क्रॉस-साइट रिक्वेस्ट फ़ोर्जरी (CSRF)

Cross-site request forgery (CSRF) एक ऐसा attack है जो logged-in user के browser से एक state-changing request भिजवा देता है जो user ने चाही ही नहीं थी। चूँकि browser session cookie अपने-आप जोड़ देता है, इसलिए सिर्फ़ cookie पर भरोसा करने वाला application forged request और असली request में फ़र्क नहीं कर पाता। उदाहरण: जब user किसी store में logged in है, तब दूसरी site का एक page चुपचाप store के change-email URL पर एक form submit कर देता है; अगर store सिर्फ़ cookie जाँचता है, तो email address बदल जाता है।

CSRF सिर्फ़ उन्हीं actions के लिए मायने रखता है जो state बदलते हैं और उन credentials पर निर्भर हैं जिन्हें browser अपने-आप भेजता है, जैसे session cookies और HTTP Basic auth। इस lesson के सारे defences और सारे tests एक ही विचार पर टिके हैं: यह सबूत कि request application के अपने pages से आई है, न कि सिर्फ़ यह सबूत कि user logged in है।

यह क्यों ज़रूरी है

सफल CSRF victim की ओर से data बदल देता है या action चला देता है: बदला हुआ email या password account takeover तक ले जा सकता है, और पैसे या settings बिना सहमति के बदल सकते हैं। User ने कुछ गलत नहीं किया और उसे कुछ दिखता भी नहीं, इसलिए बाद में इसे पकड़ना मुश्किल है।

ये defects हर functional test पास कर जाते हैं, क्योंकि सामान्य journey तो चलती है। ये सिर्फ़ उन्हीं tests में दिखते हैं जो इनके लिए लिखे गए हों, और वे tests सस्ते हैं: एक capture की हुई request, एक test account और उसे replay करने वाला एक tool। Release से पहले एक missing या बिना-जाँचा token पकड़ लेना account takeover का एक ऐसा रास्ता बंद करता है जिससे users खुद अपना बचाव नहीं कर सकते।

Forged request कैसे काम करती है

CSRF के लिए तीन चीज़ों का एक साथ होना ज़रूरी है। पहली: एक ऐसा action जो state बदले, जैसे email बदलना, पैसे transfer करना या data delete करना। दूसरी: ऐसी session handling जो उन credentials पर चले जिन्हें browser खुद भेजता है, ताकि attacker के page को उन्हें जानने की ज़रूरत न पड़े। तीसरी: ऐसे request parameters जिन्हें attacker पहले से भाँप सके; अगर request की हर value guess की जा सकती है, तो page उसे पहले से बना सकता है।

Attacker न session तोड़ता है और न कभी response देखता है। Victim जो page खोलता है — कोई advert, forum post, या remote content वाला email — वह victim के browser से target application की ओर request भिजवा देता है। Browser अपने सामान्य नियमों के अनुसार उस site की cookies जोड़ देता है। Server को एक well-formed, authenticated request मिलती है और जब तक वह cookie से ज़्यादा कुछ नहीं माँगता, वह उसे पूरा कर देता है। यही वजह है कि दूसरी site का page, जो target से कुछ भी पढ़ नहीं सकता, फिर भी वहाँ एक action करा सकता है।

  • अपने-आप submit होने वाला एक hidden form जो POST भेजे, classic carrier है; एक <img> या एक link GET ले जा सकता है।
  • Attacker को न XSS चाहिए और न target पर कोई script: CSRF browser के अपने behaviour पर सवार होता है, और यही इसे पिछले lesson के cross-site scripting (XSS) से अलग करता है।
  • चूँकि attacker response पढ़ नहीं सकता, इसलिए CSRF action करवाने के बारे में है, data चुराने के बारे में नहीं — यही फ़र्क हर test को आकार देता है।
