跨站脚本×××(XSS)是客户端脚本安全中的头号大敌。OWASP TOP 10 威胁多次把 XSS 列在榜首。

1.XSS 简介

  跨站脚本×××(Cross Site Script),本来缩写是CSS,但是为了和层叠样式表(Cascading Style Sheet,CSS)有所区别,所以在安全领域叫做 “ XSS ”。

  XSS ×××,通常指×××通过 “HTML 注入” 篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种×××。在一开始,这种×××的演示案例是跨域的,所以叫做 “ 跨站脚本 ”。现今,由于 Javascript 的强大功能以及网站前端用的复杂化,是否跨域已经不再重要。但是由于历史原因,XSS 这个名字却一直保留下来。


2. 自己搭建个 DVWA   (由于个别原因,这次就写反射型 XSS)

 反射型 XSS

 面对四种级别的代码进行分析。


 LOW

 服务器端核心代码

     

<?php 
    // Is there any input? 
    if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { 
        // Feedback for end user 
        echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; 
    }  
 ?>

可以看到,代码直接引用了name参数,并没有任何的过滤与检查,存在明显的XSS漏洞。

漏洞利用

输入<script>alert(/XSS/)</script>,成功弹框:

14824823248355.png


Medium

服务器端核心代码

<?php // 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函数将输入中的<script>删除,这种防护机制是可以被轻松绕过的。

漏洞利用

1.双写绕过

输入 <sc<script>ript>alert(/xss/)</script>,成功弹框:

14824824105236.png

2.大小写混淆绕过

输入<ScRipt>alert(/xss/)</script>,成功弹框:

14824824446366.png


High

服务器端核心代码


<?php // 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>"; 
} 
?>

可以看到,High级别的代码同样使用黑名单过滤输入,preg_replace()函数用于正则表达式的搜索和替换,这使得双写绕过、大小写混淆绕过(正则表达式中i表示不区分大小写)不再有效。

漏洞利用

虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码。

输入<img src=1 οnerrοr=alert(/xss/)>,成功弹框:

14824825209982.png


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(); 
?>

可以看到,Impossible级别的代码使用htmlspecialchars函数把预定义的字符&、 、<、>转换为HTML实体,防止浏览器将其作为HTML元素。