HTTP cookie 的安全性、安全使用方法和攻击防御手段

工作需要,要上台讲讲 cookie 安全性,索性总结成博客,自认为蛮全的

#前言

本文将把,截至2019-05-18的,从互联网上搜集到

(“cookie+security” -> Google 与 StartPage 前两页结果为源+相关学术文献)的,
有关 Cookie 标准与用法、cookie 安全性的信息,汇总索引,以方便读者学习了解相关信息。

本文需要读者对计算机网络有大致了解,
没有了解也可以,术语会挂上解释链接,但阅读体验就比较差了。

小段英文的翻译交给谷歌处理。

#目录

2部分与3部分的解决方案部分有重复,
但我认为还是把攻防和开发分开,缺陷与解决结合,比较方便阅读。

  1. Cookie 是什么&用法
  2. 设计、使用中的安全隐患以及相应改进
  3. 针对 cookie 窃取的攻击与相应防御
  4. 学术讨论涉及 cookie 的攻防
  5. 总结

1.Cookie 是什么&用法

#定义

英文维基百科 还是蛮丰富的,中文维基简单点,可以看百度百科

RFC:rfc2109-1997 -> rfc2965-2000 -> rfc6265-2011 -> rfc6265bis

https://hc.apache.org/httpcomponents-client-ga/tutorial/html/statemgmt.html

在最新的定义 cookie 的 RFC2965 上,是这么说的:

we will use the term cookie to refer to the state
information that passes between an origin server and user agent,
and that gets stored by the user agent.

我们将使用术语 cookie 来指代在源服务器和用户代理之间传递的状态信息,
以及由用户代理存储的状态信息。

简单总结,cookie 是:服务器与客户端间标识状态的信息,储存在客户端
(硬盘或内存,视类型而定),由服务器增删改读。
用途:满足对无状态的 HTTP 协议,想让它有状态的需求,一种修补措施。

比如一个服务器,需要同时与多个客户端通信。

  • 因为 HTTP 协议@的无连接性,所以需要一个额外方法区分不同客户端。
  • 然后因为计算机网络的网络层路由有CIDR-无类域间路由NAT-网络地址转换 这类协议存在,
    服务器不能单靠记录 IP 或者 MAC 这些 HTTP 包里的信息标识每一个客户端。

因此 Netscape Draft 在1994年率先定义了 cookie 这一解决方案
(此处 apache.org 的原文链接好像失效了),之后被整理成 rfc2109。

cookie 可以用来干什么?维基 给了三个功能:

  1. 会话管理
  2. 个性化定制 wikipedia-Zombie cookie (有点意思)
  3. 追踪

#格式&用法

一个 cookie 由一个键值对(key=value)组成,同时在被设置时 会附加一些变量(attributes),
这些变量用来控制该 cookie 的使用方法。

想了解详细属性,看rfc6265-The Set-Cookie Header
找不到新鲜的全面的中文材料,有个不错的博客@Jerry Qu ,但是是13年的。

比如,我们时常听闻的第三方 cookie,在设置时会标一个Third-party属性,
表明这是从非当前网站(URL 框里的网站)设置的。

当一个网站有引用(<img>…)其他网站,比如广告网站的广告资源时,
浏览器加载该网站时,也会向广告网站发 GET 请求,
第三方 cookie 就随着资源一起来到了浏览器上。

对 cookie 的操作不再赘述,有需请自取。

https://en.wikipedia.org/wiki/HTTP_cookie#Implementation

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie

https://tools.ietf.org/html/rfc6265#section-4.2

#Security risk in design and use and solution

2.Cookie 设计与使用中的安全隐患,以及相应改进

Cookie 安全性这点,rfc6265中有一整段(8. Security Considerations) 去阐述,
务必读一下,总结的很好,我会跳过那些内容,只给出一个目录以供预览。

分标题 简述
Overview 总览
Ambient Authority cookie 是一种权限凭证
Clear Text 明文传输问题
Session Identifiers 非可读的会话标识符
Weak Confidentiality cookie 在各种层面保密性都弱
Reliance on DNS cookie 的安全性以 DNS 安全为前提

与其说其设计不周全,不如说 cookie 因本身位置的限制无法保证设计安全,
rfc 还警告开发人员不要把 cookie 作为唯一的认证环节。

rfc6265: In addition, by default, cookies do not provide confidentiality or integrity
from network attackers, even when used in conjunction with HTTPS.

此外,默认情况下,cookie 不会为网络攻击者提供机密性或完整性,
即使与 HTTPS 结合使用也是如此。

rfc6265#section-4.2.2 :
Notice that the cookie attributes are not returned.
In particular,the server cannot determine from the Cookie header alone
when a cookie will expire, for which hosts the cookie is valid,
for which paths the cookie is valid, or whether the cookie was set with the Secure or HttpOnly attributes.

