OWASP Web Top 10 — A01

Insecure Direct Object Reference (IDOR)

Insecure Direct Object Reference (IDOR) is a critical access control vulnerability that allows attackers to access or modify resources belonging to other users by manipulating object references. It occurs when applications expose internal implementation objects such as database keys or file paths without proper authorization checks.

What Is Insecure Direct Object Reference?

Insecure Direct Object Reference (IDOR) is an access control vulnerability that arises when an application uses user-supplied input to directly access objects without verifying whether the user has authorization to access the requested resource. The "object" in IDOR can be a database record, a file, a directory, or any other resource that can be referenced by a user-controllable parameter such as an ID, filename, or key.

The vulnerability stems from the assumption that users will only request resources they own or have permission to access. When developers rely solely on obscurity or assume that users won't guess valid identifiers, they create opportunities for attackers to enumerate and access unauthorized resources. Simply hiding references in the user interface or using sequential IDs is not a security control—if the application doesn't verify ownership or permissions server-side, it's vulnerable to IDOR.

IDOR is classified under Broken Access Control (A01) in the OWASP Top 10 2021. It's one of the most common and exploited vulnerabilities in modern web applications. Despite being straightforward to understand and prevent, IDOR continues to appear in applications of all sizes, from small startups to major tech companies, often leading to severe data breaches and privacy violations.

How It Works

1
User accesses a resource via direct reference

The application presents a resource (such as an order, document, or profile) using a direct reference in the URL, request parameter, or API call. For example, /api/orders/12345 where 12345 is the order ID.

2
Application retrieves object without authorization check

The server receives the request and uses the provided ID to fetch the resource from the database or file system. However, it fails to verify whether the authenticated user has permission to access that specific resource—it only checks if the user is logged in, not if they own the resource.

3
Attacker identifies the reference pattern

By observing legitimate requests to their own resources, the attacker notices the predictable pattern of object references. They might see sequential IDs, UUIDs, or filenames in URLs, API responses, or HTML source code.

4
Attacker modifies the object reference

The attacker manipulates the reference parameter, changing /api/orders/12345 to /api/orders/12346, /api/orders/12344, or any other value. They might iterate through sequential IDs or try random values to discover accessible resources.

5
Unauthorized access is granted

Because the application doesn't verify ownership or permissions, it returns the requested resource regardless of whether it belongs to the authenticated user. The attacker successfully accesses, and potentially modifies or deletes, resources belonging to other users.

Vulnerable Code Example

Vulnerable — Java / Spring Boot
@RestController
@RequestMapping("/api")
public class OrderController {

    @Autowired
    private OrderRepository orderRepository;

    @GetMapping("/orders/{id}")
    public ResponseEntity<Order> getOrder(
        @PathVariable Long id,
        Principal principal
    ) {
        // VULNERABLE: Only checks if user is authenticated,
        // does NOT verify if the user owns this order
        Optional<Order> order = orderRepository.findById(id);

        if (order.isPresent()) {
            return ResponseEntity.ok(order.get());
        }

        return ResponseEntity.notFound().build();
    }
}

// Attacker scenario:
// 1. User Alice logs in and sees her order: /api/orders/100
// 2. Attacker (logged in as Bob) tries: /api/orders/99
// 3. Attacker (logged in as Bob) tries: /api/orders/101
// 4. Server returns Alice's orders because there's no ownership check
// 5. Attacker can enumerate all orders by iterating IDs

Secure Code Example

Secure — Java / Spring Boot (Authorization Check)
@RestController
@RequestMapping("/api")
public class OrderController {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/orders/{id}")
    public ResponseEntity<Order> getOrder(
        @PathVariable Long id,
        Principal principal
    ) {
        // SECURE: Verify the authenticated user owns this order
        User currentUser = userRepository.findByUsername(
            principal.getName()
        ).orElseThrow();

        Optional<Order> order = orderRepository.findById(id);

        if (order.isEmpty()) {
            return ResponseEntity.notFound().build();
        }

        // Critical authorization check: does this order belong to the user?
        if (!order.get().getUserId().equals(currentUser.getId())) {
            // Return 403 Forbidden or 404 Not Found to avoid info disclosure
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }

        return ResponseEntity.ok(order.get());
    }
}

// Alternative secure approach: Query by both ID AND user ID
@GetMapping("/orders/{id}")
public ResponseEntity<Order> getOrderSecure(
    @PathVariable Long id,
    Principal principal
) {
    User currentUser = userRepository.findByUsername(
        principal.getName()
    ).orElseThrow();

    // Find order by ID AND user ownership in a single query
    Optional<Order> order = orderRepository
        .findByIdAndUserId(id, currentUser.getId());

    return order
        .map(ResponseEntity::ok)
        .orElse(ResponseEntity.notFound().build());
}

Types of Insecure Direct Object Reference

Horizontal IDOR

The most common type, where an attacker accesses resources belonging to other users at the same privilege level. For example, a regular user accessing another regular user's profile, orders, or documents by changing an ID parameter. This type of IDOR exploits missing ownership checks between users with equal permissions. Examples include accessing /users/123/profile when you're user 456, or downloading /invoices/999.pdf that belongs to another customer.

Vertical IDOR

