Skip to content

Commit

Permalink
Merge branch 'master' of github.com:digininja/DVWA
Browse files Browse the repository at this point in the history
  • Loading branch information
digininja committed Feb 25, 2023
2 parents 5477f7a + 87642b9 commit 29dab22
Show file tree
Hide file tree
Showing 14 changed files with 826 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These are supported funding model platforms

github: digininja
custom: https://digi.ninja
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ Dockerfile

# Used by pytest
tests/__pycache__/

# Don't include any uploaded images
hackable/uploads/*
428 changes: 428 additions & 0 deletions README.es.md

Large diffs are not rendered by default.

26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ This file is available in multiple languages:
- Chinese: [简体中文](README.zh.md)
- French: [Français](README.fr.md)
- Persian: [فارسی](README.fa.md)
- Spanish: [Español](README.es.md)
- Turkish: [Türkçe](README.tr.md)

If you would like to contribute a translation, please submit a PR. Note though, this does not mean just run it through Google Translate and send that in, those will be rejected. Submit your translated version by adding a new 'README.xx.md' file where xx is the two-letter code of your desired language (based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)).
Expand Down Expand Up @@ -371,7 +372,7 @@ You may be running into problems with SELinux. Either disable SELinux or run th
setsebool -P httpd_can_network_connect_db 1
```
### Anything else
### Anything Else
For the latest troubleshooting information please read both open and closed tickets in the git repo:
Expand All @@ -388,6 +389,14 @@ If raising a ticket, please submit at least the following information:
- - -
## Tutorials
I am going to try to put together some tutorial videos that walk through some of the vulnerabilities and show how to detect them and then how to exploit them. Here are the ones I've made so far:
[Finding and Exploiting Reflected XSS](https://youtu.be/V4MATqtdxss)
- - -
## SQLite3 SQL Injection
_Support for this is limited, before raising issues, please ensure you are prepared to work on debugging, do not simply claim "it does not work"._
Expand All @@ -409,6 +418,21 @@ The challenges are exactly the same as for MySQL, they just run against SQLite3
- - -
👨‍💻 Contributors
-----
Thanks for all your contributions and keeping this project updated. :heart:
If you have an idea, some kind of improvement or just simply want to collaborate, you are welcome to contribute and participate in the Project, feel free to send your PR.
<p align="center">
<a href="https://github.com/digininja/DVWA/graphs/contributors">
<img src="https://contrib.rocks/image?repo=digininja/DVWA&max=500">
</a>
</p>
- - -
## Links
Project Home: <https://github.com/digininja/DVWA>
Expand Down
3 changes: 3 additions & 0 deletions dvwa/includes/dvwaPage.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ function dvwaHtmlEcho( $pPage ) {
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_s', 'name' => 'XSS (Stored)', 'url' => 'vulnerabilities/xss_s/' );
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'csp', 'name' => 'CSP Bypass', 'url' => 'vulnerabilities/csp/' );
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'javascript', 'name' => 'JavaScript', 'url' => 'vulnerabilities/javascript/' );
if (dvwaCurrentUser() == "admin") {
$menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'authbypass', 'name' => 'Authorisation Bypass', 'url' => 'vulnerabilities/authbypass/' );
}
}

$menuBlocks[ 'meta' ] = array();
Expand Down
53 changes: 53 additions & 0 deletions vulnerabilities/authbypass/authbypass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
function show_save_result (data) {
if (data.result == 'ok') {
document.getElementById('save_result').innerText = 'Save Successful';
} else {
document.getElementById('save_result').innerText = 'Save Failed';
}
}

function submit_change(id) {
first_name = document.getElementById('first_name_' + id).value
surname = document.getElementById('surname_' + id).value

fetch('change_user_details.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ 'id': id, 'first_name': first_name, 'surname': surname })
}
)
.then((response) => response.json())
.then((data) => show_save_result(data));
}

function populate_form() {
var xhr= new XMLHttpRequest();
xhr.open('GET', 'get_user_data.php', true);
xhr.onreadystatechange= function() {
if (this.readyState!==4) {
return;
}
if (this.status!==200) {
return;
}
const users = JSON.parse (this.responseText);
table_body = document.getElementById('user_table').getElementsByTagName('tbody')[0];
users.forEach(updateTable);

function updateTable (user) {
var row = table_body.insertRow(0);
var cell0 = row.insertCell(-1);
cell0.innerHTML = user['user_id'] + '<input type="hidden" id="user_id_' + user['user_id'] + '" name="user_id" value="' + user['user_id'] + '" />';
var cell1 = row.insertCell(1);
cell1.innerHTML = '<input type="text" id="first_name_' + user['user_id'] + '" name="first_name" value="' + user['first_name'] + '" />';
var cell2 = row.insertCell(2);
cell2.innerHTML = '<input type="text" id="surname_' + user['user_id'] + '" name="surname" value="' + user['surname'] + '" />';
var cell3 = row.insertCell(3);
cell3.innerHTML = '<input type="button" value="Update" onclick="submit_change(' + user['user_id'] + ')" />';
}
};
xhr.send();
}
51 changes: 51 additions & 0 deletions vulnerabilities/authbypass/change_user_details.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';

dvwaDatabaseConnect();

/*
On impossible only the admin is allowed to retrieve the data.
*/

