Trading Platform Pentest — Unauthenticated API to Rogue Admin
- Home
- Projects
Project Overview
A financial-technology client (confidential) asked me to test a trading platform before it carried real money: a GraphQL core API, the .NET services that route and match orders, and the internal consoles operators use to approve users and move positions. I ran it as a grey-box penetration test against a full production mirror. The result was not a list of hygiene issues — it was a chain. Privileged GraphQL queries were answered with no token at all. The account-creation path trusted a client-supplied role field, so an ordinary signup produced a working administrator. Seeded accounts shared a single password across environments, signing keys and database credentials were committed to the repository and still readable inside the published container images, and the order-intake service reconstructed attacker-influenced types from a message body. Each step was proven non-destructively, rated with CVSS, written up with exact reproduction steps, and retested once the fixes shipped.
Challenges
- Test a live-money order path without ever placing, altering or cancelling a real trade.
- Cover three very different stacks in one window — a GraphQL core API, .NET order services and the operator consoles.
- Prove privilege escalation end to end instead of filing a theoretical mass-assignment note.
- Separate genuinely missing authentication from controls enforced somewhere else in the request chain.
- Give a team shipping to a regulatory deadline a remediation order they could actually execute.
Approach
- Mapped the GraphQL schema through introspection and enumerated every resolver reachable without a bearer token.
- Built the escalation chain on the production mirror, stopping at proof and never touching live order flow.
- Audited git history and the published container images for keys, credentials and configuration left behind.
- Rated every finding with CVSS, attached reproduction steps, and grouped fixes into three deployable waves.
- Retested after remediation and confirmed each chain was broken outright, not merely blocked at one hop.
What the Test Found
Reported to the client under NDA. Product names, endpoints and identifying detail are withheld; the patterns are what transfer.
- Unauthenticated GraphQL access. Introspection was enabled in production and privileged resolvers answered without a bearer token, exposing accounts, balances and order history to anyone who could reach the endpoint.
- Mass-assignment privilege escalation. The registration mutation accepted a client-supplied role attribute, so a normal signup request created a fully functional administrator account.
- Shared seed credentials. Every seeded demo and service account used one password, and the same values were present in staging and in production.
- Secrets in source and in artifacts. Request-signing keys and database credentials were committed to the repository and remained readable inside the published container images, so rotating the repository alone would not have been enough.
- Unsafe deserialization in order intake. The routing service reconstructed attacker-influenced types from a message body — a direct path towards code execution on a host that sits next to the matching engine.
- Sensitive data written to logs. Full request bodies, including credentials and order detail, were written to log files retained for months and readable by roles that had no business need for them.
What Fixed It
Authentication moved to a single enforced gateway rather than being re-implemented per resolver, and introspection was disabled outside development. Role assignment became server-side only, with the registration payload treated as untrusted input. Every seeded credential was rotated, the exposed keys were revoked and reissued, and the container images were rebuilt from a clean layer so the old values stopped shipping. The deserialization sink was replaced with an explicit allow-list of types. The retest confirmed the chain no longer existed at any hop — and the team kept the gateway pattern for the services they built afterwards, which mattered more than any single fix.
Scope at a Glance
- GraphQL core API — schema, resolvers, authorization
- .NET order routing and matching services
- Operator consoles and approval workflows
- Source repository and published build artifacts
- Grey-box, production mirror, non-destructive proofs