XSS

跨网站指令码(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程式的安全漏洞攻击,是代码注入的一种。它允许恶意使用者将程式码注入到网页上,其他使用者在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及使用者端脚本语言。

XSS 分为三种:反射型,存储型和 DOM-based

如何攻击

XSS 通过修改 HTML 节点或者执行 JS 代码来攻击网站。

例如通过 URL 获取某些参数

  1. <!-- http://www.domain.com?name=<script>alert(1)</script> -->
  2. <div>{{name}}</div>

上述 URL 输入可能会将 HTML 改为 <div><script>alert(1)</script></div> ,这样页面中就凭空多了一段可执行脚本。这种攻击类型是反射型攻击,也可以说是 DOM-based 攻击。

也有另一种场景,比如写了一篇包含攻击代码 <script>alert(1)</script> 的文章,那么可能浏览文章的用户都会被攻击到。这种攻击类型是存储型攻击,也可以说是 DOM-based 攻击,并且这种攻击打击面更广。

如何防御

最普遍的做法是转义输入输出的内容,对于引号,尖括号,斜杠进行转义

  1. function escape(str) {
  2. str = str.replace(/&/g, "&amp;");
  3. str = str.replace(/</g, "&lt;");
  4. str = str.replace(/>/g, "&gt;");
  5. str = str.replace(/"/g, "&quto;");
  6. str = str.replace(/'/g, "&#39;");
  7. str = str.replace(/`/g, "&#96;");
  8. str = str.replace(/\//g, "&#x2F;");
  9. return str
  10. }

通过转义可以将攻击代码 <script>alert(1)</script> 变成

  1. // -> &lt;script&gt;alert(1)&lt;&#x2F;script&gt;
  2. escape('<script>alert(1)</script>')

对于显示富文本来说,不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。

  1. var xss = require("xss");
  2. var html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>');
  3. // -> <h1>XSS Demo</h1>&lt;script&gt;alert("xss");&lt;/script&gt;
  4. console.log(html);

以上示例使用了 js-xss 来实现。可以看到在输出中保留了 h1 标签且过滤了 script 标签

CSP

内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。

我们可以通过 CSP 来尽量减少 XSS 攻击。CSP 本质上也是建立白名单,规定了浏览器只能够执行特定来源的代码。

通常可以通过 HTTP Header 中的 Content-Security-Policy 来开启 CSP

  • 只允许加载本站资源

    1. Content-Security-Policy: default-src self
  • 只允许加载 HTTPS 协议图片

    1. Content-Security-Policy: img-src https://*
  • 允许加载任何来源框架

    1. Content-Security-Policy: child-src 'none'

更多属性可以查看 这里