Modern Web Exploitation Techniques
Second-Order IDOR (Whitebox)
Now that we have covered some background information about second-order vulnerabilities, we will explore the methods for identifying, exploiting, and mitigating them within a web application, taking a whitebox approach.
Code Review - Identifying the Vulnerability
Before analyzing the web application's source code, let us poke at the application to see what functionality awaits us. The application seems to be a file storage application. After logging in with our test user htb-stdnt, we can see the files stored for this user:
Clicking the first stored file results in a request to /get_data.php?id=2, which redirects us to a page displaying the file:
Since the parameter id is an obvious IDOR injection point, let us try to change the parameter to see if we can access other users' files. If we access the link /get_data.php?id=1 in our browser, we are logged out, and an error message is displayed:
Thus, the web application is not vulnerable to a classical first-order IDOR vulnerability. Let us move on to analyze the source code to see if we can spot a second-order IDOR vulnerability.
When requesting a file, the backend checks our access and redirects us to either display_data.php or error.php, depending on whether we have access to the requested file, as we can see in get_data.php:
<?php
session_start();
require_once ('db.php');
if(!$_SESSION['user']){
header("Location: index.php");
exit;
}
$_SESSION['id'] = $_GET['id'];
if(check_access($_SESSION['id'], $_SESSION['user'])){
header("Location: display_data.php");
exit;
} else {
header("Location: error.php");
exit;
}
?>
If the check is successful, the file is fetched and displayed in display_data.php:
<?php
session_start();
require_once ('db.php');
if(!$_SESSION['user']){
header("Location: index.php");
exit;
}
$user_data = fetch_user_data($_SESSION['user']);
$data = fetch_data($_SESSION['id']);
?>
<SNIP>
// HTML content displaying the file
Otherwise, we are logged out and redirected to index.php:
<?php
session_start();
session_unset();
$_SESSION['msg'] = 'Something went wrong. You have been logged out for security reasons.';
header("Location: index.php");
exit;
?>
As we can see, the session variable id is set to the file ID we provide in the GET request to get_data.php. If the access check succeeds, the file is retrieved based on the session variable id. However, if the access check fails, the session variable is only cleared after redirecting to error.php via the call to the session_unset function. Thus, the session variable id remains set to the file ID we provide to the get_data.php endpoint until we access the error.php endpoint. This enables us to access any file ID we want by not following the redirect to error.php and instead accessing display_data.php directly after setting any file ID via the get_data.php endpoint.
Running the Application Locally
As always, in a whitebox penetration test, we will verify our exploit plan by confirming it on a locally running version of the web application. The code contains a sql file which contains the required tables as well as some seed data:
CREATE TABLE `data` (
`id` int(11) NOT NULL,
`owner` varchar(256) NOT NULL,
`data` varchar(10000) NOT NULL,
`name` varchar(256) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`username` varchar(256) NOT NULL,
`description` varchar(256) NOT NULL,
`password` longtext NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# htb-stdnt:Academy_student!
INSERT INTO `users` (`id`, `username`, `description`, `password`) VALUES
(2, 'htb-stdnt', 'This is the user for HackTheBox Academy students.', '$2a$12$f4QYLeB2WH/H1GA/v3M0I.MkOqaDAkCj8vK4oHCvI3xxu7jNhjlJ.');
INSERT INTO `data` (`id`, `owner`, `data`, `name`) VALUES
(1, 'admin', "<SNIP>", 'Secret Apple Pie Recipe');
INSERT INTO `data` (`id`, `owner`, `data`, `name`) VALUES
(2, 'htb-stdnt', '<SNIP>', 'Lorem Ipsum');
We can then start a MySQL docker container that initializes the database from the provided db.sql file:
[!bash!]$ docker run -p 3306:3306 -e MYSQL_USER='db' -e MYSQL_PASSWORD='db-password' -e MYSQL_DATABASE='db' -e MYSQL_ROOT_PASSWORD='db' --mount type=bind,source="$(pwd)/db.sql",target=/docker-entrypoint-initdb.d/db.sql mysql
Afterward, we can use PHP's built-in web server to run the application:
[!bash!]$ php -S 127.0.0.1:8000
[Sun May 14 11:48:02 2023] PHP 7.4.33 Development Server (http://127.0.0.1:8000) started
Exploitation
To exploit the second-order IDOR vulnerability, we need to force the web application to set the session variable id to a different user's file such that we can display it. We can do so by supplying an arbitrary ID to the get_data.php endpoint:

As long as we do not follow the redirect to error.php, the session variable id remains set. Thus, we can now navigate to /display_data.php in our web browser to display the file, which is the admin user's secret apple pie recipe:
This proof-of-concept allows us to write a small script that exfiltrates all existing files on the web application.
Patching
To patch the vulnerability, we need to ensure the access is checked before the file can be accessed. In this web application, the file can be accessed as soon as the session variable id is set. Thus, we must ensure that this session variable is only set after the access has been checked. Thus, we can fix the vulnerability by changing the code in get_data.php:
<?php
session_start();
require_once ('db.php');
if(!$_SESSION['user']){
header("Location: index.php");
exit;
}
if(check_access($_GET['id'], $_SESSION['user'])){
$_SESSION['id'] = $_GET['id'];
header("Location: display_data.php");
exit;
} else {
header("Location: error.php");
exit;
}
?>
/ 1 spawns left
Questions
Answer the question(s) below to complete this Section and earn cubes!
Click here to spawn the target system!
Target:
Click here to spawn the target system!
Table of Contents
Introduction to Modern Web Exploitation Techniques
Introduction to Modern Web Exploitation TechniquesDNS Rebinding
Introduction to DNS Rebinding SSRF Basic Filter Bypasses DNS Rebinding: SSRF Filter Bypass DNS Rebinding: Same-Origin Policy Bypass DNS Rebinding: Tools & PreventionSecond-Order Attacks
Introduction to Second-Order Attacks Second-Order IDOR (Whitebox) Second-Order IDOR (Blackbox) Second-Order LFI Second-Order Command InjectionWebSocket Attacks
Introduction to WebSockets WebSocket Analysis in Burp Exploiting XSS via WebSockets Exploiting SQLi via WebSockets Cross-Site WebSocket Hijacking (CSWH) WebSocket Attacks: Tools & PreventionSkills Assessment
Skills AssessmentMy Workstation
OFFLINE
/ 1 spawns left