Forged change-email request उस session cookie पर सवार होती है जिसे browser खुद जोड़ता है; session से बँधा token, जिसे cross-site page पढ़ नहीं सकता, server से उसे reject करवाता है।
  • सिर्फ़ cookie की जाँच

    • Victim का browser app.example में signed in
    • दूसरी site का page attacker.example
    • Target application app.example
    1. 1 Victim का browser से Target application तक: Sign in करें; reply session cookie सेट करती है Set-Cookie: sid=9f8a…
    2. 2 Victim का browser से दूसरी site का page तक: दूसरी site का page खोलें: कोई advert या forum post
    3. 3 दूसरी site का page से Victim का browser तक: Hidden form जो खुद को app.example पर submit करता है जवाब POST /account/email
    4. 4 Victim का browser से Target application तक: Forged request; browser cookie खुद जोड़ देता है Cookie: sid=9f8a…
    5. 5 Target application से Victim का browser तक: सिर्फ़ cookie जाँची जाती है: e-mail बदल जाता है जवाब Attacker यह reply कभी नहीं देखता और उसे ज़रूरत भी नहीं 200 OK फ़ेल

    परिणाम: Cookie ने साबित किया कौन; किसी चीज़ ने नहीं साबित किया कि request कहाँ से आई। फ़ेल

  • Server पर token की जाँच

    • Victim का browser app.example में signed in
    • दूसरी site का page attacker.example
    • Target application app.example
    1. 1 Victim का browser से Target application तक: Sign in करें; cookie सेट होती है और app के अपने forms में session से बँधा token होता है sid=9f8a… token=7bQ2…
    2. 2 Victim का browser से दूसरी site का page तक: दूसरी site का page खोलें: कोई advert या forum post
    3. 3 दूसरी site का page से Victim का browser तक: Token के बिना hidden form: दूसरी site उसे पढ़ नहीं सकती जवाब POST /account/email
    4. 4 Victim का browser से Target application तक: Forged request; browser cookie खुद जोड़ देता है Cookie: sid=9f8a…
    5. 5 Target application से Victim का browser तक: Token missing: कुछ भी बदलने से पहले reject जवाब Cookie पर SameSite और Origin check दो और layers हैं 403 Forbidden पास

    परिणाम: Cookie साबित करती है user कौन है; token साबित करता है कि request application के अपने page से आई। पास

तीन defences: token, SameSite और Origin

Classic मुख्य defence है anti-CSRF token: एक unpredictable value जिसे server user की session से बाँधता है और हर page के forms में रखता है। असली form उसे वापस भेजता है; cross-site page उसे पढ़ नहीं सकता, इसलिए उसे शामिल नहीं कर सकता। Synchronizer token pattern अपेक्षित value server-side रखता है; double-submit pattern उसे एक cookie और request दोनों में भेजकर मिलाता है, जिसमें server state नहीं चाहिए पर ऐसी value इस्तेमाल होनी चाहिए जिसे server sign करे और session से बाँधे, ताकि cookie plant कर लेने वाला attacker भी matching जोड़ी न बना सके। दोनों हाल में server को request तब reject करनी चाहिए जब token गायब या गलत हो — मौजूद पर कभी न जाँचा गया token कुछ नहीं बचाता।

Session cookie पर SameSite दूसरी परत है। Strict या Lax browser को ज़्यादातर उन requests के साथ cookie जोड़ने से रोकती है जो दूसरी site से शुरू होती हैं, जिससे सीधा forged form रुक जाता है। इसे defence in depth मानें, token का विकल्प नहीं: Lax फिर भी दूसरी site से top-level GET navigation पर cookie भेजती है, और defaults browsers के बीच अलग होते हैं, इसीलिए HTTP cookies और sessions वाला lesson उम्मीद करता है कि यह attribute explicitly set हो।

तीसरी परत है Origin header, और fallback के तौर पर Referer: state-changing request पर server पुष्टि करता है कि origin उसका अपना है। Browsers cross-origin requests में Origin जोड़ते हैं और page उसे बदल नहीं सकता, इसलिए mismatch reject करने का मज़बूत कारण है; फिर भी यह header गायब या null हो सकता है, इसलिए server को यह भी तय करना होता है कि तब क्या हो। OWASP की Cross-Site Request Forgery Prevention Cheat Sheet इस जाँच को, SameSite की तरह, defence in depth में रखती है। आज के browsers Sec-Fetch-Site (जैसे cross-site) भी भेजते हैं, जिसे यही cheat sheet modern browsers के लिए मुख्य जाँच मानती है, बशर्ते Origin fallback हो। इनमें से कुछ भी CORS नहीं है, जो यह तय करता है कि page क्या पढ़ सकता है: दूसरी site से एक सीधा form post CORS headers चाहे जो हों, server तक पहुँच जाता है, इसीलिए CORS वाले lesson ने कहा कि CORS कोई CSRF defence नहीं है।

