Skip to content
All modules
CoreModule 15 of 2790 minutes

APIs, GraphQL and application logic

The bugs that live between endpoints rather than inside one: object references, mass assignment, over-broad queries, and workflows that can be run out of order.

Assumes13. Sessions, tokens and access control

By the end you can

  • Enumerate an API's real surface from a specification, a client bundle, or introspection
  • Test an object reference for authorisation rather than for existence, using two accounts
  • Find a mass-assignment field by diffing what the API returns against what it accepts
  • Query a GraphQL schema for the fields the UI never asks for, and measure the cost of a nested query
  • Model a multi-step workflow as a state machine and find the transition nobody guards
  • Write a logic bug up in terms of the assumption it breaks, not the request that broke it

1. Read

2. Use the tools

In the order they come up while solving. Read what each one does, or go straight to the workspace tab that runs it.

3. Try one now

Generated in your browser and checked in your browser. No account, nothing to download, and a fresh one whenever you want another.

4. Practise on the real thing

Real picoCTF challenges that use these techniques, easiest first. 22 match in total - see the full index.

Common mistakes

The wrong turns this topic reliably produces. Written as the mistake rather than the rule, because the rule is easy to agree with and easy to walk straight past.

  • Reporting an IDOR from one account. Without a second principal you have proved that an object exists, not that you were not entitled to it.
  • Assuming the documented API is the API. Older versions, internal hosts and undocumented parameters routinely outlive the docs that describe them.
  • Looking for injection in a logic challenge. If every request is individually valid, the bug is in the order, the quantity, or the state - not in the parsing.
  • Testing GraphQL only through the queries the UI issues. Introspection, aliases and batched operations reach fields, and rate-limit behaviour, that the client never exercises, and that is where the authorisation gaps sit.
  • Assuming a negative quantity, a zero, or an absurdly large one will be rejected because the form will not accept it. The browser's constraint is not the server's, and those are exactly the values at which a workflow's arithmetic stops holding.

Checkpoint

Against a multi-step workflow, complete it in an order the designer did not intend and state precisely which check assumed the previous step had happened.

Teaching note

Logic bugs are the hardest to teach because there is no payload to memorise. The reliable exercise is to make students write down the intended flow first, in five lines, and then attack their own diagram - the gap between the diagram and the implementation is where every finding comes from.

Go deeper

The lessons above are written to get you through a challenge. These are the chapters to read when you want the subject instead - each one named so you can check it rather than take our word for it. Nothing here is affiliate-linked or sold by us.

  • Hacking APIs - Corey Ball

    Chapter 3, Common API Vulnerabilities

    The API-specific bug classes named and separated, which stops everything being called 'an IDOR'.

  • Hacking APIs - Corey Ball

    Chapter 11, Mass Assignment

    The diff-based method for finding assignable fields, which generalises well beyond APIs.

  • Hacking APIs - Corey Ball

    Chapter 14, Attacking GraphQL

    Introspection, query depth and batching - the three things that make GraphQL its own surface.

  • Real-World Bug Hunting - Peter Yaworski

    Chapter 18, Application Logic and Configuration Vulnerabilities

    The closest thing to a worked corpus of logic bugs, each with the assumption that failed.

  • Designing Secure Software - Loren Kohnfelder

    Chapter 6, Secure Design

    Read it from the other side: the design decisions listed here are the ones a logic bug is a failure of.