浅析前端安全之 XSS

浅析前端安全之 XSS

本文是我在掘金技术社区主办的 JTalk 线下活动《前端安全大起底 | 美团技术团队专场》 活动上的分享整理。

本篇文章想讲讲 XSS 的产生和防御,主要面向前端安全了解不多的同学。首先,就不直接照搬 XSS 的定义,我想通过下面一个实例来讲讲 XSS 攻击如何进行的,希望会让对前端安全了解不多的同学更容易理解。

从一个实例讲起

这里我准备了一个 web im demo,在这个 IM 里实现了文字,链接,头像等功能



但是在实现这些功能背后,隐藏了严重的安全问题,接下来,我们来看看这个 bug 是怎么样的,先来看看

可以看到这 IM 支持图片,文字交流,如果我输入一个图片的 html 标签字符,对方就能收到图片。

可是,如果输入的是这样的的 html 标签字符,就会有意料之外的效果

<img src="1" onerror="alert(document.cookie)"> 



在看到对方的窗口调用了alert,并且内容中是自己的 cookie 信息,这通常意味着我们的 cookie 中的用户认证凭据被盗取了。 当然,这里使用 alert 是为了展示脚本的执行能力,通常情况,黑客一旦通过确认某处存在漏洞,那之后利用这个漏洞的所能做的事情就很多了。



看到消息气泡模板,找到问题所在了,这里使用了 v-html 但是却没有做任何安全处理。对于具体安全的处理方式,我们在后面细说。

<div class="bubble">
    <p v-html="data.message"></p>
</div>

刚才通过这个简单的 Case,简单介绍了 XSS 的产生和利用。

在常规分类中,XSS 共分为这三种:

  • 存储型
  • 反射型
  • DOM based

我认为,前端应用的复杂度不断提升的今天,这三个分类可能有不少融合的场景。



XSS 的风险

会话劫持

  • 将 cookie 或 token 等类似令牌数据上报给黑客,黑客就能以受害用户的权限进行操作

信息泄露

  • 个人隐私泄露
  • 商业机密泄露

进一步的攻击

  • 运行恶意脚本的用户浏览器可能被操控继续攻击其他目标
  • 有黑客利用 XSS 嗅探内网服务,然后发起下一步的攻击

如何防御 XSS

转义

网页由HTML组成,通常在模板文件中描述,并在页面呈现时嵌入动态内容。存储的XSS攻击利用对来自后端数据存储的动态内容的不当处理。攻击者通过插入一些JavaScript代码来滥用可编辑字段,当另一用户访问该页面时,该代码将在浏览器中执行。


<head>
    <meta charset="UTF-8">
    <title> {{ title }} </title>
</head>



下面是从 dev.w3.org/html5/html-a 截取的一部分字符和转义编码的表



说到转义,我们从实际场景出发,来看看我们在 nodejs 中常用的几个模板引擎的实际用例,左边上部分是 ejs ,在 ejs 中 <%=%> 是输出转义结果,<%- %> 是不进行转义。下面的 mustache nunjucks 虽然语法不一样,都一样提供了转义和不转义的功能。所以在绝大多数场景,请使用转义输出。


内容白名单

内容白名单,是一个比较宽泛的概念。比如,接着说刚才的富文本的需求,那么我们的内容白名单其实就是 HTML 标签、属性等的一个白名单。比如常规文章、评论富文本,肯定是不需要 <script> 标签的。要去除内容中具有隐患的 script 标签,最简单的方案肯定是替换掉 script 的黑名单策略,但是黑名单意味着未知的风险。

刚才说道不推荐是用黑名单对某些关键词进行过滤。就像这里的这个例子,我如果使用风险关键词替换来实现安全过滤。

这里我实现的是将所有的<script> 替换为空字符。左边的场景能够拦截清除了输入的 <script>, 但右边的场景遇到 <scr<script>ipt>,就不能适用了。



比如常见的富文本场景中,推荐对标签内容进行白名单(标签、属性等)过滤。

比如这里是一个使用 xss 的库对 HTML 做白名单过滤的简单示例:

const xss = require("xss")
const options = {
    whiteList: {
        a: ["href", "title", "target"],
        p: [],
        span: [],
        h1: []
    }
}
const myxss = new xss.FilterXSS(options);
const result = myxss.process('<script>alert("xss");</script>')

Content Security Policy

内容安全性政策 (CSP) 是一个可显著降低现代浏览器中 XSS 攻击的风险和影响的防护功能。 它允许网页的作者控制可以从哪里加载和执行JavaScript(和其他资源)。XSS攻击依赖于攻击者能够在用户的网页上运行恶意脚本 - 通过 <script><html> 页面标记内的某处插入内联标记,或者通过诱骗浏览器从恶意第三方域加载JavaScript。 通过在响应头中设置内容安全策略,您可以告诉浏览器永远不会执行内嵌 JavaScript,并锁定哪些域名可以为页面托管 JavaScript

使用方式

  • meta
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' ssl.google-analytics.com;">
  • header
Content-Security-Policy: default-src 'none'; script-src 'self' ssl.google-analytics.com;



content-security-policy.com

CSP 提供了很多指令用来约束不同资源的来源,比如这里我列举了一部分。

除了资源来源的指令还有几个特殊的指令,比如 report-uri 可以用于指定一个违反 csp 一些异常情况上报地址,让开发者能够了解到在浏览器的异常情况。

  • block-all-mixed-content:HTTPS 网页不得加载 HTTP 资源(浏览器已经默认开启)
  • upgrade-insecure-requests:自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议
  • plugin-types:限制可以使用的插件格式,比如禁用 flash, java applet
  • sandbox:浏览器行为的限制,比如不能有弹出窗口等。

安全意识

最后一点,正如这个图片的标语一样,我们需要时刻保持安全意识。虽然安全始终是相对的,但如果我们通过提高开发中的安全意识,也就增加攻击者发起攻击的成本。



参考链接

hacksplaining.com/preve

owasp.org/index.php/Cro

developers.google.com/w

content-security-policy.com

编辑于 2018-06-21

文章被以下专栏收录