if (dvwaSecurityLevelGet() == "impossible" && dvwaCurrentUser() != "admin") {
print json_encode (array ("result" => "fail", "error" => "Access denied"));
}

if ($_SERVER['REQUEST_METHOD'] != "POST") {
$result = array (
"result" => "fail",
"error" => "Only POST requests are accepted"
);
echo json_encode($result);
exit;
}

try {
$json = file_get_contents('php://input');
$data = json_decode($json);
if (is_null ($data)) {
$result = array (
"result" => "fail",
"error" => 'Invalid format, expecting "{id: {user ID}, first_name: "{first name}", surname: "{surname}"}'

);
echo json_encode($result);
exit;
}
} catch (Exception $e) {
$result = array (
"result" => "fail",
"error" => 'Invalid format, expecting \"{id: {user ID}, first_name: "{first name}", surname: "{surname}\"}'

);
echo json_encode($result);
exit;
}

$query = "UPDATE users SET first_name = '" . $data->first_name . "', last_name = '" . $data->surname . "' where user_id = " . $data->id . "";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

print json_encode (array ("result" => "ok"));
exit;
?>
41 changes: 41 additions & 0 deletions vulnerabilities/authbypass/get_user_data.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';

dvwaDatabaseConnect();

/*
On high and impossible, only the admin is allowed to retrieve the data.
*/
if ((dvwaSecurityLevelGet() == "high" || dvwaSecurityLevelGet() == "impossible") && dvwaCurrentUser() != "admin") {
print json_encode (array ("result" => "fail", "error" => "Access denied"));
}

$query = "SELECT user_id, first_name, last_name FROM users";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query );

$guestbook = '';
$users = array();

while ($row = mysqli_fetch_row($result) ) {
if( dvwaSecurityLevelGet() == 'impossible' ) {
$user_id = $row[0];
$first_name = htmlspecialchars( $row[1] );
$surname = htmlspecialchars( $row[2] );
} else {
$user_id = $row[0];
$first_name = $row[1];
$surname = $row[2];
}

$user = array (
"user_id" => $user_id,
"first_name" => $first_name,
"surname" => $surname
);
$users[] = $user;
}

print json_encode ($users);
exit;
?>
82 changes: 82 additions & 0 deletions vulnerabilities/authbypass/help/help.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<div class="body_padded">
<h1>Help - Authorisation Bypass</h1>

<div id="code">
<table width='100%' bgcolor='white' style="border:2px #C0C0C0 solid">
<tr>
<td><div id="code">
<h3>About</h3>
<p>
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.
</p>

<p>
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.
</p>

<br /><hr /><br />

<h3>Objective</h3>
<p>Your goal is to test this user management system at all four security levels to identify any areas where authorisation checks have been missed.</p>
<p>The system is only designed to be accessed by the admin user, so have a look at all the calls made while logged in as the admin, and then try to reproduce them while logged in as different user.</p>
<p>If you need a second user, you can use <i>gordonb / abc123</i>.

