Manchmal verarbeiten Webseiten verschiedene Anfragen, ohne passende Sicherheitsmaßnahmen. Das kann dazu führen, dass Daten von mehreren Threads zur gleichen Zeit bearbeitet werden. Dadurch können kollisionen entstehen. ![[Pasted image 20240515172419 1.png]]
-
Mehrfaches senden ohne Anpassungen
Bei einer einfachen Race Condition, also wo lediglich ein Request mehrfach verschickt werden muss kannrace-single-packet-attack.pyaus den Beispielen genutzt werden. Statt dem Turbo Intruder kann auch der Repeater genutzt werden. Dazu wird eine Gruppe erstellt mit dem Request. Dieser Request wird dann dupliziert und die Gruppe wird in parallel verschickt. - Ensure that the target supports HTTP/2. The single-packet attack is incompatible with HTTP/1.
- Set the
engine=Engine.BURP2andconcurrentConnections=1configuration options for the request engine. - When queueing your requests, group them by assigning them to a named gate using the
gateargument for theengine.queue()method. - To send all of the requests in a given group, open the respective gate with the
engine.openGate()method. -
Mehrfaches Senden unterschiedlicher Anfragen
#TODO In race conditions "Single-endpoint race conditions" verstehe ich nicht richtig Das Senden von Parallelen Anfragen zu einem einzigen Endpunkt, kann auch Race Conditions auslösen. -
Senden an mehrere Endpunkte
Es kann auch sein, dass es nötig ist an verschiedene Endpunkte Anfragen zu machen, um die Race Condition auszunutzen. Beispielsweise im folgenden Bild ist zu sehen, wie ein Artikel gekauft wird. Nachdem der Bezahlvorgang ausgeführt wird, gibt es eine Validierung der Bezahlung und danach wird der Einkaufskorb validiert. Während der Validierung der Bezahlung existiert ein Zeitfenster um den Einkaufswagen zu ändern und zusätzliche Artikel hinzuzufügen. ![[Pasted image 20240517150010 1.png]] -
Aufwärmen der Verbindungen
Manchmal kann es vorkommen, dass es zu verzögerungen durch das Netzwerk kommt. Dafür können Requests vorrausgeschickt werden, damit diese Verzögerungen die Ergebnisse nicht beeinflussen. Manchmal verlangsamen Webserver die Verbindungen auch, wenn zu viele Verbindungen eintreffen, dies kann ausgenutzt werden für die Race Conditions. -
Session basierte sperr Mechanismen
Es kann sein, dass es einen Schutz gibt gegen race conditions durch das verhindern innerhalb sessions. Dies ist beispielsweise beim PHP nativen Session handler der Fall. Das Absenden dieser Requests von unterschiedlichen Sessions, kann dies umgehen. -
Partial construction race conditions
Manche Anwendungen kreirren Objekte in mehreren Schritten. Das kann dazu führen, dass es einen Mittelzustand gibt, indem das Objekt verwundbar ist. Dies kann beispielsweise passieren, wenn ein neuer Nutzer angelegt wird und im zweiten Schritt ein API Key erstellt wird. Dies kann dazu führen, dass es möglich ist in die Datenbank ein Eingabewert zu injizieren, welcher mit dem nicht initialisierten Wert übereinstimmt. Frameworks lassen oft arrays und nicht string datenstrukturen mit nicht standardsyntax zu. Beispielsweise PHP: param[]=fooist äquivalent zuparam = ['foo']param[]=foo¶m[]=barist äquivalent zuparam = ['foo', 'bar']param[]ist äquivalent zuparam = []Bei Ruby on Rails ist es ähnlich.param[key]resultiert in dem folgenden Server seitigem Objekt:params = {"param"=>{"key"=>nil}}-
Zeit sensitive Attacken
Manchmal gibt es keine race conditions, aber präzises timing kann Schwachstellen enthüllen. Dies kann der Fall sein, wenn ein Security Token mit einem Timestamp erstellt wird. Daher kannn es nützlich sein Requests zur gleichen Zeit zu senden -
Engines von Turbo Intruder
Engine.HTTP2 Engine.THREADED Engine.BURP2 Engine.BURP -
Feintunning
Wortlisten sollten nicht vorgeladen werden, sondern gestreamt werden:for word in open('/usr/share/dict/words'): engine.queue(target.req, word.rstrip()) -
Bereits gesehene Wörter als Wortliste
# list of all words observed during passive scans for word in wordlists.observedWords: engine.queue(target.req, word) -
Mehrere Parameter
Parameter können im Request mit%sangegeben werden.for firstWord in open('/usr/share/dict/words'): for secondWord in open('/usr/share/dict/american-english'): engine.queue(target.req, [firstWord.rstrip(), secondWord.rstrip()]) -
Filtern von Antworten
Die Antworten werden nicht automatisch gespeichert, sie müssen hinzugefügt werden.`def handleResponse(req, interesting): if '200 OK' in req.response: table.add(req)` -
Antwort Decorators
Die Decorator werden von oben nach unten abgearbeitet.
| Zweck | Beispiel | |
|---|---|---|
| Anzeige der Response Codes | @MatchStatus(200,204) |
|
| Response Codes nicht anzeigen | @FilterStatus(200,204) |
|
| Zeigt Antworten mit der spezifizierten Größe | @MatchSize(555) |
|
| Zeigt Antworten die nicht der Größe entsprechen | @FilterSize(555) |
|
| Zeigt nur Antworten in der Reichweite der größe | @MatchSizeRange(100,1000) |
|
| Zeigt Antworten außerhalb der größe | @FilterSizeRange(100,1000) |
|
| Nur wenn bestimmter Regex auftritt | @MatchRegex(r".*Set-Cookie.*") |
|
| Nur wenn Regex nicht vorkommt | @FilterRegex(r".*Not Found.*") |
|
| Anzeige wenn Antwort Anzahl der Wörter enthält | @MatchWordCount(3) |
|
| Anzeige wenn wort Anzahl nicht stimmt | @FilterWordCount(3) |
|
| Anzahl der Wörter in Reichweite | @MatchWordCountRange(3, 6) |
|
| Anzahl der Wörter nicht in Reichweite | @FilterWordCountRange(3,6) |
|
| Anzahl der Zeilen | @MatchLineCount(1, 2, 3) |
|
| @FilterLineCount(LineCount, ...) | @FilterLineCount(LineCount, ...) |
|
| @MatchLineCountRange(min, max) | @MatchLineCountRange(min, max) |
|
| @FilterLineCountRange(min, max) | @FilterLineCountRange(min, max) |
|
| Zeigt nur n Antworten bestimmter Größe | @UniqueSize(instances=n) |
|
| Zeigt nur n Antworten mit bestimmter Wort Anzahl | @UniqueWordCount(instances=n) |
|
| Zeigt nur n Antworten mit gleicher Zeilenanzahl | @UniqueLineCount(instances=n) |
|
| - ## Quellen | ||
| https://book.hacktricks.xyz/pentesting-web/race-condition |