A privilege escalation variant where an attacker with lower privileges accesses resources that should only be available to higher-privileged users. For example, a regular user accessing an admin panel by navigating to /admin/settings, or a customer viewing internal staff documents at /staff/payroll/2024.xlsx. Vertical IDOR is more severe because it allows users to perform administrative actions they should never be authorized to do, potentially compromising the entire application.

Body/Parameter IDOR

IDOR vulnerabilities aren't limited to URL parameters. Object references can appear in request bodies (JSON/XML), HTTP headers, cookies, or form data. For example, a POST request to update a profile might include {"userId": 123, "email": "new@email.com"} where an attacker modifies userId to update someone else's profile. Hidden form fields like <input type="hidden" name="accountId" value="789"> are also vulnerable if the server trusts client-supplied values without validation.

Impact

IDOR vulnerabilities can lead to severe security breaches with far-reaching consequences. The impact depends on the sensitivity of the exposed resources and the permissions granted to authenticated users.

Unauthorized data access and privacy violations

Attackers can view sensitive personal information, financial records, medical data, private messages, or business documents belonging to other users. This leads to privacy breaches, GDPR/CCPA violations, and loss of customer trust. In healthcare or financial applications, such breaches can have severe regulatory and legal consequences.

Account takeover and impersonation

If IDOR affects user account endpoints, attackers can modify email addresses, passwords, or security settings of other accounts. This can lead to complete account takeover, allowing attackers to impersonate victims, access additional resources, or use compromised accounts for further attacks.

Data modification and destruction

When IDOR affects write operations (PUT, POST, DELETE), attackers can modify or delete other users' data. This includes canceling orders, altering financial transactions, deleting files, changing configurations, or manipulating business records. Such actions can cause financial loss, operational disruption, and data integrity issues.

Mass data harvesting and enumeration

Because IDOR often involves predictable identifiers (sequential IDs), attackers can automate the exploitation to enumerate and extract entire datasets. A simple script can iterate through thousands of IDs to harvest all customer records, invoices, or documents. This mass exfiltration can be sold on dark web markets or used for identity theft, fraud, and competitive espionage.

Prevention Checklist

Implement authorization checks on every request

Never assume that a user should have access to a resource just because they're authenticated. Every request that accesses a resource must verify that the authenticated user has permission to access that specific resource. Check ownership, role permissions, or access control lists (ACLs) before returning or modifying any data. This is the primary defense against IDOR.

Use indirect object references

Instead of exposing internal database IDs directly, use session-specific or user-specific mappings. For example, instead of /api/orders/12345, use /api/orders/my-recent-order or map internal IDs to random tokens stored in the user's session. This prevents attackers from guessing valid identifiers and makes enumeration attacks much harder.

Use unpredictable identifiers (UUIDs)

Replace sequential integer IDs with cryptographically random UUIDs (Universally Unique Identifiers). While UUIDs don't eliminate the need for authorization checks, they make enumeration attacks infeasible because attackers cannot guess valid IDs. For example, use 550e8400-e29b-41d4-a716-446655440000 instead of 12345.

Implement access control middleware/filters

Use framework-level access control mechanisms to enforce authorization consistently across your application. For example, use Spring Security's method-level security annotations (@PreAuthorize), ASP.NET's authorization filters, or custom middleware that validates resource ownership. Centralized access control reduces the risk of missing authorization checks in individual endpoints.

Query resources with user context included

When retrieving resources, include the user ID in the database query itself rather than just the object ID. For example, use SELECT * FROM orders WHERE id = ? AND user_id = ? instead of SELECT * FROM orders WHERE id = ? followed by a separate ownership check. This ensures that the database itself enforces ownership, preventing logic errors.

Regular security testing and code reviews

Conduct penetration testing specifically targeting access control issues. Use automated tools like Burp Suite Autorize extension, OWASP ZAP, or custom scripts to test for IDOR by iterating through IDs with different user sessions. Implement code review practices that specifically check for authorization logic in all resource access endpoints. Train developers to recognize and prevent IDOR vulnerabilities.

Real-World Examples

2015

Facebook Photo Deletion

A security researcher discovered an IDOR vulnerability in Facebook that allowed any user to delete photos from any other user's account. By manipulating photo IDs in delete requests, an attacker could remove photos without authorization. Facebook patched the vulnerability and awarded the researcher a $12,500 bug bounty for the critical finding.

2016

Uber Trip History Access

Uber suffered from an IDOR vulnerability that exposed riders' trip history, including pickup and dropoff locations, driver information, and timestamps. By changing the UUID in API requests, attackers could access trip data belonging to other Uber users. This privacy breach exposed sensitive location data and travel patterns of millions of users before being fixed.

2017

Airbnb Account Takeover

A researcher found multiple IDOR vulnerabilities in Airbnb's platform, including the ability to access and modify other users' reservations and messages. By manipulating reservation IDs and conversation thread IDs, an attacker could view private communications, booking details, and even cancel other users' reservations. Airbnb awarded a significant bounty for the disclosure.

2019

First American Financial

First American Financial Corporation, a major title insurance company, exposed approximately 885 million sensitive documents due to an IDOR vulnerability. Sequential document IDs in URLs allowed anyone to access mortgage and banking documents, Social Security numbers, wire transfer receipts, and other highly sensitive customer data without authentication. The breach resulted in a significant SEC investigation and settlement.

Ready to Test Your Knowledge?

Put what you have learned into practice. Try identifying and fixing IDOR vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.