XSS 和 CSRF

作者: TooooBug
链接:http://www.imooc.com/article/18069
来源:慕课网

XSS 全称 Cross Site Scripting ,跨站脚本攻击,因为 CSS 这名字老早就被样式表拿走了,所以只好叫 XSS 了。

XSS 是什么鬼

XSS 比如我只想在页面上显示一个名字:

<span class="name">{{name}}</span>

但是,如果我的名字是长这样的:

星辰<script>alert('SB')</script>

这时候就好玩了:

<span class="name">星辰<script>alert('SB')</script></span>

你看,页面中凭空多了一段脚本。

JS可以干嘛?用户登录用的JS吧,读取资料用的JS吧,点击买东西、消费用的JS吧,查用户有多少钱用的JS吧,基于 Cookies 也可以读写吧。

XSS 怎么防御

一个经典的防御方法就是对内容进行转义和过滤,比如

var escapeHtml = function(str) {
    if(!str) return '';
    str = str.replace(/&/g, '&amp;');
    str = str.replace(/</g, '&lt;');
    str = str.replace(/>/g, '&gt;');
    str = str.replace(/"/g, '&quto;');
    str = str.replace(/'/g, '&#39;');
    // str = str.replace(/ /g, '&#32;');
    return str;
};

var name = escapeHtml(`<script>alert('SB')</script>`);

此时 name 会变成

&lt;script&gt;alert(&#39;SB&#39;)&lt;/script&gt;

这样就会原样显示出来,再也无法耍流氓啦。

当然,富文本还要更麻烦一些,因为要保留一部分标签和属性,要不然全变纯文本了,就不富了。这种情况一般通过黑名单进行过滤,或者白名单放行。即只允许一部分指定的标签和属性,其它的全部转义掉。

CSP 大法

前面转义的方法的出发点,是让用户的输入不要变成程序,输入的什么就让它输出成什么。

事实上现代浏览器为我们带来了一个全新的安全策略,叫作内容安全策略,Content Security Policy,简称CSP。CSP的思路跟转义不一样,它的着手点是,如果一段代码变成了程序,我们是否应该运行它。或者更准确一点说,它实际上是定义页面上哪一些内容是可被信任的,哪一些内容是不被信任的。

因为我们自己的脚本是预先就知道并放在页面上的,所以我们可以设置好信任关系,当有 XSS 脚本出现时,它并不在我们的信任列表中,因此可以阻止它运行。

它的具体使用方式是在 HTTP 头中输出 CSP 策略:

Content-Security-Policy: <policy-directive>; <policy-directive>

从语法上可以看到,一个头可以输出多个策略,每一个策略由一个指令和指令对应的值组成。指令可以理解为指定内容类型的,比如script-src指令用于指定脚本,img-src用于指定图片。值则主要是来源,比如某个指定的URL,或者self表示同源,或者unsafe-inline表示在页面上直接出现的脚本等。

详细的指令和值,可以查看MDN相关页面

具体到上面的 XSS 例子,可以使用

Content-Security-Policy: script-src 'self';

这样除了在同一个域名下的JS文件外,其它的脚本都不可以执行了,自然之前 XSS 的内容也就失效啦。简单粗暴有没有?

当然,如果你说,我就是要在页面中放点内联的脚本,不可以么?当然可以啦,CSP 设计的时候也考虑了这些情况,还是相当灵活的。你只需要指定一个 nonce 属性,或者计算一下 hash 值,即可。详细的用法看 MDN 哦。

说实话,用 CSP 来处理 XSS 攻击还是不如转义来得优雅,因为转义可以不影响用户输入输出,不改变内容的本质。但是 CSP 提供了足够简单而又灵活的方式来防御 XSS ,可以很好地作为我们前端 XSS 防御的最后一道防线。

CSRF

CSRF 也是个望文生不到义的词,它的全称是 Cross Site Request Foggy,即跨站请求攻击。虽然也有跨站,但我觉得这个跨站还是相当可以理解的,它真的是从别的网站发起一个请求到我们的网站的。

当一个用户登录我们的网站后,在 Cookies 中会存放用户的身份凭证。在大部分时候,就是一个 SessionId 。当用户下次访问我们的网站的时候,我们用这个凭证识别出用户是谁,有没有登录态。

如果第三方网站的代码请求了我们的网站,会发生什么呢?比如

<img src="//www.example.com/haha" />

虽然它是一张图片,但它确实向www.example.com发了一个请求,如此用户有登录态的话,其实就相当于是用户自己发了一个请求。如果这个地址是一个发表文章、发布微博甚至转账之类的链接,那用户就在不知情的情况下进行了一些操作。这也是比较严重的安全问题。

当然你可能会说,现在谁还这么弱智,把这么敏感的操作用 GET 啊?没错,你可以选择用 POST ,但是这丝毫不能阻止 CSRF 攻击的发生啊。

<iframe name="test"></iframe>
<form target="test" method="post" action="http://www.example.com/haha">
    ...
</form>

当这个表单提交的时候,我们就发了一个 POST 请求。华丽丽的 CSRF 。

CSRF 的常规防御

CSRF 比较常规的防御方式是通过判断来源和加 token。

判断来源比较简单,主要是判断referer这个头,如果不是自己的网站,就返回错误。

加 token 即同样的随机 token,在 cookies 中放一份,在表单中再放一份。这样第三方网站就无法获取到这个 token 是什么。

但是这样做也有一个比较明显的问题,就是无法保证站内用户的体验。虽然你防了站外的攻击,但是也降低了站内用户的体验。具体表现在如果同时打开多个表单,只有最后一个表单能成功提交。

same-site 的 Cookie

回想 CSRF 之所以能够攻击成功,核心原因就在于用户的身份是放在 Cookies 中的,而不管你通过什么方式访问网站,都会带上这个网站的 Cookies ,从第三方来的访问自然也不能例外。

但是,Chrome 在这个问题上给了我们不同的答案,可以放第三方访问时不带 Cookies 。也就是说 Cookies 只有本站能用,来自第三方的访问都不能使用。

具体的使用方式,是在打 Cookie 的时候,加上一个属性:SameSite,它的值有两:

  • strict 任何来自第三方的请求都不能使用 Cookies ,包括通过链接点进来的
  • lex 只有比较敏感的操作不带 Cookies ,比如表单提交

针对 CSRF ,我们可以将 Cookies 设置成SameSite: strict的,这样就可以有效防御 CSRF 了。不过比较可惜的是,目前只有 Chrome 才支持这一属性。希望未来所有浏览器都能跟上脚步。

使用 SameSite 还会面临一个问题,如果用户是点击链接进来的,那么是不能使用登录态的。一般可以考虑将用户不敏感的信息不设置这个属性,点进来仍然可以显示当前用户是谁,但是在请求的时候要求一个比较敏感的 SameSite 的 Cookies。这里需要更多的实践经验来探索。

小结

本文重点讲了 XSS 和 CSRF 这两种比较常见的前端安全问题的防御思路,尤其是如何使用一些新的规范、实现来帮助我们进行防御。希望后面浏览器对这些安全相关防御办法的普及率能再高一些,让前端工程师能花更少的时间写出更安全的代码。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • CSRF(Cross-site request forgery,跨站请求伪造),是通过伪造请求,冒充用户在站内进行...
    07120665a058阅读 2,999评论 1 6
  • XSS是什么?它的全名是:Cross-site scripting,为了和CSS层叠样式表区分所以取名XSS。是一...
    圆心角阅读 497评论 2 0
  • XSS篇: XSS,(cross site scripting),跨站脚本注入,指攻击者利用一些技巧向页面注入脚本...
    TheoLin阅读 2,333评论 0 2
  • xss(cross site script),跨站脚本攻击,简称本应该是css,但是为了避免和css层叠样式表冲突...
    Quilljou阅读 572评论 0 0
  • XSS XSS: Cross-Site Scripting 原理概述: 简单来说 正常用户 A 提交正常内容,显...
    DeeJay_Y阅读 267评论 0 0