mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-07-06 11:27:52 +02:00
browser-driven testing doctrine + 8 SPA/API agents (Juice Shop-ready)
- tool_doctrine: agents now actively DRIVE the browser on JS/SPA targets — use the Playwright MCP (render, read live DOM, click client-side routes, watch the network to find the real API, screenshot proof); when no MCP, use the Playwright CLI (write+run a small script / npx playwright screenshot) to render and capture XHR/fetch traffic — complementing curl (which only sees the empty shell). - probe: detect SPAs (<app-root>, ng-version, near-empty body + linked scripts → Angular/React/Vue/SPA) and note in recon that the browser is required, so the SPA agents get selected. - +8 SPA/API agents (library 383): spa_api_discovery, spa_hidden_admin, login_sqli_bypass, dom_xss_spa, api_bola_numeric_ids, register_privilege_mass_assign, jwt_forgery_spa, spa_business_logic. - Docs: README/RELEASE/TUTORIAL counts + notes.
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
<img src="https://img.shields.io/badge/Version-3.5.5-blue?style=flat-square">
|
<img src="https://img.shields.io/badge/Version-3.5.5-blue?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Harness-Rust%20%7C%20tokio-e6b673?style=flat-square">
|
<img src="https://img.shields.io/badge/Harness-Rust%20%7C%20tokio-e6b673?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square">
|
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/MD%20Agents-375-red?style=flat-square">
|
<img src="https://img.shields.io/badge/MD%20Agents-383-red?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Models-14%20providers-success?style=flat-square">
|
<img src="https://img.shields.io/badge/Models-14%20providers-success?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Modes-Black%20%7C%20White%20%7C%20Grey%20%7C%20Host-9cf?style=flat-square">
|
<img src="https://img.shields.io/badge/Modes-Black%20%7C%20White%20%7C%20Grey%20%7C%20Host-9cf?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Auth-API%20key%20%7C%20Subscription-orange?style=flat-square">
|
<img src="https://img.shields.io/badge/Auth-API%20key%20%7C%20Subscription-orange?style=flat-square">
|
||||||
@@ -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
|
Grok) — recons the target, **intelligently selects only the agents that match the
|
||||||
discovered surface**, runs them in parallel, **chains** findings into deeper
|
discovered surface**, runs them in parallel, **chains** findings into deeper
|
||||||
impact, and **validates every claim by cross-model voting + tool-receipt
|
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**.
|
Control TUI**.
|
||||||
|
|
||||||
### Engagement modes
|
### Engagement modes
|
||||||
|
|||||||
+19
@@ -102,6 +102,25 @@ interactive line-editing.
|
|||||||
- **Rate-limit testing** is a first-class control check (small non-disruptive
|
- **Rate-limit testing** is a first-class control check (small non-disruptive
|
||||||
burst → look for 429/lockout/Retry-After), never a DoS.
|
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** (`<app-root>`, `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 check & Playwright MCP fixes
|
||||||
|
|
||||||
- **Subscription login preflight.** Before a `--subscription` run, the harness
|
- **Subscription login preflight.** Before a `--subscription` run, the harness
|
||||||
|
|||||||
+3
-3
@@ -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/…).
|
1. **Recons** the target with real tools (curl/nmap/…).
|
||||||
2. **Intelligently selects** only the agents whose preconditions match the recon
|
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
|
3. **Exploits** in parallel — each agent works in a ReAct loop and must prove its
|
||||||
claim with a **tool receipt** (raw output).
|
claim with a **tool receipt** (raw output).
|
||||||
4. **Validates** every candidate by **cross-model voting** (a different model
|
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
|
```bash
|
||||||
neurosploit --version # neurosploit 3.5.5
|
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
|
neurosploit models # all providers & models
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -535,7 +535,7 @@ built from SAST/dataflow), so uncertainty becomes *path reachability*, not state
|
|||||||
|
|
||||||
## 13. The agent library
|
## 13. The agent library
|
||||||
|
|
||||||
`agents_md/` holds **375** markdown agents in categories:
|
`agents_md/` holds **383** markdown agents in categories:
|
||||||
|
|
||||||
| Category | Dir | Count | Purpose |
|
| Category | Dir | Count | Purpose |
|
||||||
|----------|-----|-------|---------|
|
|----------|-----|-------|---------|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -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=<img src=x onerror=…>) 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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -51,9 +51,14 @@ fn operator_directives(cfg: &RunConfig) -> String {
|
|||||||
/// where these tools are preinstalled.
|
/// where these tools are preinstalled.
|
||||||
fn tool_doctrine(mcp_on: bool) -> String {
|
fn tool_doctrine(mcp_on: bool) -> String {
|
||||||
let browser = if mcp_on {
|
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 {
|
} 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 <url>` to get the rendered DOM + the XHR/fetch URLs the app calls (that reveals the real API). Use `npx playwright screenshot <url> out.png` for quick proof. Combine with curl for the discovered API endpoints."
|
||||||
};
|
};
|
||||||
format!(
|
format!(
|
||||||
"TOOLING (authorized; best on Kali Linux or the kalilinux/kali-rolling Docker image):\n\
|
"TOOLING (authorized; best on Kali Linux or the kalilinux/kali-rolling Docker image):\n\
|
||||||
|
|||||||
@@ -157,16 +157,29 @@ pub async fn probe(target: &str) -> Probe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Tech hints (headers + body keywords).
|
// Tech hints (headers + body keywords).
|
||||||
let hay = format!("{} {} {} {}", p.server, p.powered_by, p.content_type, body.chars().take(20_000).collect::<String>()).to_lowercase();
|
let hay = format!("{} {} {} {}", p.server, p.powered_by, p.content_type, body.chars().take(30_000).collect::<String>()).to_lowercase();
|
||||||
for (needle, tech) in [
|
for (needle, tech) in [
|
||||||
("wp-content", "WordPress"), ("/wp-json", "WordPress"), ("drupal", "Drupal"), ("joomla", "Joomla"),
|
("wp-content", "WordPress"), ("/wp-json", "WordPress"), ("drupal", "Drupal"), ("joomla", "Joomla"),
|
||||||
("x-drupal", "Drupal"), ("laravel_session", "Laravel"), ("csrftoken", "Django"), ("__next", "Next.js"),
|
("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"),
|
("microsoft-iis", "IIS"), ("express", "Express"), ("phpsessid", "PHP"), ("jsessionid", "Java"),
|
||||||
("cloudflare", "Cloudflare"), ("swagger", "Swagger/OpenAPI"), ("graphql", "GraphQL"),
|
("cloudflare", "Cloudflare"), ("swagger", "Swagger/OpenAPI"), ("graphql", "GraphQL"),
|
||||||
|
// SPA / framework markers (Juice Shop = Angular <app-root>).
|
||||||
|
("<app-root", "Angular"), ("ng-version", "Angular"), ("angular", "Angular"),
|
||||||
|
("data-reactroot", "React"), ("id=\"root\"", "SPA"), ("id=\"app\"", "SPA"),
|
||||||
|
("polyfills", "SPA"), ("runtime.", "SPA"),
|
||||||
] {
|
] {
|
||||||
if hay.contains(needle) && !p.tech.iter().any(|t| t == tech) { p.tech.push(tech.to_string()); }
|
if hay.contains(needle) && !p.tech.iter().any(|t| t == tech) { p.tech.push(tech.to_string()); }
|
||||||
}
|
}
|
||||||
|
// Heuristic: a nearly-empty body with several linked scripts is a JS SPA
|
||||||
|
// (curl sees the shell only — the browser is required to render it).
|
||||||
|
let text_len = body.chars().filter(|c| !c.is_whitespace()).count();
|
||||||
|
if p.scripts.len() >= 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.
|
// CORS reflection probe.
|
||||||
if let Ok(r2) = c.get(target).header("Origin", "https://evil.neurosploit.test").send().await {
|
if let Ok(r2) = c.get(target).header("Origin", "https://evil.neurosploit.test").send().await {
|
||||||
|
|||||||
@@ -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=<img src=x onerror=…>) "
|
||||||
|
"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()
|
||||||
Reference in New Issue
Block a user