IDOR Attack (Insecure Direct Object Reference)
An Insecure Direct Object Reference (IDOR) attack occurs when an application exposes a direct reference to an internal object (such as a database record, file, or API endpoint) without proper access control checks. Attackers manipulate these references to access unauthorized data, modify records, or perform actions on behalf of other users by simply changing identifiers in URLs, parameters, or cookies.
How IDOR Attack (Insecure Direct Object Reference) Works
IDOR vulnerabilities arise when developers trust client-supplied identifiers without verifying the user has permission to access the referenced object. Common patterns include sequential or predictable IDs in URLs (e.g., /orders/123), API parameters (?userId=456), or form fields. Attackers enumerate or guess these identifiers to access other users' data. The vulnerability exists entirely on the server side — even if the frontend restricts UI access, a determined attacker can bypass it by crafting direct requests.
Identify object references
Explore the application to find direct object references. Look for predictable IDs in URLs (/profile/42), API endpoints (/api/orders/789), request parameters (?documentId=101), or hidden form fields. Common targets include user profiles, orders, invoices, documents, messages, and transactions.
Analyze access control logic
Understand the authentication and authorization model. Does the application verify that the current user owns the object? Many implementations only check if the user is authenticated ("logged in") but not if they have permission to access the specific resource. Test by logging in as User A and attempting to access User B's resources.
Enumerate or manipulate identifiers
Systematically test object references. For sequential IDs, increment or decrement the number. For UUIDs or hashed IDs, look for patterns or vulnerabilities in the generation algorithm. In multi-tenant SaaS, test if users from one organization can access data from another organization.
Exploit unauthorized access
Access sensitive data (personal information, financial records, confidential documents), modify records (change email addresses, shipping destinations, payment methods), or perform privileged actions (approve orders, delete data, reset passwords). In severe cases, attackers can gain complete control over other users' accounts or administrative privileges.
Real-World Examples
Uber bug bounty payout record
A security researcher discovered that by changing user IDs in Uber's API, he could access any user's trip history, pickup locations, and payment information. Uber paid a $100,000 bug bounty and later patched the vulnerability. The incident highlighted how even major companies can miss fundamental access control flaws.
Clever data breach via IDOR
Attackers exploited an IDOR vulnerability in Clever's educational platform to access student data from multiple school districts. By manipulating district IDs in API requests, they bypassed access controls and retrieved sensitive information including student names, birthdates, and school assignments, affecting potentially thousands of students.
Robinhood data leak
Robinhood suffered a data leak when researchers discovered they could access other users' email addresses by enumerating account IDs. The flaw exposed millions of email addresses, which attackers could use for phishing, credential stuffing, or social engineering campaigns. The company patched the issue and implemented proper access controls.
Impact & Risk Assessment
IDOR attacks lead to unauthorized data access, privacy breaches, account takeover, fraud, and regulatory violations. Attackers can steal personal information (GDPR, CCPA exposure), financial data, intellectual property, or perform fraudulent transactions. The impact scales with application sensitivity: healthcare applications expose medical records, financial applications enable money laundering, government systems reveal classified information. Organizations face legal liability, reputational damage, and loss of customer trust. IDOR consistently ranks among OWASP's top security risks due to its prevalence and severe consequences.
How to Detect IDOR Attack (Insecure Direct Object Reference)
Monitor for abnormal access patterns: rapid enumeration of sequential IDs, requests for objects the user shouldn't access, or access attempts across multiple tenants. Log all access control checks with user and object identifiers. Implement audit trails for sensitive data access. Use automated testing to scan for predictable ID patterns in APIs and endpoints. Conduct penetration testing focused on access control, particularly on REST endpoints and URL parameters. Static analysis tools can detect patterns where IDs are used without authorization checks.
How to Prevent IDOR Attack (Insecure Direct Object Reference)
Implement proper authorization checks for every direct object reference. Never trust client-supplied identifiers — always verify the user has permission to access the requested resource. Use indirect object references: map internal IDs to unguessable tokens (UUIDs, random strings) and maintain server-side mapping tables. Implement role-based access control (RBAC) or attribute-based access control (ABAC). For multi-tenant applications, enforce strict tenant isolation at the database and application layers. Use framework-level authorization (e.g., Django@login_required, Spring Security @PreAuthorize) rather than manual checks. Conduct security code reviews focused on access control patterns. Test authentication vs. authorization boundaries regularly.
Code Examples
@app.route('/orders/<int:order_id>')
def get_order(order_id):
# VULNERABLE: No check if user owns this order
order = Order.query.get(order_id)
if not order:
return 'Order not found', 404
return jsonify(order.to_dict())
# Attacker can access any order by changing order_id in URL
# /orders/42, /orders/43, /orders/44, etc.
from flask_login import current_user
@app.route('/orders/<int:order_id>')
def get_order(order_id):
# SECURE: Verify ownership before returning data
order = Order.query.get(order_id)
if not order:
return 'Order not found', 404
if order.user_id != current_user.id:
# Log unauthorized access attempt
log_security_event(
'idor_attempt',
user=current_user.id,
attempted_order=order_id
)
return 'Access denied', 403
return jsonify(order.to_dict())
const authorizeOwnership = (modelName) => {
return async (req, res, next) => {
const resourceId = req.params.id;
const userId = req.user.id;
try {
const Model = mongoose.model(modelName);
const resource = await Model.findById(resourceId);
if (!resource) {
return res.status(404).json({ error: 'Resource not found' });
}
// Check if user owns the resource or has admin role
const hasAccess = resource.userId?.equals(userId) ||
req.user.role === 'admin';
if (!hasAccess) {
// Log the IDOR attempt
await SecurityLog.create({
type: 'idor_attempt',
userId,
resourceId,
modelName,
ip: req.ip
});
return res.status(403).json({ error: 'Access denied' });
}
// Attach resource to request for use in route handler
req.resource = resource;
next();
} catch (error) {
return res.status(500).json({ error: 'Server error' });
}
};
};
// Usage
router.get('/orders/:id', authenticate, authorizeOwnership('Order'), getOrder);
Strengthen your defenses against IDOR Attack (Insecure Direct Object Reference) with PowerWAF.
Comprehensive web application security with WAF, rate limiting, and real-time threat monitoring.
Free plan spots are limited