关于 Web 安全, 99%的网站都忽略了这些

2015-10-13 20:22:34 +08:00
 wilddog

作者:肖光宇
野狗科技联合创始人,先后在猫扑、百度、搜狗任职。技术栈较广,曾经致力于数据分析,异常检测领域,通过数学模型和机器学习解决用户输入和搜索广告中的反作弊难题。也曾做过 java 开发,熟悉从网络到前端的全部技术。
公众订阅号: wilddogbaas
野狗科技官方网站: https://www.wilddog.com

Web 安全是一个如何强调都不为过的事情,我们发现国内的众多网站都没有实现全站 https ,对于其他安全策略的实践更是很少,本文的目的并非讨论安全和攻击的细节,而是从策略的角度引发对安全的思考和重视。

1.数据通道安全

http 协议下的网络连接都是基于明文的,信息很有可能被泄露篡改,甚至用户都不知道通信的对方是否就是自己希望连接的服务器。因此,信息通道安全有以下两个目标:

幸运的是 https 解决了上述问题的(更多关于 https 的细节可以看下上一篇干货[扒一扒 https 网站的内幕][2])。理论上 https 是安全的,即使如此, https 依然应该被重视,因为理论上理论和实践是一样的,但实践中又是另外一回事。前段时间爆发的心血漏洞就是一个例子。

2.浏览器安全

https 解决了点到点的安全问题和身份认证问题,接下来会出现问题的地方就只有 2 个:浏览器和服务器,这个层面上的安全问题并没有 https 一样的银弹可以一次性解决。

2.1 origin 源

了解浏览器安全,有一个概念特别重要,那就是源(origin) 什么是源呢?

举栗子:

源这个概念为甚这么重要,这要从同源策略说起。

2.2 同源策略

同源策略限制了一个源( origin )中加载文本或脚本与来自其它源( origin )中资源的交互方式。简单的说就是一个源的页面上的 js 只能访问当前源的资源,不能访问其他源的资源。那么资源是什么呢?

很显然,同源策略以源为单位,把资源天然分隔,保护了用户的信息安全。

同源策略是一堵墙,然而墙并非不透风。有很多方法可以绕过同源策略让 javascript 访问其他源的资源。比如: JSONP :
基于 iframe 的方法( iframe+window.name iframe+window.domain iframe+webMessage )
CORS : 我认为只有 CORS 是"正当的"绕过同源策略的方法 同源策略是浏览器安全策略的基础,但同源策略面对很多攻击是无能为力的,比如 XSS

2.3 XSS(Cross-Site Script)

跨站脚本攻击,名字跟同源策略很像,事实上他们之间基本没有关系。跨站脚本攻击本质上是一种注入攻击(有兴趣了解更多注入攻击可以看 Injection Theory )。其原理,简单的说就是利用各种手段把恶意代码添加到网页中,并让受害者执行这段脚本。 XSS 的例子只要百度一下有很多。 XSS 能做用户使用浏览器能做的一切事情。可以看到同源策略无法保证不受 XSS 攻击,因为此时攻击者就在同源之内。

XSS 攻击从攻击的方式可以分为:

这种分类方式有些过时,长久以来,人们认为 XSS 分类有以上三种,但实际情况中经常无法区分,所以更明确的分类方式可以分为以下两类:

当一端 XSS 代码是在服务端被插入的,那么这就是服务端型 XSS ,同理,如果代码在客户端插入,就是客户端型 XSS 。

2.4 防止 XSS 攻击--转义

无论是服务端型还是客户端型 XSS ,攻击达成需要两个条件:

其实只要做好无论任何情况下保证代码不被执行就能完全杜绝 XSS 攻击。详情可以看下 XSS (Cross Site Scripting) Prevention Cheat Sheet 这篇文章。
这里简单说下结论:任何时候都不要把不受信任的数据直接插入到 dom 中的任何位置,一定要做转义。

2.4.1 对于某些位置,不受信任的数据做转义就可以保证安全:

2.4.2 对于某些位置,即使做了转义依然不安全:

2.4.3 使用 JSON.parse 而不是 eval,request 的 content-type 要指定是 Content-Type: application/json;

2.4.4 如果链接的 URL 中部分是动态生成的,一定要做转义。

2.5 HTML 转义:

& --> &
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#x27;
/ --> &#x2F;

2.6 使用浏览器自带的 XSS-filter

现代浏览器都对反射型 XSS 有一定的防御力,其原理是检查 url 和 dom 中元素的相关性。但这并不能完全防止反射型 XSS 。另外,浏览器对于存储型 XSS 并没有抵抗力,原因很简单,用户的需求是多种多样的。所以,抵御 XSS 这件事情不能指望浏览器。

可以通过 http 头控制是否打开 XSS-filter,当然默认是打开的.X-XSS-Protection

2.7 CSP(Content Security Policy)

从原理上说防止 XSS 是很简单的一件事,但实际中,业务代码非常多样和复杂,漏洞还是时不时会出现。 CSP 并不是用来防止 XSS 攻击的,而是最小化 XSS 发生后所造成的伤害。事实上,除了开发者自己做好 XSS 转义,并没有别的方法可以防止 XSS 的发生。 CSP 可以说是 html5 给 Web 安全带来的最实惠的东西。 CSP 的作用是限制一个页面的行为不论是否是 javacript 控制的。

如何引入 CSP 呢?

2.7.1 通过 response 头

//只允许脚本从本源加载 Content-Security-Policy: script-src 'self'

2.7.2 通过 html 的 meta 标签

//作用同上<meta http-equiv="Content-Security-Policy" content="script-src 'self'">

那么 CSP 除了限制 script-src 之外还能限制什么呢?

base-uri:限制这篇文档的 uri ;
child-src:限制子窗口的源(iframe 、弹窗等),取代 frame-src ;
connect-src:限制脚本可以访问的源;
font-src:限制字体的源;
form-action:限制表单能够提交到的源;
frame-ancestors:限制了当前页面可以被哪些页面以 iframe,frame,object 等方式加载;
frame-src:deprecated with child-src,限制了当前页面可以加载哪些源,与 frame-ancestors 对应;
img-src:限制图片可以从哪些源加载;
media-src:限制 video,audio, source,track 能够从哪些源加载;
object-src:限制插件可以从哪些源加载;
sandbox:强制打开沙盒模式;

可以看出, CSP 是一个强大的策略,几乎可以限制了所有能够用到的资源的来源。使用好 CSP 可以很大成都降低 XSS 带来的风险。另外, CSP 还提供一个报告的头 Content-Security-Policy-Report-Only ,使用这个头浏览器向服务器报告 CSP 状态,细节先不讨论。

Content-Security-Policy-Report-Only:script-src'self';
                              report-uri/csp-report-endpoint/

CSP 目前有两版: CSP1 和 CSP2 。

两版的支持状态可以在 http://caniuse.com/#search=csp 中查到。

2.8 X-Frame-Options

这是 response 头,现在正在使用,但以后可以被 CSP 的 frame-ancestors 取代。目前支持的状态比起 CSP frame-ancestors 要好,使用的方式:

X-Frame-Options:DENY//这个页面不允许被以 frame 的方式加载

X-Frame-Options:SAMEORIGIN//这个页面只允许同源页面加载 X-Frame-Options:<uri>
//这个页面只能被特定的域加载

2.9 Http-Only

使用 Http-only 保护 cookie ,可以保证即使发生了 XSS ,用户的 cookie 也是安全的。使用 Http-only 保护的 cookie 是不会被 javascript 读写的。

2.10 iframe 沙箱环境

虽然有同源策略, iframe 的问题还是有很多的,比如各种利用 iframe 进行跨源。 HTML5 为 iframe 提供了安全属性 sandbox ,如果使用此属性, iframe 的能力将会被限制,细节我们将会在以后的文章中详细讨论。

2.11 其他安全相关的 HTTP 头

X-Content-Type-Options 阻止浏览器进行 content-type 嗅探。告诉浏览器相信此服务器下发的资源的类型,防止类型嗅探攻击。

HPKP(Public Key Pinning)Public Key Pinning 是一个 response 头,用来检测一个证书的公钥是否发生了改变,防止中间人攻击。

HSTS (HTTP Strict-Transport-Security) 强制使用 TSL 作为数据通道,在[扒一扒 HTTPS 网站的内幕][9]中也有详细介绍。

3.HTML5 对 Web 安全的影响

HTML5 带来了很多新的特性,让浏览器和 javascript 获得了更大的能力。然而能力越大,被攻破后的危险就越大。

HTML5 对 XSS 的影响主要体现在:

更大的攻击面, HTML5 带来来更多的标签和更多的属性, XSS 发生的可能性更大。
更大的危害, HTML5 更多的资源可以被 XSS 利用。黑客可以利用浏览器的一切权限,比如本地存储, GEO , WebSocket , Webworker 。

遗憾的是 HTML 并没有针止 XSS 和 XSRF 带来系统性解决方案。在这个前提下, CSP 变得非常重要,可以大大降低 XSS 后的危害。

HTML5 时代实际对开发者提出来更高的要求,因为有更多的交互,更多的前端行为, HTML5 有更多的 API 。希望共勉,不做蒙古大夫,与广大的开发者一同提高中国互联网的用户体验!

4.references

安全相关的 HTTP 头
https://www.owasp.org/index.php/List_of_useful_HTTP_headers

同源策略
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

CSP
http://www.w3.org/TR/CSP/

HPKP
https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning

w3c iframe element
http://www.w3.org/TR/2011/WD-html5-20110525/the-iframe-element.html

MDN web security
https://developer.mozilla.org/en-US/docs/Web/Security

XSS cheet sheet
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

野狗科技官网
https://www.wilddog.com/

7102 次点击
所在节点    SSL
29 条回复
wilddog
2015-10-13 20:25:03 +08:00
作者:肖光宇
野狗科技联合创始人,先后在猫扑、百度、搜狗任职。技术栈较广,曾经致力于数据分析,异常检测领域,通过数学模型和机器学习解决用户输入和搜索广告中的反作弊难题。也曾做过 java 开发,熟悉从网络到前端的全部技术。
公众订阅号: wilddogbaas
野狗科技官方网站: https://www.wilddog.com
dong3580
2015-10-13 20:30:42 +08:00
先收藏,我就想说 为什么那么多网站都是用户名密码明文 post 提交,还是 http...呵呵,
wilddog
2015-10-13 20:50:02 +08:00
@dong3580 感谢
ryd994
2015-10-13 21:06:58 +08:00
X-Content-Type-Option 是告诉浏览器验证 mime
abelyao
2015-10-13 21:19:22 +08:00
@dong3580 因为前端加密就是自欺欺人,直接上 HTTPS 才是王道,连 HTTPS 都懒得部署的网站,你让他前端加密,顶多也就给你套一层 MD5 ,而对服务端来说收到一份不可逆的密码,也无法校验你的密码是否对方安全要求,如果是可逆的加密那直接看 JS 就跟皇帝的新衣一样。
loading
2015-10-13 21:46:27 +08:00
这个只是个合集…感谢您的汗水
wilddog
2015-10-13 21:51:56 +08:00
@loading 感谢您的回复
crazycen
2015-10-13 21:52:35 +08:00
然而我并没有看完!
dong3580
2015-10-13 21:54:02 +08:00
@abelyao
你确定是前端问题?
曾经我做后端的时候,做前端的不配合我做加密,然后我转做前端了。。。
然而做后端的居然不被配合我 MD5 加密用户名密码验证码再 post ,
然而还被鄙视是我太敏感了,
可怕的不是一个人的无知,而是一群人的无知,
认为前端 MD5 用户名密码验证到后端校验多此一举。
crab
2015-10-13 21:55:33 +08:00
@abelyao 现在很多都是把密码通过 JS 内的 RSA 加密。
abelyao
2015-10-13 22:37:16 +08:00
@dong3580 是是是,别人都无知。
some0ne
2015-10-13 22:46:16 +08:00
@dong3580 确实是多此一举,因为你无法保证用户收到的 JS 是未被修改的。


@crab JS 实现 RSA 加密也是一样的问题,你如何保证你收到的密钥是服务器发给你的密钥。
crab
2015-10-13 22:50:36 +08:00
@some0ne 是不能保证啊。但比直接明文好多了。
jackxy
2015-10-13 23:06:55 +08:00
@crab 确实比明文安全许多,但从理论上, https 是没有漏洞的,自己实现加密的办法一定会有漏洞。因为没办法建立 CA 证书链。
jackxy
2015-10-13 23:12:28 +08:00
讨论安全问题一定要设置一个前提,
比如 https 是安全的
sha1 是无法被逆转的
。。。
在这个前提下讨论问题才有意义,不然会陷入无限的抬杠中
其实做任何形式的加密都会对安全有提升,但标准组织已经造好了一套完美的轮子,我们照做就行。重复造了
cooooooooool
2015-10-14 00:06:45 +08:00
收藏了,好文
uuair
2015-10-14 00:16:07 +08:00
刚在 segmentfault 看到这篇文章,原来作者也在这里。。。
lincanbin
2015-10-14 00:22:32 +08:00
感觉我是 1%诶,虽然用了 SSL ,但是登录时密码提交前我也 Hash 了一下再提交。
X-Frame-Options 、 Http-Only 、 XSS 等等我也都做了。
是不是自我感觉太良好?
RitianZhao1988
2015-10-14 01:56:14 +08:00
mark
wilddog
2015-10-14 08:11:56 +08:00
@uuair 😄

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/227773

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX