Fintech · Architecture

Securing Fintech & Payment Platforms — An Offensive Checklist

Aug 2026 · 11 min read · Imperonlabs Research

Payment and fintech platforms carry a different threat profile from ordinary web apps: the assets are fungible and irreversible, the flows are asynchronous and multi-party, and a single logic gap can move real money. Generic web testing misses most of it. This is the checklist we run — written from the offensive side, but it doubles as a hardening guide.

Money movement is an authorization problem first

Before anything exotic, the highest-severity fintech bugs are still broken authorization on money-moving endpoints:

  • Can one user initiate a transfer from another user's account by changing an account ID? (BOLA on the source of funds is catastrophic.)
  • Can a viewer or support role approve, refund, or release funds a their role shouldn't?
  • In maker-checker flows, can the same identity play both roles, or approve its own request?
  • Does every state transition on a payment (authorize → capture → refund → void) re-check authorization, or only the first one?

Test authorization on every endpoint that reads a balance, moves funds, changes a payout destination, or alters a limit — as each role, and cross-account. This is where the crown-jewel findings are.

Idempotency and races: the money-printing class

Asynchronous, retried, multi-party flows make idempotency the load-bearing control. Attack it directly:

  • Replay a settled request with the same idempotency key vs. a fresh key — does it double-process?
  • Race the same operation from many connections in one window: duplicate refunds, double coupon/credit redemption, withdrawing the same balance twice before the first debit commits, redeeming a one-time code N times.
  • Negative and boundary amounts — a refund larger than the charge, a negative transfer that credits the source, decimal/rounding abuse across currency conversion.

If the check ("does this balance cover it?") and the commit ("debit it") aren't a single atomic transaction, a race turns a legitimate one-time action into an unlimited one. Assume they aren't until proven.

Webhooks are an unauthenticated code path into your ledger

Payment providers notify your back-end of events (charge.succeeded, payout.paid) via webhooks. Attackers know this. Check:

  • Signature verification. Is every webhook's provider signature verified, with the raw body, before the event mutates state? A missing or bypassable check lets an attacker POST charge.succeeded and receive goods for free.
  • Replay protection. Are signatures timestamped and old events rejected? Can a captured legitimate webhook be replayed to double-credit?
  • Event trust. Does the handler trust amounts and IDs from the webhook body, or re-fetch the authoritative object from the provider? Trusting the body is how "I paid $0.01, the webhook says $10,000 of value" happens.
  • Idempotent handling. Providers retry; a non-idempotent handler double-fulfills on the provider's own retry, no attacker required.

Reconciliation and the ledger

The ledger is the source of truth; attacks aim to desync it from reality:

  • Can you create a state where goods/credit are released but the ledger never debited (fulfill-before-settle, or an error path that ships but doesn't charge)?
  • Are money movements append-only and auditable, or can a mutable balance be written directly?
  • Do error and timeout paths leave partial transactions — charged-not-fulfilled, or fulfilled-not-charged?
  • Does currency handling use integer minor units end-to-end, or float arithmetic that rounds in the attacker's favor?

The regulated surface

Fintech carries controls generic apps don't, and each is a test target:

  • KYC/onboarding bypass — can identity-verification steps be skipped by calling the final step directly, reused across accounts, or satisfied with recycled documents?
  • Limits and velocity — are transaction/withdrawal limits enforced server-side and atomically, or can they be raced past?
  • PCI scope — is cardholder data ever reachable outside the tokenized path? Does the front-end ever handle a PAN it shouldn't?
  • Statement/data authorization — statements, transaction histories, and exports are classic IDOR targets carrying dense PII and financial data.

Sensitive data hygiene

  • No card numbers, full account numbers, or secrets in logs, error messages, analytics, or client-side storage.
  • Transaction and support endpoints scoped so one customer can never enumerate another's records.
  • Tokens for money-movement actions short-lived and bound to the specific operation.

How we prove it

Every finding is demonstrated on throwaway test accounts and the smallest possible amount — one duplicated cent to your own balance, immediately reversed; one benign webhook replay against a test object; one cross-account read of your own second account. You prove the control failed and stop. In a domain where the asset is real money, discipline in the proof is not optional — it's the difference between a researcher and a liability.


Run this list top to bottom and the authorization + idempotency sections alone will surface more severe issues than a full generic web assessment. Money changes the threat model — test like it.