对于web系统而言,由于HTTP协议无状态的特性,用户登录时需要服务端生成通行证返回给浏览器。浏览器保存该通行证并在接下来的请求中携带该通行证。通常来讲,web系统使用http cookie来保存和传输通行证。本文介绍http cookie的原理、特性、并分析用其保存通行证可能遇到的安全问题。

本文假设使用cookie的客户端是浏览器,虽然还有其它客户端也使用cookie,但普通用户使用更多的还是浏览器。

什么是Http Cookie?

一种Http状态管理机制,最早由Lou Montulli发明于1994年,最新的标准是2011年发布的RFC 6265 - HTTP State Management Mechanism。因为保存信息到客户端的本质,也有系统用cookie来缓存信息,但这并不是Http Cookie的主要用途。

Cookie既指整个状态保存机制,也指用户保存状态的数据本身,由String类型的name和value以及若干属性组成。追根溯源,其名字来源于fortune cookie,一种内含写有幸运文字小纸条的饼干。

Cookie保存在哪,如何生成又怎样传输?

Cookie由服务端生成,保存在浏览器。通过两个Http Header:Set-Cookie和Cookie进行传输。Set-Cookie Header用于服务端传输登录通行证等cookie键值对及属性给浏览器,浏览器收到并验证合法性后会做相应保存。Cookie Header用于浏览器传递cookie键值对给服务端,服务端依次来鉴别用户身份等状态信息。

RFC6265定义了Cookie的一些属性,包含Expires、Max-Age、Domain、Path、Secure、HttpOnly。也有一些还没定义到RFC,但已经实际应用的属性,比如SameSite。Cookie写时有属性读时无属性,属性仅在设置时即Set-Cookie Header中指定,浏览器依此来决定是否接受该cookie如何使用该cookie,而一旦浏览器决定了将cookie放到Cookie Header中传递到服务端,那么浏览器不会传递更多的的信息到服务端,只会传递键值对name和value。

很多浏览器会提供读Cookie和写Cookie的api给运行在其上Javascript脚本使用,通常的api是操作docment.cookie:

    document.cookie=“SID=31d4d; domain=example.com; path=/;”;

说说Domain和Path这两个属性

Domain、Path、Name三者唯一确定一个cookie。其它属性仅用作读写时的权限控制,不作为cookie标识。在浏览器在使用cookie时:

  • 不区分Http/Https
  • 不区分端口号

这相比浏览器同源策略更加宽松,带来很多安全问题。

Domain是向上通配的:

  • 写入(Set-Cookie)访问www.example.com
    Set-Cookie: sid1=a; domain=example.com; path=/;            接受
Set-Cookie: sid2=b; domain=www.example.com; path=/; 接受
Set-Cookie: sid3=c; domain=pay.example.com; path=/; 拒绝
  • 读取(Cookie)
    访问pay.example.com
Cookie: sid1=a 访问www.example.com
Cookie: sid1=a; sid2=b;

很多系统写cookie,习惯在域名前加一个点,写成.example.com,以为这么写才是通配的,其实这个点是多余的,没有必要的。

Path是向下通配的:

  • 写入(Set-Cookie)

Set‐Cookie: sid1=a; domain=example.com; path=/;
Set‐Cookie: sid2=b; domain=example.com; path=/test/;
  • 读取(Cookie)

访问http://example.com/
Cookie: sid1=a; 访问http://example.com/test/
Cookie: sid1=a; sid2=b

Cookie的有效期过长导致通行证泄露

这两个属性指定cookie有效期。不指定有效期时,cookie默认为当前session有效,当前session有效指关闭浏览器时cookie失效。

Cookie的有效期过长可能导致通行证泄露。比如用户使用了公用电脑,关闭浏览器时,没有点击注销。这样Cookie就留存在这台电脑上,其它人只需打开浏览器即可获取其在网站上的cookie。

一般保存通行证的cookie应该设置为session有效的cookie,并在用户选择记住登录状态时,提醒用户,不要再公用电脑上做这样的勾选。

明文传输的HTTP流量

HTTP明文传输数据的特性,使得攻击者可从网路上抓包获取Cookie。

解决方案:

  • 服务端使用HTTPS
  • 指定cookie的secure属性,该属性使cookie只能在HTTPS请求中带出。

利用XSS漏洞读取保存在cookie的通行证

假如网站存在XSS漏洞,那么恶意JS可直接读取Cookie中的通行证。可以通过指定Cookie的HttpOnly属性。对于指定了HttpOnly的Cookie,浏览器会拒绝JS读写。

XSS仍有可能利用服务端漏洞获取cookie:

- 服务端有可能在请求的正常响应中包含通行证。不要笑,这真的有,尤其现在很多公司app和web共用一套后台;

- 服务端可能有漏洞导致cookie包含在请求响应中,从而被窃取。比如:Apache CEV-2012-005

所以HttpOnly不是银弹,XSS也有很多其它的危害。但至少,HttpOnly可以避免通行证在浏览器被JS直接读取。

利用XSS漏洞写cookie

  • 使用户退登

保存了通行证的cookie因为是HttpOnly,所以XSS无法读取。但XSS还是可以写Cookie,由于domain、path、name三者才唯一标识一个cookie,XSS可以写一个跟通行证cookie name相同,但domain或path不同的cookie。

这样当浏览器发送请求给服务端时,服务端就会收到两个相同name的cookie。因为cookie读时无属性,所以服务端无从判断哪一个才是正确的。这样会使用哪一个cookie,就要看具体web server的实现,可能是第一个也可能是第二个。

这样通过写cookie,XSS可以轻易地使已登录用户退登。

  • 更危险的情况,Cookie替换攻击

恶意JS可针对特定的域名和path写入一个攻击者的cookie通行证。比如针对某电商网站的余额充值domain和path,写入攻击者的通行证。该攻击者cookie在用户正常购物的请求中不会带出,当用户充值时会带出,从而使用户充值到了攻击者的账号。

不安全的公共wifi

对于HTTP,公共wifi可劫持用户所有的流量,窃取cookie通行证自然不在话下。

对于HTTPS,因为可以在DNS上做手脚,可以在路由器上截取和篡改流量,在公共wifi上很容易诱导用户发出到网站的HTTP请求,几遍该网站是全站HTTPS也是如此。

因此,对于XSS写cookie的危害,公共wifi都能做到。而且能力更强,危害更大。

对于设置了secure属性的cookie,虽然不会在http请求中带出,但却可被http请求的Cookie设置覆盖。因此,设置了secure也不安全。

Although seemingly useful for protecting cookies from active network

attackers, the Secure attribute protects only the cookie's

confidentiality. An active network attacker can overwrite Secure

cookies from an insecure channel, disrupting their integrity

---- from RFC 6265

HSTS

公共wifi的危害,有一个关键点,就是诱导用户对指定网站发出HTTP请求。这一点通过HSTS - HTTP Strict Transport Security可以避免。

HSTS通过设置strict‐transport‐security头,来告知浏览器,对当前域名以及所有子域名,都只使用HTTPS访问。


让浏览器对当前域名及子域名,强制进行HTTPS访问: strict‐transport‐security: max‐age=15552000;includeSubDomains;

但HSTS在现实中难以被利用。因为:

  • 囿于cookie的通配特性,必须对整个域名部署HSTS才能生效;
  • 浏览器并非全支持这个特性。IE11+才开始支持;

所以,真正全站部署HSTS的网站,少之又少。

利用cookie大小和数量的限制来破坏安全

o At least 4096 bytes per cookie (as measured by the sum of the

length of the cookie's name, value, and attributes).

o At least 50 cookies per domain.

o At least 3000 cookies total.

---- From RFC 6265

  • Cookie的大小和数量是有限制的;
  • 每个浏览器,每种Web Server,限制都可能不一样;
  • 超出限制的行为,是未定义的。

设置超大cookie,超多cookie,都是典型的攻击手段。上文提到的Apache CEV-2012-005漏洞,即是利用了Apache对Cookie大小的限制。

利用csrf漏洞偷用通行证

在访问恶意网站时,网站的页面代码中,可能包含到你银行账号或是其它什么账号的请求。由于这时浏览器会自动带出到相应域名的cookie,所以用户的登录通行证,就很容易被恶意网站偷用。

这个问题,可以通过设置Cookie的SameSite属性来解决。设置了SameSite属性的cookie,只会在当前正在访问(浏览器地址栏)的域名与cookie的domain可匹配时,才会带出。

  • 在设置SameSite时,可以指定严格还是不严格。在不严格的情况下,如果请求会导致浏览器地址栏发生变化,那么cookie也是允许带出的;
  • SameSite没有包含在RFC 6265中,因此还不是标准。但Chrome 51(发布于2016年8月)已经支持了这个属性。

如下截图,是Chrome支持的cookie属性:

读取浏览器保存在硬盘上的cookie

有人会说,cookie不就是存放在硬盘,我直接从硬盘上窃取不可以吗?

答案是可以。比如Chrome的cookie就存放在目录:C:\Users<username>\AppData\Local\Google\Chrome\User Data\Default\下,是一个sqllite的数据库文件,虽然cookie内容都进行了加密,但也是可以破解的。

只是,当你攻破一个用户的电脑,破解了chrome的加密算法,最终只是窃取到了一个用户的登录凭证而已。这种攻击,性价比很低。

举个例子

Github推出的github pages功能,一开始的时候使用的是github.com主站域名,后来因为上面提到的cookie安全问题,不得不为github pages单独启动了github.io域名。

具体可看Github的官方blog,里面提到了上面部分的cookie安全问题。blog链接:Yummy Cookies across Domains

总结

  • Cookie从机制上就有安全问题,使用时要小心再小心;
  • 对于一些加强安全的Cookie属性,要尽量在系统早期实施。越晚实施,代价越大,实施难度越高;
  • 公共wifi不安全,即便网站使用了https,公共wifi也不安全。当离开一个公共wifi时,清除这段时间浏览器产生的cookie!

Reference

Cookie与Passport安全的更多相关文章

  1. [转帖]Cookie与Passport安全

    Cookie与Passport安全 https://www.cnblogs.com/xinzhao/p/6395153.html 感觉自己对网络安全性的理解还是不深入 不透彻. 对于web系统而言,由 ...

  2. Node.js 模块之【passport】

    什么是passport passport是Nodejs的一个中间键,用于用户名和密码的验证登陆.在项目中我用它来验证后台用户名和密码,但passport更多用在第三方登录,功能强大. 安装与配置 本项 ...

  3. asp.net单点登录(SSO)解决方案

    前些天一位朋友要我帮忙做一单点登录,其实这个概念早已耳熟能详,但实际应用很少,难得最近轻闲,于是决定通过本文来详细描述一个SSO解决方案,希望对大家有所帮助.SSO的解决方案很多,但搜索结果令人大失所 ...

  4. 基于.Net的单点登录(SSO)解决方案

    前些天一位朋友要我帮忙做一单点登录,其实这个概念早已耳熟能详,但实际应用很少,难得最近轻闲,于是决定通过本文来详细描述一个SSO解决方案,希望对大家有所帮助.SSO的解决方案很多,但搜索结果令人大失所 ...

  5. sso单点登录解决方案收集

    本文来自:http://blog.csdn.net/huwei2003/article/details/6038017 我的想法是使用集中验证方式,多个站点集中Passport验证. 主站:Passp ...

  6. Asp.net单点登录解决方案

    原文出处:http://www.cnblogs.com/wu-jian 主站:Passport集中验证服务器,DEMO中为:http://www.passport.com/ 分站:http://www ...

  7. 【大前端之打通账号系统】passport应该如何落地?

    前言 之前接入百度账号系统的时候写了一篇博客做研究:[大前端]认识单点登录,出来后才发现,很多小公司其实并没有将账号系统打通,总结一下账号系统没通的原因是: ① 最初设计就没想过身份认证应该做整合 ② ...

  8. [转]passport.js学习笔记

    概述 passport.js是Nodejs中的一个做登录验证的中间件,极其灵活和模块化,并且可与Express.Sails等Web框架无缝集成.Passport功能单一,即只能做登录验证,但非常强大, ...

  9. cookie单点登录(跨域访问)

    新近一家公司上来就让做oa,要求嵌入公司现有系统模块,自然而然想到模拟post单点登录对方系统新建单点登陆页面保存session,然现有系统都有用cookie保存用户信息,故保存本地cookie……测 ...

随机推荐

  1. [iOS Animation]-CALayer 缓冲

    缓冲 生活和艺术一样,最美的永远是曲线. -- 爱德华布尔沃 - 利顿 在第九章“图层时间”中,我们讨论了动画时间和CAMediaTiming协议.现在我们来看一下另一个和时间相关的机制--所谓的缓冲 ...

  2. window环境变量

    首先Window中有很多乱七八糟的路径变量之类的,归类下来有几类,主要是为了我们分清楚概念,以免搞的糊涂了. 1. Window系统的环境变量:顾名思义,就是系统级别的变量,或者利用我们编程的角度来讲 ...

  3. poj3190区间类贪心+优先队列

    题意:每个奶牛产奶的时间为A到B,每个奶牛产奶时要占用一间房子,问n头奶牛产奶共需要多少房子,并输出每头奶牛用哪间房子 分析:这题就是一个裸的贪心,将奶牛按开始时间进行排序即可,但考虑一下数据范围,我 ...

  4. mysqlslap 使用总结

    mysqlslap 可以用于模拟服务器的负载,并输出计时信息.其被包含在 MySQL 5.1 的发行包中.测试时,可以指定并发连接数,可以指定 SQL 语句.如果没有指定 SQL 语句,mysqlsl ...

  5. Yii -- framework 目录结构说明

    base 底层的类库文件 caching 所有缓存方法 cli 项目生成脚本 collecions 用PHP语言构造传统OO语言的数据存储单元.如队列,栈,哈希等等 console yii控制台 db ...

  6. iOS开发 missing iOS distribution signing identity for 。。。

    苹果真是不让人省心,新年一来上传APP,就出现Missing iOS Distribution signing indetity for xxx 于是就把证书删了做,做了删了再重做,还是不行 百度了一 ...

  7. 关于ios 推送功能的终极解决

    刚刚做了一个使用推送功能的应用 遇到了一些问题整的很郁闷 搞了两天总算是弄明白了 特此分享给大家 本帖 主要是针对产品发布版本的一些问题 综合了网上一些资料根据自己实践写的 不过测试也可以看看 首先要 ...

  8. 游标使用 和sp_executesql动态sql

    /****** Script for SelectTopNRows command from SSMS ******/ declare @oid int declare @cid int declar ...

  9. nlpir分词器过期处理

    nlpir分词器的非商业授权期限只有1个月,到期之后使用分词器在创建实例时就会提示授权到期,解决方法如下: 在nlpir发明者张教授的github页面下载对应的授权证书,地址在这. 将下载的证书覆盖分 ...

  10. iOS 解决一个复杂bug 之 计分卡

    由于该模块界面和业务逻辑都很复杂,并且整个界面设计和业务逻辑都在ViewController(下面简称为VC)里面完成.该VC共有3000多行,一个函数几百张的也有.所以,解决起来真是头疼. 1. 问 ...