rfc6265#section-4.2.2 :
请注意,不返回 cookie 属性。特别是,当 cookie 过期时,
服务器无法单独从 Cookie 标头确定,cookie 对哪些主机有效,cookie 的路径有效,
或者 cookie 是否使用 Secure 或 HttpOnly 属性设置。

同时在设置 cookie 时,客户端并不会发回结果反馈。这使得服务器不知道 cookie 是否被正确设置。
这等于要从数据库读一个不知道是否干净的数据,对数据完整性有影响。

#解决:服务器容错与键名“走私(Smuggle)”

大多数情况下,可以用服务器逻辑容错。
OWASPLondon20171130_Cookie_Security_Myths_Misconceptions_David_Johansson
此报告提供了在 cookie 名里添加“私货”以标识属性的方法,
比如一个 cookie 设置了属性http-only,名字就加个前缀 HTTP_ONLY_。

#2. “Domain”“Path”属性影响完整性

rfc6265-两个属性的设置

rfc6265-两个属性在客户端的处理算法

不贴原文了,简单地总结(参照维基):

#Path 是指域名|Host 下的路径归属。

  • 比如两网站example.com/site1/index.htm,example/com/site2/index.htm
    设置 Path 属性为/site1,/site2两个值以分离两个目录中的页面的 cookie。
  • 有些网站的不同目录是运行不同功能的,比如两个朋友共租一个域名运营博客,用上述方式划分。
    通过这种方式可以做到分离两个博客的 cookie。

看起来很好,但稍有不慎(或故意为之),就可以用来绕过SOE-同源策略
比如,设置 path 成/,好,域名下所有页面都能读该 cookie 了。

这是一种减少网站开发人员工作量的窍门,也能被攻击者用来做窃取 cookie 的手段。

#Domain 是指域名归属。

它和Path属性的缺点差不多类型,设置了Domain的 cookie 是默认暴露给所有子域名的。
我们都知道,同域名不一定等于同服务器 IP,所以攻击者可以劫持域名解析偷 cookie。
因为这个原因,实际开发中一般不建议设置Domain属性。

#解决:SameSite 属性(2016年)&不设置Domain属性

#SameSite

维基#Same-site_cookie:
In 2016 Google Chrome version 51 introduced a new kind of cookie, the same-site cookie,
which can only be sent in requests originating from the same origin as the target domain.
This restriction mitigates attacks such as cross-site request forgery (XSRF).
A cookie is given this characteristic by setting the SameSite flag to Strict or Lax.
google:draft-ietf-httpbis-cookie-same-site

2016年,谷歌 Chrome 版本51引入了一种新型 cookie,即同一站点的 cookie,
只能在源自与目标域相同的源的请求中发送。此限制可缓解诸如跨站点请求伪造(XSRF)等攻击。
通过将 SameSite 标志设置为 Strict 或 Lax,可以为 cookie 提供此特性。

标准支持:截至撰文时间(2019-05),

  • 开发支持:查到的是 node.js 的 express、PHP7.3支持,应该还有没搜到的
  • 浏览器支持:几个主流浏览器,的新版本都已支持,不再列举名字。

Browser Compatibility Testing of ‘SameSite’ cookie - LambdaTest

#不设置Domain属性

Stack over flow-What is a host only cookie?

之所以不设置Domain属性,其实是为了激活host-only-flag
当 host-only-flag 被设置,子域名无法访问此 cookie。

rfc6265-5.3. Storage Model

上面算是设计问题,下面是多数文章主要讲的,开发者对 cookie 的误用。

cookie 默认不加密传输,可以在传输中被坏家伙窃听或修改。

解决:设置 Secure属性&cookie 加密和签名

rfc6265-5.2.5. The Secure Attribute
Secure属性保证 cookie 只在 HTTPS 环境下可被传输。

和数据库设计一样,为了保险,应尽量减少数据中非必须的信息量。
cookie 值可以是随机生成的字符串(会话凭证)而不是具体信息,
在下次登录时修改,以应对 cookie 窃取与重放攻击。

rfc6265:
Servers SHOULD encrypt and sign the contents of cookies
(using whatever format the server desires) when transmitting them to the
user agent (even when sending the cookies over a secure channel).

当将服务器传输给用户代理时,服务器应该对 cookie 的内容进行加密和签名
(使用服务器所需的任何格式)(即使通过安全通道发送 cookie)。

解决:设置时加 Http-only-flag ,禁止客户端 JS 读取 cookie。

#③错误规划max-ageexpires

rfc6265-The Set-Cookie Header

标准太长,简单总结:
max-age: 类似 TTL,以秒计,到时删除。
expires: GMT 时间字符串(Wed, 09 Jun 2021 10:18:14 GMT),到时删除。
max-ageexpires 的一个补充性属性。没有这两个属性,cookie 被视为session cookie
cookie 保留在客户端的时间越长,被攻击的可能性越高。

