9
作者:Larry Lu
译者:前端小智
来源:stackabuse

有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

随着网络上的 Web 应用越来越多,为了提升安全性,现在跟安全性有关的 HTTP header 也是多到记不得。因为各种不同功能的 HTTP header 实在太多,所以这边想要介绍几个比较简单、好设定的安全性 headers ,只要把这些 headers 加进去,网站就会突然变安全哦~

Content Security Policy (CSP)

首先是历史悠久的 CSP,这个 header 是用来限制浏览器只能从哪些地方载入资源。譬如说我设定 Content-Security-Policy: default-src larry.com,就代表我限制浏览器只能从 larry.com 这个域名载入图片、CSS、字体等等各种资源

当然想设定很多个域名也是可以的,只要一直往下接就可以了。下图开发者工具的内容是我上 Github 首页时 response header 裡的 CSP 设定,他就是把 uploads.github.comapi.github.com 等等很多个网域都加进去,虽然看起来很冗长,但至少有一个白名单,不会莫名其妙载入其他域名的东西

image.png

如果想针对不同类型的资源有不同的 policy(虽然比较麻烦但会更安全),那也可以写成 Content-Security-Policy: img-src a.com; font-src b.com 的形式,那浏览器就会知道你希望只能从 a.com 载入图片、从 b.com 载入字体

想看还有哪些属性可以设定可以参考 MDN 上的 Directives

那限制域名有什么用呢?假如哪天黑客在我的网站上发现了一个 XSS 漏洞,让他可以在首页的 HTML 中加入一段 <script src=“hacker.com/evil.js”>,那每一个使用者到我的网站时浏览器就会载入恶意的 evil.js,让黑客可以做一些坏坏的事情,譬如说重新导向、偷走帐号密码等等

但如果有把 CSP 设定成 Content-Security-Policy: default-src larry.com 的话,浏览器就会拒绝载入 evil.js(下图),因为那个脚本是从 hacker.com 来的。因此虽然 CSP 不能完全防堵 XSS,但能减轻 XSS 造成的影响,因为如果攻击者不能从外部载入恶意资源,那可以做的事情也相对比较少一点

image.png

Strict Transport Security (HSTS)

HSTS 的全名是 HTTP Strict Transport Security,听过这个 header 的人可能比较少一点,他是用来强制浏览器只能使用安全的 HTTPS 协定跟网站进行连线,而不能使用 HTTP

譬如说很多网站其实用 HTTP 跟 HTTPS 都连得上,但考量到安全性,当然是希望使用者都走 HTTPS。这时只要在 header 裡加上 Strict-Transport-Security: max-age=31536000; includeSubDomains,那在往后的 31536000 秒内(其实就是一年啦XD),只要使用者的浏览器看到这个域名或他的子域名,就会全部改成用 HTTPS 进行连线,真的是很方便呢

也因为现在网站几乎都有 HTTPS 了,所以像平常会用到的 Google、Medium、Facebook 都可以看到 HSTS 的踪迹,只是大家设定的 max-age 稍有不同,比较常看到的大概会是 31536000(一年)、15552000(180 天)这类的数字

image.png

X-Content-Type-Options

听过这个 header 的人可能又更少了,在讲这个 header 之前,得先来谈谈什麽是 content sniffing:一般来说浏览器会通过 Content-Type 来判断请求到的资源是什麽类型,像透过 <script src="script.js"> 拿到的 Content-Type 一般都是 text/javascript,因此浏览器看到之后就会拿来执行

image.png

但有些网站(尤其是十几二十年前的旧网站)在开发时并没有把 Content-Type 设好,导致某些 JS 档的 Content-Type 是 text/plain,也就是纯文字档。为了让这些网站可以顺利运作,浏览器除了参考 Content-Type 之外,也会做 content sniffing 从档案内容分析是什麽类型,如果分析出是 JS 那就会拿去执行,这样旧网站才不会坏掉

但 sniffing 这个动作看似贴心,却也是一个弱点。譬如说有些网站允许使用者上传资源,那攻击者就可以恶意上传一些有 JS 特性的 JPG 档(这些图片会被浏览器判断成脚本)。接著想办法让这张图片被载入到前端来,导致裡面的恶意脚本被执行,造成 XSS 攻击

为了防止浏览器在那边乱猜资源的 Content-Type 是什麽(而且麻烦的是每个浏览器猜的方式还不太一样),我们要在 headers 裡面加上 X-Content-Type-Options: nosniff 告诉浏览器直接用 header 裡面提供的 Content-Type 就好,不要在那边瞎猜,如此一来就不会再有纯文字、图片被判断成脚本这种事

image.png

但也因为加了 nosniff,所以务必要注意各种资源的 Content-Type 有没有设定好,因为浏览器不会帮你猜,如果你真的把 JS、CSS 的 Content-Type 设错,那浏览器就不会把它跑起来,网站看起来也就怪怪的

X-Frame-Options

平常在写网页时,若是想把其他网页的内容拿过来用(下图),可以用 <iframe src="https://website.com"> 把他嵌入进来;反之,若是别人想把我做的网站嵌入到他的网站裡面也是可以的

image.png

那这样会有什麽资安疑虑呢?万一有个坏坏网站,他通过 iframe 把气象局网页嵌入进去后,用 CSS 把那个 iframe 调成透明的,然后在透明的 iframe 背后放一些按钮(下图)。那使用者在坏坏网站上点击我很帅、我帅爆时,就会不小心点到气象局的网站,这种攻击就称作 Clickjacking

image.png

如果点到的只是气象局网站那不会怎麽样,反正怎麽点也就是那样。但万一被嵌入的是某银行的网站呢?那使用者可能就会被精心设计的按钮给骗到,在无意识的情况下就按了 iframe 裡面的转帐、提款等等按钮

为了要避免这类问题,最好的方法就是加上 X-Frame-Options: deny 这个 header,意思是告诉浏览器说我这个网站不想被嵌入(为了安全起来大部分的银行都会加这个 header)

image.png

所以当我想在自己的网站上把玉山银行的页面嵌入进来时,浏览器就会喷出ebank.esunbank.com.tw 不允许在被别的网站嵌入”的错误。因为玉山银行的页面根本不允许被嵌入,也就避免了基于 iframe 的 Clickjacking 攻击

总结

今天介绍了 CSP、HSTS、X-Content-Type-Options 跟 X-Frame-Options 总共四个跟安全性有关的 HTTP headers,这些 headers 不只用起来轻松简单,加上去根本不用十分钟,而且又可以大幅提高安全性,所以已经是网站开发不可缺少的 HTTP headers 了

除了这四个之外其实还有 X-XSS-Protection、Expect-CT、Public-Key-Pins、Feature-Policy 等等很多 header,但因为有些效果没那麽大、有些则是已经被宣佈弃用了,所以这边就暂且不提,有兴趣可以自己到 Owasp Secure Headers 上面看看~


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

https://medium.com/starbugs/m...

交流

有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。


王大冶
68k 声望104.9k 粉丝