DVWA
XSS(Reflected) 反射型XSS
一、Low 级别
没有任何的安全防护措施
输入 <script>alert('hack')</script>
,直接就执行了我们的 js 代码:
我们的js代码直接插入到了网页源代码中:
源代码:
<?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参数是否为空,如果不为空的话就直接打印出来,并没有对name参数做任何的过滤和检查。
二、Medium 级别
对
<scripit>
标签进行过滤
源代码:
<?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>";
}
?>
漏洞利用
大写绕过:<SCRIPT>alert('xss')</SCRIPT>
三、High 级别
使用正则表达式直接把
<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t
给过滤了;
正则表达式:/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i
*代表一个或多个任意字符;
i 代表不区分大小写。
源代码:
<?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>";
}
?>
漏洞利用
通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码。
<img src='#' onerror='alert(/xss/)'>
四、Impossible 级别
源代码:
<?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();
?>
代码先判断name是否为空,不为空的话然后验证其token,来防范CSRF攻击。然后再用htmlspecialchars函数将name中的预定义字符转换成html实体,这样就防止了我们填入标签;
- htmlspecialchars(string)函数
把预定义的字符 “<” (小于)、 “>” (大于)、& 、‘’、“” 转换为 HTML 实体,防止浏览器将其作为HTML元素;
当我们输入 <script>alert('/xss/')</script>
时,因为 htmlspecialchars 函数会将 <
和 >
转换成html实体,并且 ${name}
取的是 $name
的值,然后包围在<pre></pre>
标签中被打印出来,所以我们插入的语句并不会被执行。
表单提交的过程中,user_token也一并提交了,和服务器端的session_token做验证,防止CSRF攻击。我们输入的代码,直接被当成html文本给打印出来了,并不会被当成js脚本执行: