当我们说“前端安全问题”的时候,我们在说什么
“安全”是个很大的话题,各种安全问题的类型也是种类繁多。如果我们把安全问题按照所发生的区域来进行分类的话,那么所有发生在后端服务器、应用、服务当中的安全问题就是“后端安全问题”,所有发生在浏览器、单页面应用、Web页面当中的安全问题则算是“前端安全问题”。比如说,SQL注入漏洞发生在后端应用中,是后端安全问题,跨站脚本攻击(XSS)则是前端安全问题,因为它发生在用户的浏览器里。
除了从安全问题发生的区域来分类之外,也可以从另一个维度来判断:针对某个安全问题,团队中的哪个角色最适合来修复它?是后端开发还是前端开发?
总的来说,当我们下面在谈论“前端安全问题”的时候,我们说的是发生在浏览器、前端应用当中,或者通常由前端开发工程师来对其进行修复的安全问题。
8大前端安全问题
按照上面的分类办法,我们总结出了8大典型的前端安全问题,它们分别是:
- 老生常谈的XSS
- 警惕iframe带来的风险
- 别被点击劫持了
- 错误的内容推断
- 防火防盗防猪队友:不安全的第三方依赖包
- 用了HTTPS也可能掉坑里
- 本地存储数据泄露
- 缺失静态资源完整性校验
由于篇幅所限,本篇文章先给各位介绍前4个前端安全问题。
1 老生常谈的XSS
XSS是跨站脚本攻击(Cross-Site Scripting)的简称,它是个老油条了,在OWASP Web Application Top 10排行榜中长期霸榜,从未掉出过前三名。XSS这类安全问题发生的本质原因在于,浏览器错误的将攻击者提供的用户输入数据当做JavaScript脚本给执行了。
XSS有几种不同的分类办法,例如按照恶意输入的脚本是否在应用中存储,XSS被划分为“存储型XSS”和“反射型XSS”,如果按照是否和服务器有交互,又可以划分为“Server Side XSS”和“DOM based XSS”。
无论怎么分类,XSS漏洞始终是威胁用户的一个安全隐患。攻击者可以利用XSS漏洞来窃取包括用户身份信息在内的各种敏感信息、修改Web页面以欺骗用户,甚至控制受害者浏览器,或者和其他漏洞结合起来形成蠕虫攻击,等等。总之,关于XSS漏洞的利用,只有想不到没有做不到。
如何防御
防御XSS最佳的做法就是对数据进行严格的输出编码,使得攻击者提供的数据不再被浏览器认为是脚本而被误执行。例如<script>在进行HTML编码后变成了<script>,而这段数据就会被浏览器认为只是一段普通的字符串,而不会被当做脚本执行了。
编码也不是件容易的事情,需要根据输出数据所在的上下文来进行相应的编码。例如刚才的例子,由于数据将被放置于HTML元素中,因此进行的是HTML编码,而如果数据将被放置于URL中,则需要进行URL编码,将其变为%3Cscript%3E。此外,还有JavaScript编码、CSS编码、HTML属性编码、JSON编码等等。好在现如今的前端开发框架基本上都默认提供了前端输出编码,这大大减轻了前端开发小伙伴们的工作负担。
其他的防御措施,例如设置CSP HTTP Header、输入验证、开启浏览器XSS防御等等都是可选项,原因在于这些措施都存在被绕过的可能,并不能完全保证能防御XSS攻击。不过它们和输出编码却可以共同协作实施纵深防御策略。
你可以查阅OWASP XSS Prevention Cheat Sheet,里面有关于XSS及其防御措施的详细说明。
2 警惕iframe带来的风险
有些时候我们的前端页面需要用到第三方提供的页面组件,通常会以iframe的方式引入。典型的例子是使用iframe在页面上添加第三方提供的广告、天气预报、社交分享插件等等。
iframe在给我们的页面带来更多丰富的内容和能力的同时,也带来了不少的安全隐患。因为iframe中的内容是由第三方来提供的,默认情况下他们不受我们的控制,他们可以在iframe中运行JavaScirpt脚本、Flash插件、弹出对话框等等,这可能会破坏前端用户体验。
如果说iframe只是有可能会给用户体验带来影响,看似风险不大,那么如果iframe中的域名因为过期而被恶意攻击者抢注,或者第三方被黑客攻破,iframe中的内容被替换掉了,从而利用用户浏览器中的安全漏洞下载安装木马、恶意勒索软件等等,这问题可就大了。
如何防御
还好在HTML5中,iframe有了一个叫做sandbox的安全属性,通过它可以对iframe的行为进行各种限制,充分实现“最小权限“原则。使用sandbox的最简单的方式就是只在iframe元素中添加上这个关键词就好,就像下面这样:
<iframe sandbox src="..."> ... </iframe>
sandbox还忠实的实现了“Secure By Default”原则,也就是说,如果你只是添加上这个属性而保持属性值为空,那么浏览器将会对iframe实施史上最严厉的调控限制,基本上来讲就是除了允许显示静态资源以外,其他什么都做不了。比如不准提交表单、不准弹窗、不准执行脚本等等,连Origin都会被强制重新分配一个唯一的值,换句话讲就是iframe中的页面访问它自己的服务器都会被算作跨域请求。
另外,sandbox也提供了丰富的配置参数,我们可以进行较为细粒度的控制。一些典型的参数如下:
- allow-forms:允许iframe中提交form表单
- allow-popups:允许iframe中弹出新的窗口或者标签页(例如,window.open(),showModalDialog(),target=”_blank”等等)
- allow-scripts:允许iframe中执行JavaScript
- allow-same-origin:允许iframe中的网页开启同源策略
更多详细的资料,可以参考iframe中关于sandbox的介绍。