आज़माएँ: कुकी एनालाइज़र

Worked example: change-email action का टेस्ट

एक ऐसा sandbox application लें जो आपका हो या जिसे टेस्ट करने की आपके पास लिखित अनुमति हो। एक test account से sign in करें और account email बदलने वाली request capture करें — intercepting proxy से, जैसा intercepting proxies वाले lesson में किया था, या browser के developer tools से। नीचे की capture की गई request एक session cookie और एक token ले जाती है।

अब एक बार में एक चीज़ बदलकर उसे replay करें — proxy के replay feature से, या REST API Tester में या एक cURL command के रूप में उसे दोबारा बनाकर — और response तथा stored email देखें। हर replay एक साफ़ expected result वाला test case है। Replay यह टेस्ट करता है कि server क्या जाँचता है; यह नहीं दिखा सकता कि browser क्या भेजता, इसीलिए SameSite को अलग से Set-Cookie header पर जाँचा जाता है।

  • X-CSRF-Token हटाकर replay करें: rejection (जैसे 403) और email unchanged की उम्मीद रखें। अगर succeed हो जाए, तो action में token check नहीं है।
  • Token की जगह दूसरे test account की session का valid token रखकर replay करें: rejection की उम्मीद रखें। अगर succeed हो, तो token session से बँधा नहीं है।
  • Valid token रहने दें, Origin को किसी दूसरी site में बदलकर replay करें: rejection दिखाता है कि server origin भी जाँचता है; accept होने का मतलब है कि token ही अकेली परत है, जिसे आप observation के रूप में दर्ज करते हैं, failed result के रूप में नहीं।
  • Login का Set-Cookie Cookie Analyzer में paste करें और पुष्टि करें कि session cookie SameSite explicitly सेट करती है।
  • ऐसा कोई action ढूँढें जो GET से पहुँचे और state बदले: वह अपने-आप में एक defect है, क्योंकि SameSite=Lax भी link follow करने पर cookie भेज देती है।
POST /account/email HTTP/1.1
Host: app.example
Origin: https://app.example
Cookie: sid=9f8aUq0Zr8Ty2Nc6
X-CSRF-Token: 7bQ2mK9rLp4XwZ1
Content-Type: application/x-www-form-urlencoded

email=sara%40app.example

आज़माएँ: REST API टेस्टर आज़माएँ: cURL जनरेटर आज़माएँ: रिक्वेस्ट हेडर इंस्पेक्टर

हर release के लिए दोहराने-योग्य CSRF test

Worked example को एक checklist में बढ़ाएँ। Feature की हर state-changing request लिखें; हर एक के लिए दर्ज करें: क्या token ज़रूरी है, क्या वह unpredictable और session-bound है, क्या server उसे जाँचता है, और क्या Origin या Referer validate होते हैं। Token body या किसी header में जाना चाहिए, कभी query string में नहीं, जहाँ वह Referer header, server logs और browser history से leak होता है।

उन जाँचों पर ध्यान दें जो सिर्फ़ page की अपनी JavaScript में चलती हैं, जिनसे forged request कभी गुज़रती ही नहीं, उन tokens पर जो reflect तो होते हैं पर verify नहीं, और उन GET endpoints पर जो चुपचाप state बदलते हैं। RFC 9110 GET को एक safe method मानता है, जिसका अर्थ मूल रूप से read-only है, इसलिए GET के पीछे state बदलना CSRF पर विचार करने से पहले ही एक defect है। Request, आपने क्या बदला और response — सब ठीक-ठीक दर्ज करें, ताकि developer एक ही step में finding reproduce कर सके।

आज़माएँ: HTTP हेडर पार्सर

