Insecure Direct Object Reference (IDOR)

A vulnerability where applications expose internal object references without proper authorization checks, allowing unauthorized access to data.

Insecure Direct Object Reference (IDOR) is a type of access control vulnerability that occurs when an application exposes internal implementation objects—like database IDs, file paths, or user references—and fails to verify whether the requesting user is authorized to access them. In Web3 contexts, IDOR vulnerabilities commonly appear in dApp backends, NFT metadata APIs, and user management systems, potentially exposing sensitive user data or enabling unauthorized actions.

How IDOR Works

A vulnerable endpoint might look like:

1GET /api/user/12345/profile

If the application doesn't verify that the authenticated user is actually user 12345, an attacker can enumerate through IDs:

1GET /api/user/12346/profile → Another user's data
2GET /api/user/12347/profile → Another user's data
3...

IDOR in Web3 Applications

NFT Metadata APIs

1// Vulnerable endpoint
2app.get('/api/nft/:tokenId/metadata', (req, res) => {
3 const metadata = getMetadata(req.params.tokenId);
4 res.json(metadata); // No ownership check!
5});
6
7// Could expose unrevealed NFT metadata before mint

User Wallet APIs

1// Vulnerable: Exposes any user's data by ID
2app.get('/api/users/:userId/wallets', (req, res) => {
3 const wallets = getUserWallets(req.params.userId);
4 res.json(wallets); // No authorization!
5});
6
7// Attack: Enumerate user IDs to discover wallet addresses

Transaction History

1// Vulnerable: Internal transaction IDs exposed
2app.get('/api/transactions/:txId', (req, res) => {
3 const tx = getTransaction(req.params.txId);
4 res.json(tx); // Attacker can view others' transactions
5});

Common IDOR Patterns

Sequential IDs

1/api/orders/1001
2/api/orders/1002
3/api/orders/1003 → Easy to enumerate

Predictable References

1/api/documents/report_2024_Q1.pdf
2/api/documents/report_2024_Q2.pdf → Pattern is obvious

Exposed Internal Keys

1/api/files?key=aws-s3-bucket/users/private/document.pdf

Prevention Techniques

Authorization Checks

Always verify the requester has permission:

1app.get('/api/user/:userId/profile', authenticate, (req, res) => {
2 // Check requester is the user or has admin role
3 if (req.user.id !== req.params.userId && !req.user.isAdmin) {
4 return res.status(403).json({ error: 'Forbidden' });
5 }
6
7 const profile = getUserProfile(req.params.userId);
8 res.json(profile);
9});

Indirect References

Map public tokens to internal IDs:

1// Instead of exposing user ID 12345
2// Generate a random reference token
3const publicRef = generateSecureToken(); // "a7f3b2c1d4e5"
4referenceMap.set(publicRef, userId);
5
6// Endpoint uses non-enumerable reference
7app.get('/api/user/:publicRef/profile', (req, res) => {
8 const userId = referenceMap.get(req.params.publicRef);
9 if (!userId) return res.status(404).json({ error: 'Not found' });
10 // Continue with authorization check...
11});

UUIDs Instead of Sequential IDs

1// Instead of: /api/orders/1001
2// Use: /api/orders/550e8400-e29b-41d4-a716-446655440000
3
4const orderId = crypto.randomUUID();

UUIDs are not enumerable, but still require authorization checks.

Scoped Queries

Always filter by authenticated user:

1// VULNERABLE: Fetches any order by ID
2const order = await Order.findById(orderId);
3
4// SECURE: Filters by authenticated user
5const order = await Order.findOne({
6 _id: orderId,
7 userId: req.user.id // Scope to current user
8});

IDOR in Smart Contracts

While smart contracts are transparent by design, IDOR-like issues can occur:

1// All data is public on-chain, but...
2// This function lets anyone modify any user's data!
3function updateUserData(address user, bytes memory data) external {
4 userData[user] = data; // No msg.sender check!
5}
6
7// Correct:
8function updateMyData(bytes memory data) external {
9 userData[msg.sender] = data; // User can only modify their own
10}

Testing for IDOR

Manual Testing

  1. Authenticate as User A
  2. Access resource belonging to User A (note the ID)
  3. Change ID to another user's resource
  4. Check if access is granted

Automated Testing

1# Simple IDOR scanner
2for user_id in range(1, 10000):
3 response = requests.get(
4 f'/api/user/{user_id}/profile',
5 headers={'Authorization': f'Bearer {attacker_token}'}
6 )
7 if response.status_code == 200:
8 print(f'IDOR found: User {user_id} data accessible')

Audit Checklist

When auditing for IDOR:

  • All endpoints with resource IDs have authorization checks
  • Authorization checks verify ownership/permission, not just authentication
  • Sequential/predictable IDs replaced with UUIDs or indirect references
  • Database queries scoped to authenticated user
  • API responses don't leak other users' data
  • Admin endpoints properly protected
  • File access uses indirect references

Impact in Web3

IDOR vulnerabilities in Web3 applications can:

  • Expose wallet addresses and transaction patterns
  • Reveal unreleased NFT metadata
  • Enable unauthorized API actions
  • Leak KYC/identity information
  • Allow access to private user settings

While blockchain data is public, off-chain APIs often contain sensitive information that requires proper access control.

Need expert guidance on Insecure Direct Object Reference (IDOR)?

Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.

Get a Quote

oog
zealynx

Subscribe to Our Newsletter

Stay updated with our latest security insights and blog posts

© 2024 Zealynx