diff --git a/README.md b/README.md index 5150551..95780be 100755 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - + @@ -44,7 +44,7 @@ LLMs** — via **API key** or local **subscription** (Claude Code / Codex / Gemi Grok) — recons the target, **intelligently selects only the agents that match the discovered surface**, runs them in parallel, **chains** findings into deeper impact, and **validates every claim by cross-model voting + tool-receipt -grounding** before reporting. It ships **375 markdown agents** and a **Mission +grounding** before reporting. It ships **383 markdown agents** and a **Mission Control TUI**. ### Engagement modes diff --git a/RELEASE.md b/RELEASE.md index 1d3d0e0..95e0b8a 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -102,6 +102,25 @@ interactive line-editing. - **Rate-limit testing** is a first-class control check (small non-disruptive burst → look for 429/lockout/Retry-After), never a DoS. +## Browser-driven testing & SPA agents (Juice Shop-ready) + +- **Agents now actively drive the browser while testing.** The tool doctrine was + strengthened: on JS-heavy / SPA (Angular/React/Vue) targets the agent MUST use + the **Playwright MCP** browser (render, wait, read the live DOM, click + client-side routes, watch the network to discover the real REST/GraphQL API, + prove client-side issues with a screenshot). When no MCP is present, it uses the + **Playwright CLI** (writes & runs a small `playwright` script / `npx playwright + screenshot`) to render and capture the app's XHR/fetch traffic — **complementing + curl**, which only sees the empty shell. +- **Deterministic probe detects SPAs** (``, `ng-version`, near-empty + body + linked scripts → Angular/React/Vue/SPA) and flags in recon that the + browser is required — so the SPA agents get selected. +- **+8 SPA/API agents** (library **383**): SPA API & route discovery, hidden-admin / + client-side access control, login SQLi bypass, SPA DOM XSS, API BOLA via + sequential IDs, privileged registration / mass assignment, JWT forgery & + verification bypass, and SPA business-logic abuse — tuned for apps like OWASP + Juice Shop. (Existing NoSQLi/GraphQL/JWT/mass-assignment agents complement them.) + ## Subscription login check & Playwright MCP fixes - **Subscription login preflight.** Before a `--subscription` run, the harness diff --git a/TUTORIAL.md b/TUTORIAL.md index 8f6dd58..7d865f7 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -40,7 +40,7 @@ You give NeuroSploit a **target** (URL, repo, app, or host/IP). It: 1. **Recons** the target with real tools (curl/nmap/…). 2. **Intelligently selects** only the agents whose preconditions match the recon - (it does *not* blindly run all 375). + (it does *not* blindly run all 383). 3. **Exploits** in parallel — each agent works in a ReAct loop and must prove its claim with a **tool receipt** (raw output). 4. **Validates** every candidate by **cross-model voting** (a different model @@ -99,7 +99,7 @@ Agents **degrade gracefully**: if `rustscan` is absent they use `nmap`; if neith ```bash neurosploit --version # neurosploit 3.5.5 -neurosploit agents # {"vulns":196,...,"chains":12,"total":375} +neurosploit agents # {"vulns":196,...,"chains":12,"total":383} neurosploit models # all providers & models ``` @@ -535,7 +535,7 @@ built from SAST/dataflow), so uncertainty becomes *path reachability*, not state ## 13. The agent library -`agents_md/` holds **375** markdown agents in categories: +`agents_md/` holds **383** markdown agents in categories: | Category | Dir | Count | Purpose | |----------|-----|-------|---------| diff --git a/agents_md/vulns/api_bola_numeric_ids.md b/agents_md/vulns/api_bola_numeric_ids.md new file mode 100644 index 0000000..386bafa --- /dev/null +++ b/agents_md/vulns/api_bola_numeric_ids.md @@ -0,0 +1,39 @@ +# API BOLA via Sequential IDs Agent + +## User Prompt +You are testing **{target}** for broken object level authorization on numeric API IDs. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Capture own IDs +- As a low-priv user, capture the numeric IDs of your own objects (basket, order, user, review) from the API + +### 2. Cross-access +- Change the ID to another user's (id-1, id+1, enumerate) on GET/PUT/DELETE and see if you reach their object +- Also try the object under a different collection (e.g. /api/Users/{id}, /rest/basket/{id}) + +### 3. Confirm +- Show reading or modifying another user's object; prove with the two requests (yours vs theirs). Mask PII + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: API BOLA via Sequential IDs at [route/endpoint] +- Severity: High +- CWE: CWE-639 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Cross-user data read/modification +- Remediation: Authorize every object access against the session user server-side; use unguessable IDs +``` + +## System Prompt +You are a specialist in broken object level authorization on numeric API IDs on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/dom_xss_spa.md b/agents_md/vulns/dom_xss_spa.md new file mode 100644 index 0000000..4f2026a --- /dev/null +++ b/agents_md/vulns/dom_xss_spa.md @@ -0,0 +1,38 @@ +# SPA DOM-Based XSS Agent + +## User Prompt +You are testing **{target}** for DOM-based XSS via client-side sinks in a JS SPA. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Find sinks +- From rendered pages and JS, find inputs reflected into the DOM via dangerous sinks (innerHTML, bypassSecurityTrust*, v-html, dangerouslySetInnerHTML, location/hash handlers) + +### 2. Fire it +- Deliver a payload through the URL fragment/search or an input (e.g. #/search?q=) and CONFIRM script execution IN THE BROWSER (dialog/DOM change/JS callback), with a screenshot + +### 3. Scope +- Note reflected vs stored, and whether it needs interaction + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: SPA DOM-Based XSS at [route/endpoint] +- Severity: High +- CWE: CWE-79 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Session/token theft, account takeover, UI redress +- Remediation: Contextual output encoding; framework auto-escaping; avoid bypassSecurityTrust/innerHTML; CSP +``` + +## System Prompt +You are a specialist in DOM-based XSS via client-side sinks in a JS SPA on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/jwt_forgery_spa.md b/agents_md/vulns/jwt_forgery_spa.md new file mode 100644 index 0000000..45092eb --- /dev/null +++ b/agents_md/vulns/jwt_forgery_spa.md @@ -0,0 +1,38 @@ +# JWT Forgery & Verification Bypass Agent + +## User Prompt +You are testing **{target}** for forgeable/weak JWT accepted by the API. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Grab a token +- Log in (browser or API) and capture the JWT the SPA stores/sends (Authorization/cookie) + +### 2. Attack the signature +- Test alg:none (strip signature), RS→HS confusion (sign with the public key as HMAC secret), and weak HS256 secret cracking; forge a token with elevated claims (e.g. admin email/role) + +### 3. Confirm +- Show the forged token is ACCEPTED by an authenticated API endpoint (server didn't verify properly) + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: JWT Forgery & Verification Bypass at [route/endpoint] +- Severity: Critical +- CWE: CWE-347 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Authentication bypass / account takeover +- Remediation: Verify signature with a strong secret/correct alg; pin the algorithm; reject alg:none +``` + +## System Prompt +You are a specialist in forgeable/weak JWT accepted by the API on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/login_sqli_bypass.md b/agents_md/vulns/login_sqli_bypass.md new file mode 100644 index 0000000..2c72430 --- /dev/null +++ b/agents_md/vulns/login_sqli_bypass.md @@ -0,0 +1,38 @@ +# Authentication SQLi Bypass Agent + +## User Prompt +You are testing **{target}** for SQL injection in the login/auth flow to bypass authentication. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Locate login +- Identify the login API the SPA calls (watch the network on a login attempt) + +### 2. Inject +- Try auth-bypass payloads in the identifier field, e.g. `' OR 1=1--`, `admin'--`, `' OR '1'='1`; observe whether a session/JWT is issued without valid credentials + +### 3. Confirm +- Show a token/session returned for an injected credential, then use it to reach an authenticated resource + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: Authentication SQLi Bypass at [route/endpoint] +- Severity: Critical +- CWE: CWE-89 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Full authentication bypass / account takeover +- Remediation: Parameterize queries / use an ORM; never build SQL from input; generic auth errors +``` + +## System Prompt +You are a specialist in SQL injection in the login/auth flow to bypass authentication on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/register_privilege_mass_assign.md b/agents_md/vulns/register_privilege_mass_assign.md new file mode 100644 index 0000000..f678dfc --- /dev/null +++ b/agents_md/vulns/register_privilege_mass_assign.md @@ -0,0 +1,38 @@ +# Privileged Registration / Mass Assignment Agent + +## User Prompt +You are testing **{target}** for elevating privilege via extra fields on register/update. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Inspect the model +- Watch the register/profile-update API request and infer server-side fields (e.g. role, isAdmin, deluxeToken) not shown in the UI + +### 2. Inject fields +- Add the privileged field (e.g. "role":"admin") to the register/update body and submit + +### 3. Confirm +- Show the account was created/updated with the elevated attribute and can reach admin-only resources + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: Privileged Registration / Mass Assignment at [route/endpoint] +- Severity: High +- CWE: CWE-915 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Privilege escalation to admin +- Remediation: Server-side allow-list of writable fields (DTO); never bind role/permission from client input +``` + +## System Prompt +You are a specialist in elevating privilege via extra fields on register/update on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/spa_api_discovery.md b/agents_md/vulns/spa_api_discovery.md new file mode 100644 index 0000000..d15c9e4 --- /dev/null +++ b/agents_md/vulns/spa_api_discovery.md @@ -0,0 +1,42 @@ +# SPA API & Route Discovery Agent + +## User Prompt +You are testing **{target}** for mapping a JS SPA's client-side routes and backend API. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Render & watch +- Open the app in the browser, wait for it to render, and record every XHR/fetch the app makes (method, URL, body) — that reveals the real REST/GraphQL API behind the SPA + +### 2. Enumerate routes +- Extract client-side routes from the router config in the bundled JS and by navigating (e.g. #/login, #/admin, #/administration, #/score-board, #/accounting); note gated/hidden ones + +### 3. Map the API +- List each API base/path (e.g. /rest/*, /api/*, /graphql), its params, auth requirement, and shape +- Fetch and grep the JS bundles + any source maps for endpoints, params and secrets + +### 4. Handoff +- Produce a route+API map so the specialist agents know exactly where to test + +### 5. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: SPA API & Route Discovery at [route/endpoint] +- Severity: Info +- CWE: CWE-200 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Full client + API attack-surface map +- Remediation: Don't ship route/API details or source maps to prod; require auth on sensitive routes; least data +``` + +## System Prompt +You are a specialist in mapping a JS SPA's client-side routes and backend API on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/spa_business_logic.md b/agents_md/vulns/spa_business_logic.md new file mode 100644 index 0000000..4ddc44b --- /dev/null +++ b/agents_md/vulns/spa_business_logic.md @@ -0,0 +1,38 @@ +# SPA Business-Logic Abuse Agent + +## User Prompt +You are testing **{target}** for business-logic flaws in cart/checkout/coupon/workflow. + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Model the flow +- Map the multi-step flow via the browser + its API (cart → basket item → checkout → order) + +### 2. Break invariants (non-destructive) +- Test negative/zero/huge quantities, client-set prices, reusing/forging coupons, skipping steps, or tampering totals in the API request — WITHOUT completing a real fraudulent purchase or altering others' data + +### 3. Confirm +- Show the server accepted an invalid state (e.g. negative quantity, altered price) in its response + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: SPA Business-Logic Abuse at [route/endpoint] +- Severity: High +- CWE: CWE-840 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Financial loss / integrity abuse +- Remediation: Validate all invariants & prices server-side; idempotent coupons; enforce workflow order +``` + +## System Prompt +You are a specialist in business-logic flaws in cart/checkout/coupon/workflow on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/agents_md/vulns/spa_hidden_admin.md b/agents_md/vulns/spa_hidden_admin.md new file mode 100644 index 0000000..6cde072 --- /dev/null +++ b/agents_md/vulns/spa_hidden_admin.md @@ -0,0 +1,38 @@ +# Hidden Admin & Client-Side Access Control Agent + +## User Prompt +You are testing **{target}** for client-side-only access control (hidden admin/features). + +> This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, and watch the network to discover the real API. + +**Recon Context:** +{recon_json} + +**METHODOLOGY:** + +### 1. Find gated routes +- From the router/JS, find admin/privileged routes and feature flags (e.g. #/administration, score-board, accounting) that the UI hides but the router still resolves + +### 2. Navigate directly +- Browse straight to the gated route as a low-priv/anon user; if the page renders and its API calls succeed, access control is only client-side + +### 3. Confirm at the API +- Call the underlying admin API directly (curl) as the low-priv role and show it returns data/allows the action + +### 4. Report Format +For each CONFIRMED finding: +``` +FINDING: +- Title: Hidden Admin & Client-Side Access Control at [route/endpoint] +- Severity: High +- CWE: CWE-602 +- Endpoint: [route or API URL] +- Vector: [what/where] +- Payload: [exact payload/request] +- Evidence: [rendered DOM / network request+response / screenshot path proving it] +- Impact: Unauthorized admin access / privileged data & actions +- Remediation: Enforce authorization SERVER-SIDE on every route's API; never rely on hiding UI +``` + +## System Prompt +You are a specialist in client-side-only access control (hidden admin/features) on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. Report ONLY what you proved with a real receipt (rendered DOM / network request+response / screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or change state without permission; mask any PII. No destructive/DoS. Credits: Joas A Santos and Red Team Leaders. diff --git a/neurosploit-rs/crates/harness/src/pipeline.rs b/neurosploit-rs/crates/harness/src/pipeline.rs index 6328813..9961d26 100644 --- a/neurosploit-rs/crates/harness/src/pipeline.rs +++ b/neurosploit-rs/crates/harness/src/pipeline.rs @@ -51,9 +51,14 @@ fn operator_directives(cfg: &RunConfig) -> String { /// where these tools are preinstalled. fn tool_doctrine(mcp_on: bool) -> String { let browser = if mcp_on { - "A Playwright MCP browser IS available — use it for JS-heavy pages, DOM/JS execution, and to PROVE client-side issues (e.g. XSS firing); capture screenshots as evidence." + "BROWSER (Playwright MCP is available — USE IT, don't rely on curl alone): for any JS-heavy / SPA / Angular / React / Vue target, DRIVE THE REAL BROWSER — navigate, wait for the app to render, read the live DOM, click through client-side routes (e.g. #/admin, #/administration, #/score-board), submit forms, and watch the NETWORK requests the app makes to discover the real REST/GraphQL API. PROVE client-side issues (XSS actually firing, DOM sinks, auth flows) in the browser and capture a screenshot as evidence. Use curl for the API/backend calls you discover; use the browser for anything the SPA renders or executes client-side." } else { - "No browser MCP is available — use `curl` (and `wget`) for all HTTP interaction; render/inspect responses directly." + "BROWSER (no MCP — use the Playwright CLI to complement curl on JS-heavy targets): curl only sees the initial HTML (an empty SPA shell renders nothing useful). To render/interact, write a small Playwright script and run it, e.g.:\n\ + `npx -y playwright@latest install chromium >/dev/null 2>&1; cat > /tmp/pw.js <<'EOF'\n\ + const { chromium } = require('playwright');\n(async () => { const b = await chromium.launch(); const p = await b.newPage();\n\ + p.on('request', r => console.log('REQ', r.method(), r.url()));\n await p.goto(process.argv[2], {waitUntil:'networkidle'});\n\ + console.log(await p.content()); await p.screenshot({path:'/tmp/shot.png'}); await b.close(); })();\nEOF`\n\ + then `node /tmp/pw.js ` to get the rendered DOM + the XHR/fetch URLs the app calls (that reveals the real API). Use `npx playwright screenshot out.png` for quick proof. Combine with curl for the discovered API endpoints." }; format!( "TOOLING (authorized; best on Kali Linux or the kalilinux/kali-rolling Docker image):\n\ diff --git a/neurosploit-rs/crates/harness/src/probe.rs b/neurosploit-rs/crates/harness/src/probe.rs index 9f50314..a7b65c5 100644 --- a/neurosploit-rs/crates/harness/src/probe.rs +++ b/neurosploit-rs/crates/harness/src/probe.rs @@ -157,16 +157,29 @@ pub async fn probe(target: &str) -> Probe { } } // Tech hints (headers + body keywords). - let hay = format!("{} {} {} {}", p.server, p.powered_by, p.content_type, body.chars().take(20_000).collect::()).to_lowercase(); + let hay = format!("{} {} {} {}", p.server, p.powered_by, p.content_type, body.chars().take(30_000).collect::()).to_lowercase(); for (needle, tech) in [ ("wp-content", "WordPress"), ("/wp-json", "WordPress"), ("drupal", "Drupal"), ("joomla", "Joomla"), ("x-drupal", "Drupal"), ("laravel_session", "Laravel"), ("csrftoken", "Django"), ("__next", "Next.js"), - ("react", "React"), ("vue", "Vue"), ("angular", "Angular"), ("nginx", "nginx"), ("apache", "Apache"), + ("react", "React"), ("vue", "Vue"), ("nginx", "nginx"), ("apache", "Apache"), ("microsoft-iis", "IIS"), ("express", "Express"), ("phpsessid", "PHP"), ("jsessionid", "Java"), ("cloudflare", "Cloudflare"), ("swagger", "Swagger/OpenAPI"), ("graphql", "GraphQL"), + // SPA / framework markers (Juice Shop = Angular ). + ("= 2 && text_len < 3000 && !p.tech.iter().any(|t| t == "SPA") { + p.tech.push("SPA".to_string()); + } + if p.tech.iter().any(|t| t == "SPA" || t == "Angular" || t == "React" || t == "Vue") { + p.notes.push("JS-rendered SPA — curl sees the shell only; use the browser (MCP/Playwright) to render, enumerate routes, and discover the API.".to_string()); + } // CORS reflection probe. if let Ok(r2) = c.get(target).header("Origin", "https://evil.neurosploit.test").send().await { diff --git a/scripts/build_spa_agents_v355.py b/scripts/build_spa_agents_v355.py new file mode 100644 index 0000000..d43237d --- /dev/null +++ b/scripts/build_spa_agents_v355.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +""" +NeuroSploit v3.5.5 — SPA / API-driven application agents (browser-first). + +Targets modern single-page apps (Angular/React/Vue) and their REST/GraphQL +backends — e.g. OWASP Juice Shop. These agents DRIVE A REAL BROWSER (Playwright +MCP when available, else the Playwright CLI) to render the app, enumerate +client-side routes, watch the network, and prove client-side issues — then use +curl for the discovered API. Read-only-first, non-destructive, authorized only. +Credits: Joas A Santos & Red Team Leaders. +""" +import os + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +OUT = os.path.join(ROOT, "agents_md", "vulns") + +BROWSER_NOTE = ("This target is likely a JS-rendered SPA: curl sees only an empty shell, so you MUST use the " + "browser (Playwright MCP if available, otherwise a Playwright CLI script) to render and interact, " + "and watch the network to discover the real API.") + + +def render(a): + L = [f"# {a['title']} Agent\n", "## User Prompt", + f"You are testing **{{target}}** for {a['for']}.\n", + f"> {BROWSER_NOTE}\n", + "**Recon Context:**\n{recon_json}\n", "**METHODOLOGY:**\n"] + for i, (s, bs) in enumerate(a["steps"], 1): + L.append(f"### {i}. {s}") + L += [f"- {b}" for b in bs] + L.append("") + n = len(a["steps"]) + 1 + L += [f"### {n}. Report Format", "For each CONFIRMED finding:", "```", "FINDING:", + f"- Title: {a['title']} at [route/endpoint]", f"- Severity: {a['sev']}", f"- CWE: {a['cwe']}", + "- Endpoint: [route or API URL]", "- Vector: [what/where]", "- Payload: [exact payload/request]", + "- Evidence: [rendered DOM / network request+response / screenshot path proving it]", + f"- Impact: {a['impact']}", f"- Remediation: {a['fix']}", "```\n", "## System Prompt", a["system"]] + return "\n".join(L) + "\n" + + +def A(name, title, vc, cwe, sev, steps, fix, impact): + return {"name": name, "title": title, "for": vc, "sev": sev, "cwe": cwe, "impact": impact, "fix": fix, + "steps": steps, + "system": (f"You are a specialist in {vc} on modern SPA/API apps. AUTHORIZED engagement. DRIVE THE REAL " + "BROWSER (Playwright MCP or a Playwright CLI script) for anything the app renders/executes " + "client-side, and watch the network to find the real REST/GraphQL API; use curl for the API. " + "Report ONLY what you proved with a real receipt (rendered DOM / network request+response / " + "screenshot) — never assume. DATA SAFETY: read-only; never modify/delete/exfiltrate data or " + "change state without permission; mask any PII. No destructive/DoS. " + "Credits: Joas A Santos and Red Team Leaders.")} + + +AGENTS = [ + A("spa_api_discovery", "SPA API & Route Discovery", "mapping a JS SPA's client-side routes and backend API", + "CWE-200", "Info", + [("Render & watch", ["Open the app in the browser, wait for it to render, and record every XHR/fetch the app makes " + "(method, URL, body) — that reveals the real REST/GraphQL API behind the SPA"]), + ("Enumerate routes", ["Extract client-side routes from the router config in the bundled JS and by navigating " + "(e.g. #/login, #/admin, #/administration, #/score-board, #/accounting); note gated/hidden ones"]), + ("Map the API", ["List each API base/path (e.g. /rest/*, /api/*, /graphql), its params, auth requirement, and shape", + "Fetch and grep the JS bundles + any source maps for endpoints, params and secrets"]), + ("Handoff", ["Produce a route+API map so the specialist agents know exactly where to test"])], + "Don't ship route/API details or source maps to prod; require auth on sensitive routes; least data", + "Full client + API attack-surface map"), + + A("spa_hidden_admin", "Hidden Admin & Client-Side Access Control", "client-side-only access control (hidden admin/features)", + "CWE-602", "High", + [("Find gated routes", ["From the router/JS, find admin/privileged routes and feature flags (e.g. #/administration, " + "score-board, accounting) that the UI hides but the router still resolves"]), + ("Navigate directly", ["Browse straight to the gated route as a low-priv/anon user; if the page renders and its API " + "calls succeed, access control is only client-side"]), + ("Confirm at the API", ["Call the underlying admin API directly (curl) as the low-priv role and show it returns data/allows the action"])], + "Enforce authorization SERVER-SIDE on every route's API; never rely on hiding UI", + "Unauthorized admin access / privileged data & actions"), + + A("login_sqli_bypass", "Authentication SQLi Bypass", "SQL injection in the login/auth flow to bypass authentication", + "CWE-89", "Critical", + [("Locate login", ["Identify the login API the SPA calls (watch the network on a login attempt)"]), + ("Inject", ["Try auth-bypass payloads in the identifier field, e.g. `' OR 1=1--`, `admin'--`, `' OR '1'='1`; " + "observe whether a session/JWT is issued without valid credentials"]), + ("Confirm", ["Show a token/session returned for an injected credential, then use it to reach an authenticated resource"])], + "Parameterize queries / use an ORM; never build SQL from input; generic auth errors", + "Full authentication bypass / account takeover"), + + A("dom_xss_spa", "SPA DOM-Based XSS", "DOM-based XSS via client-side sinks in a JS SPA", + "CWE-79", "High", + [("Find sinks", ["From rendered pages and JS, find inputs reflected into the DOM via dangerous sinks " + "(innerHTML, bypassSecurityTrust*, v-html, dangerouslySetInnerHTML, location/hash handlers)"]), + ("Fire it", ["Deliver a payload through the URL fragment/search or an input (e.g. #/search?q=) " + "and CONFIRM script execution IN THE BROWSER (dialog/DOM change/JS callback), with a screenshot"]), + ("Scope", ["Note reflected vs stored, and whether it needs interaction"])], + "Contextual output encoding; framework auto-escaping; avoid bypassSecurityTrust/innerHTML; CSP", + "Session/token theft, account takeover, UI redress"), + + A("api_bola_numeric_ids", "API BOLA via Sequential IDs", "broken object level authorization on numeric API IDs", + "CWE-639", "High", + [("Capture own IDs", ["As a low-priv user, capture the numeric IDs of your own objects (basket, order, user, review) from the API"]), + ("Cross-access", ["Change the ID to another user's (id-1, id+1, enumerate) on GET/PUT/DELETE and see if you reach their object", + "Also try the object under a different collection (e.g. /api/Users/{id}, /rest/basket/{id})"]), + ("Confirm", ["Show reading or modifying another user's object; prove with the two requests (yours vs theirs). Mask PII"])], + "Authorize every object access against the session user server-side; use unguessable IDs", + "Cross-user data read/modification"), + + A("register_privilege_mass_assign", "Privileged Registration / Mass Assignment", "elevating privilege via extra fields on register/update", + "CWE-915", "High", + [("Inspect the model", ["Watch the register/profile-update API request and infer server-side fields " + "(e.g. role, isAdmin, deluxeToken) not shown in the UI"]), + ("Inject fields", ["Add the privileged field (e.g. \"role\":\"admin\") to the register/update body and submit"]), + ("Confirm", ["Show the account was created/updated with the elevated attribute and can reach admin-only resources"])], + "Server-side allow-list of writable fields (DTO); never bind role/permission from client input", + "Privilege escalation to admin"), + + A("jwt_forgery_spa", "JWT Forgery & Verification Bypass", "forgeable/weak JWT accepted by the API", + "CWE-347", "Critical", + [("Grab a token", ["Log in (browser or API) and capture the JWT the SPA stores/sends (Authorization/cookie)"]), + ("Attack the signature", ["Test alg:none (strip signature), RS→HS confusion (sign with the public key as HMAC secret), " + "and weak HS256 secret cracking; forge a token with elevated claims (e.g. admin email/role)"]), + ("Confirm", ["Show the forged token is ACCEPTED by an authenticated API endpoint (server didn't verify properly)"])], + "Verify signature with a strong secret/correct alg; pin the algorithm; reject alg:none", + "Authentication bypass / account takeover"), + + A("spa_business_logic", "SPA Business-Logic Abuse", "business-logic flaws in cart/checkout/coupon/workflow", + "CWE-840", "High", + [("Model the flow", ["Map the multi-step flow via the browser + its API (cart → basket item → checkout → order)"]), + ("Break invariants (non-destructive)", ["Test negative/zero/huge quantities, client-set prices, reusing/forging coupons, " + "skipping steps, or tampering totals in the API request — WITHOUT completing a real " + "fraudulent purchase or altering others' data"]), + ("Confirm", ["Show the server accepted an invalid state (e.g. negative quantity, altered price) in its response"])], + "Validate all invariants & prices server-side; idempotent coupons; enforce workflow order", + "Financial loss / integrity abuse"), +] + + +def main(): + os.makedirs(OUT, exist_ok=True) + for a in AGENTS: + open(os.path.join(OUT, a["name"] + ".md"), "w").write(render(a)) + print(f"wrote {len(AGENTS)} SPA/API agents to {OUT}") + + +if __name__ == "__main__": + main()