#解决:谨慎设计max-ageexpires的值

越敏感的数据,越要设置时间短,保持用户频繁认证。

#Attack on cookies and solution

3.针对 cookie 窃取的攻击与相应防御

以下所有攻击手段,都能单独拉出来写好多篇技术报告|分享,
很明显本文没有这个篇幅,因此本文征求做到全而不详,并附链接以供详求。

这篇文章 的一段话讲得不错:

Because the data they contain is, more often than not, extremely sensitive
— cookies are generally used to store session IDs or access tokens,
an attacker’s holy grail.
Once they are exposed or compromised, attackers can impersonate users,
or escalate their privileges on your application.

因为它们包含的数据通常非常敏感 - 通常用于存储会话 ID 或访问令牌,攻击者的圣杯。
一旦他们暴露或受到攻击,攻击者就可以冒充用户,或者升级他们对您的应用程序的权限。

#常见攻击方式

维基百科总结了几种常见的攻击方式,包括攻击过程简介与防御手段,在此不复述,只提供目录。

攻击 防御
MITM TLS&secureattr
DNS Poisoning TLS&secureattr
DOM-Based-XSS http-only-flag&SameSiteattr
反射型 XSS+恶意代理服务器 secureattr&SameSiteattr
CSRF SameSiteattr

还有一类维基没提到的,针对TLS 协议 的攻击。
TLS 协议不是完全安全的,因为设计或实现的缺陷,
已有不少在特定情况下针对 TLS 的攻击出现,
主要目的是使 HTTPS 降为“等同于”HTTP 的情况(即复原密文为明文),
这不是一个新方向,列举几个比较有名的攻击方式:

#非常见方式

非单一的、利用知识组合各种部分的针对 cookie 的攻击方式,
可惜我只找到一个。

#①cookiejacking-Rosario Valotta-2011-05[link]

该方法利用了 IE 浏览器的“跨域交互策略”的一个漏洞,
外部 HTML 的<iframe>标签可以加载本地 cookie 文件(本应不能)。
恶意服务器通过一系列正常的手段获知用于构造 cookie 路径的信息,
然后通过此漏洞读取 cookie,并利用Clickjacking 手段传输 cookie 至服务器。
因为读的是文件,任何 cookie 都会被窃取。

微软6月 给这个漏洞打了补丁。
至于 Clickjacking,x-frame-options(XFO) 可以防止。

#Academic discussion about cookies

关于 cookie 的学术讨论

本来想把理论方面作为2、3段的添头,没想到专家们已经在纸头上打过一两轮攻防了。
故单开此段,索引几个我觉得有意思的学术文献。

TLS Record Protocol: Security Analysis and
Defense-in-depth Countermeasures for HTTPS

Author: Olivier Levillain etc
Time: 2015

这个研究总结了针对 TLS 记录协议的5个攻击方式,并给出了两个 cookie 掩盖方式:
TLS Scramble & MCookies,以保证在意外导致 HTTP 明文传输的情况下,
继续保持 cookie 等秘密信息机密性。

Statistical attacks on cookie masking for RC4
Author: Kenneth G. PatersonEmail author etc
Time: 2018-02

该文验证了上篇文章两种掩盖方式理论上可被加大提供算力后破解,
因此该掩盖方式只能提供不强的机密性。

#测信道攻击

Path Leaks of HTTPS Side-Channel by Cookie Injection
Author: Fuqing Chen etc
Time: 2018-04

该文阐述了一种攻击方式和两种应用方面:
利用 cookie 的弱同源策略(上文有提),实施 cookie 注入,
用注入的 cookie 来推断敏感信息,进而复原一部分密文(比如请求的 URL)。
没看完,大概是利用当时浏览器的 cookie 路径匹配的算法的一个缺陷。

Protecting Encrypted Cookies from
Compression Side-Channel Attacks

Author: Janaka Alawatugoda etc
Time: 2015-07

有那么两种对 TLS 的攻击:CRIMEBREACH (上文有提),
它们基于传输前压缩过程中产生的额外信息量,复现敏感信息,
针对它们的常规解决方法是禁止传输中压缩,
这意味着加大使用带宽资源。
该文阐述了两种新的压缩方式,用于实现压缩并保护机密信息的功能。

#Summary

总结

首先,关于此文,不包括素材阅读的,纯搜索时间,大概只有2小时多,
因此即使是截至2019-05,此文大概还是遗漏了许多值得一提的部分,请读者海涵。

其次,经过编写此文,作者对 cookie 的认识有了很大变化,认清了 cookie 能力是很有限的,
以后编写 web 服务也会注意 cookie 的正确运用。希望各位读者也能从此文中学到知识。

updatedupdated2023-08-082023-08-08