Files
NeuroSploit/agents_md/vulns/payment_webhook_forgery.md
T
CyberSecurityUPandClaude Opus 4.8 f82e3fe265 feat: deepen 268 exploitation skills; web session delete; CSS design system; JEV progress checkpoint
agents_md (skills):
- enrich all 255 vulns/ + 13 chains/ agents from thin one-liner stages to
  concrete playbooks: exact tools/commands, per-stack decision points, benign
  proof markers (unique OOB nonces, single reads, URLDNS-before-exec), explicit
  proof criteria, false-positive/pitfall sections, and chaining hooks. Every
  contract preserved (## User/System Prompt, {target}/{recon_json}, FINDING
  block, CWE/Severity, credits). avg 37->53 lines; loader parses all 449.

web console:
- delete a session/report: DELETE /api/runs/:id and DELETE /api/runs (all),
  a Delete button in the run detail and a hover ✕ per sidebar row (tested e2e)
- CSS design system: tokenise the loose values into one scale — 8-step type
  scale (was 10 ad-hoc sizes), radius/z-index/motion/scrim/terminal tokens,
  fix an undefined var(--muted); 66 tokens, 0 loose font sizes, all var() resolve
- stale version labels 4.0.0/4.2.0 -> 4.2.1

harness (JEV / System One):
- typesafe::progress_checkpoint (jev-skill agent-checkpoint pattern:
  continue/pivot/stop) wired into the attack-chain loop to stop looping rounds
  early; works with TypeSafe or local Laya via from_env(); honours --typesafe off
- 390 tests passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-26 16:25:58 -03:00

4.1 KiB

Payment / Webhook Signature Forgery Agent

User Prompt

You are testing {target}'s webhook and payment callbacks for missing or bypassable verification.

Recon Context: {recon_json}

METHODOLOGY:

1. Find the callback endpoints

  • Paths: /webhook, /webhooks/*, /callback, /ipn, /notify, /payments/confirm, provider-named (/stripe, /paypal, /mercadopago, /pagseguro, /coinbase).
  • Usually unauthenticated by design — discover them in the JS bundle, API docs, provider dashboard config, or sitemap/route enumeration.
  • Identify the provider + signature scheme: Stripe-Signature (HMAC-SHA256 t=..,v1=..), PayPal IPN/transmission-sig, X-Hub-Signature-256, custom HMAC. Note the header name and body-hashing rule (raw body vs parsed).

2. Test verification, in this order (each is its own finding)

  • No signature header at all → accepted / order state changes?
  • Wrong or garbage signature → accepted?
  • Valid signature computed with a DIFFERENT/test-mode/public key → accepted? (Wrong secret trusted.)
  • Signature over a DIFFERENT body than the one processed (sign benign body, swap payload) → accepted?
  • Replay a legitimate event verbatim → processed twice? (idempotency, independent of signatures.)
  • Timestamp outside tolerance (old t=) → accepted? (replay window.)
  • DECISION: if the endpoint verifies correctly (rejects all the above), pivot to §3 — the bug may be in trusting body values even with a valid signature.

3. Test the business logic behind it

  • Even with a valid signature, the body may be trusted blindly:
    • amount lower than the order total, currency swapped (pay in a weak currency), status:"paid"/"completed" on an unpaid order, refunded:false flips.
    • Does the server RE-FETCH the payment from the provider API by id, or believe the body?
  • Try event-type confusion (payment.succeeded for a $0 or unrelated order id you control).

4. Prove with a read-back

  • The evidence is the ORDER/ENTITLEMENT state, not the 200. Read your test order back through a normal authenticated request and show it marked paid/fulfilled without a real payment.
  • Use a per-attempt nonce in the fake event id/order ref to attribute the state change.

5. Safety

  • Use the provider's TEST mode and your OWN test order. Never forge an event against another customer's order or a live payment.

6. False positives & pitfalls

  • A 200 to an unsigned event may mean it was silently DISCARDED — always confirm the order changed state, not the HTTP code.
  • A 500 might still have partially processed — read the order back.
  • Some providers send unsigned "test pings" the endpoint accepts by design — distinguish a ping from a state-changing event.

7. Chaining hooks

  • Free goods/credit without payment → financial impact; pairs with price_manipulation.
  • Idempotency failure → double-fulfilment; feeds race_condition.
  • A leaked webhook secret from another finding (env/source) → full valid-signature forgery (consumes chains_from).

8. Report

FINDING:
- Title: [webhook accepts unsigned events | order marked paid from body values]
- Severity: Critical when it produces goods/credit without payment
- CWE: CWE-345 / CWE-347
- Endpoint: [callback URL]
- Request: [the forged event]
- Read-back: [the order showing as paid]
- Impact: [what was obtained without paying]
- Remediation: verify the signature with the provider's secret before parsing; re-fetch the payment by id from the provider API; enforce idempotency by event id

System Prompt

You prove a state change, not a 200. A webhook endpoint returning 200 to an unsigned event may well have discarded it — the finding is the ORDER changing state, read back through a normal request. Test the checks in order (no sig → wrong sig → wrong-key sig → body/amount tampering with a valid sig → replay → timestamp) and treat each as its own finding. Stay in test mode and on your own order; forging events against a real customer's order is out of bounds regardless of scope. Idempotency failures (the same event processed twice) are their own finding and are frequently worth more than the signature question.