<br /><hr /><br />

<h3>Low Level</h3>
<p>Non-admin users do not have the 'Authorisation Bypass' menu option.</p>
<p>Spoiler: <span class="spoiler">Try browsing directly to /vulnerabilities/authbypass/</span>.</p>


<br />

<h3>Medium Level</h3>
<p>The developer has locked down access to the HTML for the page, but have a look how the page is populated when logged in as the admin.</p>
<p>Spoiler: <span class="spoiler">Try browsing directly to /vulnerabilities/authbypass/get_user_data.php to access the API which returns the user data for the page.</span></p>

<br />

<h3>High Level</h3>
<p>Both the HTML page and the API to retrieve data have been locked down, but what about updating data? You have to make sure you test every call to the site.</p>
<p>Spoiler: <span class="spoiler">GET calls to retrieve data have been locked down but the POST to update the data has been missed, can you figure out how to call it?</span></p>

<p>Spoiler: <span class="spoiler">This is one way to do it:</p>

<pre><span class="spoiler">fetch('change_user_details.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ 'id':1, "first_name": "Harry", "surname": "Hacker" })
}
)
.then((response) => response.json())
.then((data) => console.log(data));
</span></pre>

<br />

<h3>Impossible Level</h3>
<p>
Hopefully on this level all the functions correctly check authorisation before allowing access to the data.
</p>
<p>
There may however be some non-authorisation related issues on the page, so do not write it off as fully secure.
</p>
</div></td>
</tr>
</table>

</div>

<br />

<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/05-Authorization_Testing/02-Testing_for_Bypassing_Authorization_Schema' ); ?></p>
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/04-Authentication_Testing/04-Testing_for_Bypassing_Authentication_Schema' ); ?></p>
<p>Reference: <?php echo dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-top-ten/2017/A2_2017-Broken_Authentication' ); ?></p>

</div>
77 changes: 77 additions & 0 deletions vulnerabilities/authbypass/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';

dvwaPageStartup( array( 'authenticated', 'phpids' ) );

$page = dvwaPageNewGrab();
$page[ 'title' ] = 'Vulnerability: Authorisation Bypass' . $page[ 'title_separator' ].$page[ 'title' ];
$page[ 'page_id' ] = 'authbypass';
$page[ 'help_button' ] = 'authbypass';
$page[ 'source_button' ] = 'authbypass';
dvwaDatabaseConnect();

$method = 'GET';
$vulnerabilityFile = '';
switch( dvwaSecurityLevelGet() ) {
case 'low':
$vulnerabilityFile = 'low.php';
break;
case 'medium':
$vulnerabilityFile = 'medium.php';
break;
case 'high':
$vulnerabilityFile = 'high.php';
break;
default:
$vulnerabilityFile = 'impossible.php';
$method = 'POST';
break;
}

require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/authbypass/source/{$vulnerabilityFile}";

$page[ 'body' ] .= '
<div class="body_padded">
<h1>Vulnerability: Authorisation Bypass</h1>
<p>This page should only be accessible by the admin user. Your challenge is to gain access to the features using one of the other users, for example <i>gordonb</i> / <i>abc123</i>.</p>
<div class="vulnerable_code_area">
<div style="font-weight: bold;color: red;font-size: 120%;" id="save_result"></div>
<div id="user_form"></div>
<p>
Welcome to the user manager, please enjoy updating your user\'s details.
</p>
';

$page[ 'body' ] .= "
<script src='authbypass.js'></script>
<table id='user_table'>
<thead>
<th>ID</th>
<th>First Name</th>
<th>Surname</th>
<th>Update</th>
</thead>
<tbody>
</tbody>
</table>
<script>
populate_form();
</script>
";

$page[ 'body' ] .= '
' .
$html
. '
</div>
</div>';

dvwaHtmlEcho( $page );

?>
Loading

0 comments on commit 29dab22

Please sign in to comment.