आम गलतियाँ

  • सिर्फ़ यह टेस्ट करना कि valid request चलती है, और token हटाकर या बदलकर उसे replay कभी न करना।
  • मौजूद token को passing result मान लेना — test यह है कि क्या server missing या गलत token वाली request को reject करता है।
  • सिर्फ़ SameSite पर भरोसा करना, और भूल जाना कि Lax फिर भी दूसरी site से top-level GET navigation पर cookie भेजती है।
  • CSRF को XSS या CORS से गड्डमड्ड करना: XSS site के अपने origin में script चलाता है और token पढ़ सकता है, और CORS सिर्फ़ यह तय करता है कि page क्या पढ़ सकता है, यह नहीं कि action चलेगा या नहीं।
  • CSRF token को URL में रखना, जहाँ वह Referer header, server logs और browser history से leak होता है।
  • State बदलने वाले actions को GET requests पर छोड़ देना, जिन्हें forms के token अनुशासन से कोई नहीं बचा सकता।

QA का नज़रिया

Team में CSRF test बनने से पहले एक review सवाल है। जब कोई नया form या endpoint आता है, tester पूछता है कि वह कैसे protected है — token, SameSite, या origin check — और developer के साथ expected rejection तय कर लेता है, ताकि test का एक साफ़ oracle हो। जवाब test case में लिखे जाते हैं, याद में नहीं।

Testing हमेशा ऐसे system पर होती है जो आपका हो या जिसे टेस्ट करने की लिखित अनुमति हो, test account और non-destructive values के साथ; आप पुष्टि कर रहे हैं कि एक defence मौजूद है और लागू है, किसी पर हमला नहीं कर रहे। Finding में request, वह एकमात्र बदलाव जो accept हुआ, और response लिखा जाता है; बिना काम करने वाले token check के account बदलने वाला action आम तौर पर high severity माना जाता है, क्योंकि वह account takeover तक ले जा सकता है।

अभ्यास

तय करें कौन-सी requests CSRF के लिए exposed हैं

आपका काम

नीचे एक banking sandbox की चार requests हैं जहाँ user session cookie के साथ logged in है। हर एक के लिए तय करें कि क्या वह जैसी है वैसे CSRF के लिए exposed है, missing defence का नाम बताएँ, और दूसरी origin से उसे replay करने का expected result लिखें।

मानें कि session cookie अपने-आप भेजी जाती है और कोई Origin check नहीं है जब तक कोई request उसे न दिखाए।

सामग्री
1  GET /transfer?to=ACME&amount=500 HTTP/1.1
   Cookie: sid=Zc4Hn8Tq1Wy6Bd3F

2  POST /transfer HTTP/1.1
   Cookie: sid=Zc4Hn8Tq1Wy6Bd3F
   Content-Type: application/x-www-form-urlencoded

   to=ACME&amount=500

3  POST /transfer HTTP/1.1
   Cookie: sid=Zc4Hn8Tq1Wy6Bd3F
   X-CSRF-Token: Lm8Vb3Nk7Xr5Tq2

   to=ACME&amount=500

4  POST /profile/theme HTTP/1.1
   Cookie: sid=Zc4Hn8Tq1Wy6Bd3F

   theme=dark
चरण
  1. हर request के लिए: क्या action state बदलता है?
  2. क्या वह unpredictable, session-bound token ले जाती है जिसे server जाँचेगा?
  3. क्या दूसरी site cookie जुड़ी हुई यह request करा सकती है?
  4. Defence लागू होने के बाद expected result लिखें।
मॉडल उत्तर दिखाएँ
मॉडल उत्तर

Request 1 सबसे बुरी है: यह GET से state बदलती है, इसलिए किसी भी site का एक link या <img> इसे trigger कर देता है, और SameSite=Lax भी link follow करने पर cookie भेज देती है। इसे POST पर ले जाएँ और token जोड़ें; fix के बाद expected result: दूसरी origin से rejected।

Request 2 POST पर state बदलती है पर कोई token नहीं ले जाती, इसलिए दूसरी site का hidden auto-submitting form succeed कर जाता है। एक session-bound token जोड़ें जिसे server जाँचे; expected result: valid token के बिना 403।

Request 3 एक header में token ले जाती है। अगर server उसे session से मिलाता है तो यह protected है, क्योंकि cross-site page token पढ़कर उसे शामिल नहीं कर सकता। Test यह है कि token हटाकर, और फिर दूसरी session के token के साथ replay करें और दोनों का rejection पक्का करें।

