CTF特训营:技术详解、解题方法与竞赛技巧
上QQ阅读APP看书,第一时间看更新

3.2 常见XSS漏洞分类

按漏洞成因,一般可以把XSS漏洞分为反射型、存储型、DOM型。

基于上述三种XSS类型,还可以根据输出点的不同,依照输出点的位置分成3类,具体如下。

·输出在HTML属性中。

·输出在CSS代码中。

·输出在JavaScript中。

下面将分别为大家介绍这几种类型。

1.反射型XSS

XSS代码作为客户端输入的内容提交给服务端,服务端解析后,在响应内容中返回输入的XSS代码,最终由浏览器解释执行。原型如下:


<?php
echo 'your input:' . $_GET['input'];
?>

客户端输入的input值未经任何过滤便直接输出,所以攻击者可以提交:


http://example.com/xss.php?input=<script>alert(/xss/)</script> 

在服务端对客户端输入的内容进行解析后,echo语句会将客户端输入的代码完整地输出到HTTP响应中,浏览器解析并执行,如图3-1所示。

图3-1 反射型XSS示例

注意 上方的example.com是经过Burp进行名称转换到虚拟机的,前文1.1节的Burp工程选项介绍中有提到过。

2.存储型XSS

存储型XSS与反射型XSS的区别主要在于提交的XSS代码是否会存储在服务端,下次请求该网页时是否需要再次提交XSS代码。存储型XSS的典型应用有留言板、在线聊天室、邮件服务等,攻击者提交包含XSS代码的留言后,服务端会将其存储于数据库中,其他用户访问网页查看留言时,服务端将从数据库中查询已有留言并将留言内容输出在HTTP响应中,由浏览器对包含恶意代码的响应进行解析执行。原型如下:


<html>
<head>
     <title>GuestBook v1.0</title>
     <meta charset="utf-8">
</head>
<body>
     <form method="post">
          昵称:<input type="text" name="nickname"><br>
          内容:<textarea name="content"></textarea><br>
          <input type="submit" name="submit" value="提交留言">
     </form>
     <hr>
     <?php
          $conn = mysql_connect("localhost","root","root");
          if (!$conn) {
               die('Could not connect: ' . mysql_error());
          }
          mysql_select_db("guestbook", $conn);
          if (isset($_POST['submit'])) {
               $nickname = $_POST['nickname'];
               $content = $_POST['content'];
               mysql_query("INSERT INTO guestbook (nickname, content) VALUES ('$nickname', '$content')");
          }
          $result = mysql_query("SELECT * FROM guestbook");
          while($row = mysql_fetch_array($result)) {
               echo $row['nickname'] . ": " . $row['content'] . '<br>';
          }
          mysql_close($conn);
     ?>
</body>
</html>

攻击者提交留言<script>alert(/xss/)</script>后,服务端存储留言,其他用户访问网页时执行恶意代码,如图3-2所示。

图3-2 存储型XSS示例

3.DOM XSS

DOM XSS与反射型XSS、存储型XSS的主要区别在于DOM XSS的XSS代码不需要服务端解析响应的直接参与,触发XSS的是浏览器端的DOM解析。原型如下:


<html>
<head>
        <title>DOM XSS</title>
        <meta charset="utf-8">
</head>
<body>
        <div id="area"></div>
        <script>
                document.getElementById("area").innerHTML = unescape(location.hash);
        </script>
</body>
</html>

代码中服务端未做任何操作,而客户端的JavaScript代码动态地将location.hash赋给document.getElementById("area").innerHTML,导致了这个DOM XSS,使用方法如下:


http://example.com/dom.html#<img src=x onerror='alert(/xss/)'>

执行结果如图3-3所示。

图3-3 DOM XSS示例

4.输出在HTML标签中

原型如下:


<input name="user" value="{{ your input }}"/>

XSS攻击Payload输出在HTML属性中时,攻击者需要在闭合相应的HTML属性后注入新属性,或者在闭合标签后直接注入新标签,如输入:


" onclick="alert(/xxs/)

闭合前面的value属性,注入新的onclick属性,则会输出:


<input name="user" value="" onclick="alert(/xss/)"/>

或输入:


"><script>alert(/xss/)</script>

直接闭合input标签,注入新的script标签,则会输出:


<input name="user" value=""><script>alert(/xss/)</script>"/>

5.输出在CSS代码中

原型如下:


<style type="text/css">
body {
    color: {{ your input }};
}
</style>

XSS攻击Payload输出在CSS代码中时,攻击者需要闭合相应的CSS代码,如输入:


#000; background-image: url('javascript:alert(/xss/)')

闭合前面的color属性,注入background-image属性,则会输出:


<style type="text/css">
body {
    color: #000; background-image: url('javascript:alert(/xss/)');
}
</style>

6.输出在Javascript代码中

原型如下:


<script>
    var name='{{ your input }}';
</script>

XSS攻击Payload输出在Javascript代码中时,攻击者需要闭合相应的Javascript代码,如输入:


'+alert(/xss/)+'

闭合前面的单引号,注入攻击代码,则会输出:


<script>
var name=''+alert(/xss/)+'';
</script>