文章目录
  1. 1. 分类
  2. 2. 检测方法
  3. 3. XSS防御
    1. 3.1. 使用HttpOnly
    2. 3.2. 输入检查
    3. 3.3. 输出检查
  4. 4. 参考

XSS的本质是一种“HTML 注入”, 用户的数据被当成了HTML代码的一部分来执行,从而混淆了原本的语义,产生了新的语义。

分类

  • 反射型XSS
    简单地把用户输入数据“反射”给浏览器。 一般需要诱导用户点击恶意链接, 非持久化。

    1
    2
    3
    <?php
    echo "<p>欢迎您, ".$username."!</p>";
    ?>

    如果这里的username变量,是通过获取用户输入的,

    1
    $username = $_GET["name"];

    那么可以制造恶意链接欺骗用户点击, 触发恶意代码

    1
    http://localhost/test.php?name=<script>alert(/我的名字是张三/)</script>
  • 存储型XSS
    将用户输入的数据“存储”在服务器端。用户访问普通链接即可中招, 容易造成蠕虫。
    如上文例子, 如果 username 已经存储于数据库,用户直接访问普通链接也会中招。

    1
    $username = "<script>alert(/我的名字是张三/)</script>"

    存储型XSS具有较强的稳定性

  • DOM Based XSS
    通过修改页面DOM节点数据信息而形成的XSS跨站脚本攻击

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <script>
    function xsstest()
    {

    var str = document.getElementById("input").value;
    document.getElementById("output").innerHTML = "<img src='"+str+"'></img>";
    }
    </script>


    <input type="text" id="input" size=50 value="" />
    <input type="button" value="提交" onclick="xsstest()" />

    通过构造如下数据,输入

    1
    #’ onerror=’javascript:alert(/DOM Based XSS Test/)

    在浏览器中提交后,代码被执行,出现了弹窗提示

    DOM Based XSS 效果上来说也是反射性XSS

检测方法

通常有一些方式可以测试网站是否有正确处理特殊字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
><script>alert(document.cookie)</script>

='><script>alert(document.cookie)</script>

"><script>alert(document.cookie)</script>

<script>alert(document.cookie)</script>

<script>alert(vulnerable)</script>

%3Cscript%3Ealert('XSS')%3C/script%3E

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

<img src="javascript:alert('XSS')">

<img src="http://xxx.com/yyy.png" onerror="alert('XSS')">

<div style="height:expression(alert('XSS'),1)" />(这个仅限 IE 有效)

XSS防御

使用HttpOnly

  • 解决 XSS 后的 Cookie 劫持攻击。
  • 在支持 HttpOnly cookies 的浏览器中,JavaScript 是无法读取和修改 HttpOnly cookies。

输入检查

  • 过滤特殊字符。“XSS filter”
  • 不够智能,有可能过滤用户需要的数据。如: 1+1 > 2 ==> 1+1 2

输出检查

  • 针对 HTML 代码: HtmlEncode
    它的作用是将字符转换成HTMLEntities,对应的标准是ISO88591。
    对了对抗XSS,在HtmlEncode中至少要转换以下字符:

    1
    2
    3
    4
    5
    6
    & => &amp;  
    < => &lt;
    > => &gt;
    “ => &quot;
    ‘ => &#x27;
    / => &#x2f;

    相关防御:
    一般来说, 用户可控制变量输出是在 HTML 代码, 如:

    1
    2
    3
    4
    5
    <!--HTML 标签中输出-->
    <div>$var</div>

    <!--HTML HTML 属性中输出-->
    <div name=”$var”></div>

    需要执行恶意代码都需要包含
    <script></script>
    对应这种情况 我们必须进行HtmlEncode

  • 针对 JavaScript 代码: JavaScriptEncode
    与 HtmlEncode 编码方式不同, 它需要使用“\” 对特殊字符进行转义。
    要求输出的变量必须包含在引号内部。 如: var y = ‘ “ ‘ + escapeJavascript($evil) + ’ ” ’

    相关防御:

    1
    2
    3
    4
    5
    <!--在script标签中输出-->
    <script>$var </script>

    <!--在事件中输出-->
    <a onclick="onclick=$var"></a>

    此类注入恶意代码可直接运行,需要加入JavascriptEncode, 并确保输出变量在引号中

  • 防御 DOM Based XSS
    对于浏览器来说, htmlparser 会优先于 JavaScript Parse 执行。解析过程HtmlEncode的字符先被解码,然后执行JavaScript事件。

    1. 在 $var 输出到 <script>时,应该执行一次 javascriptencode
    2. 如果javascript将输出变量写入DOM时,根据上述场景进行再一次encode (HtmlEncode or JavaScriptEncode)

参考

  • 《白帽子讲 Web 安全》
文章目录
  1. 1. 分类
  2. 2. 检测方法
  3. 3. XSS防御
    1. 3.1. 使用HttpOnly
    2. 3.2. 输入检查
    3. 3.3. 输出检查
  4. 4. 参考