Lesson: capture-replay differential authz fuzzing (M3 v0.1)
Date: 2026-06-30 | Origin: M3 capability build (~/bounty/tools/authz-diff-fuzzer/)
The arm
Autorize-style capture-replay IDOR/BAC fuzzer. Two sessions (attacker + victim) + the
victim's captured requests -> replay each victim request under the attacker (and anon) -> flag
attacker-gets-2xx / attacker-gets-victim-bytes where deny was expected. Stdlib-only, single file.
When to reach for it (vs the source-guided ~/bounty/fuzzer-arm)
fuzzer-arm = spec-driven: enumerates OpenAPI/GraphQL/tRPC, provisions identities. Reaches what the spec describes.
authz-diff-fuzzer = capture-driven: replays proxy/HAR traffic cross-session, no source. Reaches custom/undocumented routes a spec misses (SPA XHR, hidden params).
- They are complementary. On a real self-hosted multi-tenant target, run BOTH.
Reusable rules banked
- Victim-baseline-then-replay is the crisp IDOR confirmation: capture the victim's own
success (status + body hash) FIRST, then a cross-user body-hash equality = attacker got
the victim's exact bytes = high-confidence IDOR (very low FP).
- Differential authz has an irreducible shared-vs-private ambiguity. A shared-by-design
team/public resource ALSO shows attacker-gets-victim-bytes. Pure black-box cannot separate
it from a real IDOR (Autorize has the same limit). Tool surfaces + ranks; human judges intent.
Mitigate with a configurable body content-tell (
shared_markers -> NEEDS-HUMAN-SHARED), not a hard claim.
- Writes off by default. A write 2xx on a victim object is the highest-severity signal
(
CONFIRMED-WRITE-BAC), but only replay writes on a disposable instance (--allow-writes),
and ideally re-read as victim to prove the mutation landed (v0.2 --confirm-writes).
- Anon as a third lane escalates severity for free: anon 2xx on a victim object = unauth IDOR.
- Surface INVALID-BASELINE loudly: if the victim's own request doesn't 2xx, the template is
junk - don't silently treat a 404-for-everyone as "scoped-ok".
- Build a bespoke tiny practice target for v0.1 capability validation (vuln + guarded
sibling + shared-by-design, one file) instead of a heavy docker stack - gives perfect
TP/TN/ambiguous controls at zero infra cost.
Validation
3/3 TP caught (2 read-IDOR + 1 write-BAC, write genuinely mutated victim state), 3/3 TN cleared,
shared-by-design correctly downgraded. 0 false-CONFIRMED, 0 false-clear.
Report: ~/bounty/reports/2026-06-30-m3-authz-fuzzer-v01.md.
Next (v0.2)
Capture ingestion (Caido/Burp/HAR -> requests.json) is the top usability win; then auto-harvest
victim ids from list responses; then promote to a discoverable Skill.