Request 4 एक low-risk setting बदलती है पर request 2 की तरह ही CSRF-exposed है; theme किसी भी ऐसे logged-in user के लिए पलटी जा सकती है जो attacker का page खोले। Severity कम है, शून्य नहीं। इसे उसी तरह protect करें, और ध्यान दें कि किसी action का कम impact severity की बात है, इस बात की नहीं कि defence चाहिए या नहीं।

अक्सर पूछे जाने वाले सवाल

अब जब कुछ browsers cookies को default रूप से SameSite=Lax कर देते हैं, तो क्या CSRF अब भी relevant है?

हाँ। Defaults browsers और versions के बीच अलग होते हैं, Lax अब भी top-level GET navigation की अनुमति देती है, और कुछ applications legitimate cross-site ज़रूरतों के लिए SameSite=None सेट करते हैं। OWASP cheat sheet अब भी मुख्य defence के रूप में server-side जाँच, आम तौर पर token, माँगती है और SameSite को defence in depth मानती है।

CSRF और XSS में क्या फ़र्क है?

XSS attacker की script को site के अपने origin में चलाता है, इसलिए वह page, token और response पढ़ सकता है; CSRF target पर कोई script नहीं चलाता और response नहीं पढ़ सकता — यह सिर्फ़ एक action करवाता है। एक XSS flaw CSRF tokens को हरा सकता है, इसीलिए दोनों टेस्ट किए जाते हैं।

जो REST APIs एक header में bearer token इस्तेमाल करती हैं, क्या उन्हें CSRF protection चाहिए?

अगर API सिर्फ़ उस token से authenticate करती है जिसे client हर request में जोड़ता है — न कि उस cookie से जिसे browser अपने-आप भेजता है — तो वह classic CSRF के लिए exposed नहीं है, क्योंकि browser वह token खुद कभी नहीं जोड़ता और दूसरी site का page उसे पढ़ नहीं सकता। जो API session cookie स्वीकार करती है वह exposed है और उसे वही defences चाहिए।

क्या मैं सीखने के लिए किसी भी site पर CSRF टेस्ट कर सकता हूँ?

नहीं। सिर्फ़ उन्हीं systems को टेस्ट करें जो आपके हों या जिन्हें टेस्ट करने की आपके पास लिखित अनुमति हो, test account और non-destructive values के साथ। किसी और के application के खिलाफ़ requests forge करना एक attack है, नीयत चाहे जो हो।

संदर्भ

  • OWASP Cheat Sheet Series: Cross-Site Request Forgery PreventionOWASP FoundationCSRF से बचाव: सिंक्रोनाइज़र टोकन, SameSite कुकी और ऑरिजिन जाँच।
  • OWASP Web Security Testing Guide (WSTG)OWASP Foundationवेब एप्लिकेशन और API की सुरक्षा कमज़ोरियों को परखने की संदर्भ कार्यप्रणाली, एक-एक टेस्ट के रूप में।
  • Using HTTP cookies — MDNMDN Web Docs (Mozilla)कुकी की अवधि, स्कोप, Secure/HttpOnly/SameSite एट्रिब्यूट और उनके सुरक्षा निहितार्थ।
  • RFC 9110: HTTP SemanticsIETF · 2022HTTP मेथड, हेडर फ़ील्ड, स्टेटस कोड और कंटेंट निगोशिएशन के अर्थ, वायर वर्ज़न से स्वतंत्र।

Mutqan tools से अभ्यास करें

Set-Cookie हेडर पार्स करें और Secure, HttpOnly, SameSite, Domain, Path, एक्सपायरी तथा साइज़ की सर्वोत्तम प्रथाएँ जाँचें।

वैलिडेशन

कच्चे HTTP रिक्वेस्ट/रिस्पॉन्स हेडर को व्याख्या सहित एक संरचित तालिका में बदलें।

वेब

method, हेडर और JSON बॉडी पर पूरे नियंत्रण के साथ REST endpoint टेस्ट करें, फिर स्टेटस, हेडर और JSON path पर assertion लगाएँ।

API टेस्टिंग

मेथड, URL, हेडर, बॉडी और auth विकल्पों से cURL कमांड बनाएँ।

वेब

और गहराई से

इस topic में आपकी प्रगति

QA रोडमैप का हिस्सा