浅析前端安全之 XSS
Posted 前端深夜告解室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析前端安全之 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>
下面是从 https://dev.w3.org/html5/html-author/charref截取的一部分字符和转义编码的表:
说到转义,我们从实际场景出发,来看看我们在 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;
https://content-security-policy.com/
CSP 提供了很多指令用来约束不同资源的来源,比如这里我列举了一部分。
block-all-mixed-content:HTTPS 网页不得加载 HTTP 资源(浏览器已经默认开启)
upgrade-insecure-requests:自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议
plugin-types:限制可以使用的插件格式,比如禁用 flash, java applet
sandbox:浏览器行为的限制,比如不能有弹出窗口等。
安全意识
最后一点,正如这个图片的标语一样,我们需要时刻保持安全意识。虽然安全始终是相对的,但如果我们通过提高开发中的安全意识,也就增加攻击者发起攻击的成本。
参考链接
https://www.hacksplaining.com/prevention/xss-stored
https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
https://developers.google.com/web/fundamentals/security/csp/
https://content-security-policy.com/
以上是关于浅析前端安全之 XSS的主要内容,如果未能解决你的问题,请参考以下文章