Cookies Hacking
Last updated
Last updated
学习和实践 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) 学习和实践 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Cookies 具有多个属性,控制其在用户浏览器中的行为。以下是这些属性的简要说明:
Cookie 的过期日期由 Expires
属性决定。相反,Max-age
属性定义了在删除 Cookie 之前的秒数。选择 Max-age
,因为它反映了更现代的做法。
接收 Cookie 的主机由 Domain
属性指定。默认情况下,这设置为发出 Cookie 的主机,不包括其子域。然而,当 Domain
属性被显式设置时,它也包括子域。这使得 Domain
属性的指定成为一个不那么严格的选项,适用于需要跨子域共享 Cookie 的场景。例如,设置 Domain=mozilla.org
使得在其子域如 developer.mozilla.org
上可以访问 Cookie。
Path
属性指示必须在请求的 URL 中存在的特定 URL 路径,以便发送 Cookie
头。此属性将 /
字符视为目录分隔符,允许在子目录中匹配。
当两个 Cookie 具有相同名称时,选择发送的 Cookie 基于:
与请求的 URL 中最长路径匹配的 Cookie。
如果路径相同,则选择最近设置的 Cookie。
SameSite
属性决定是否在来自第三方域的请求中发送 Cookie。它提供三种设置:
Strict: 限制 Cookie 在第三方请求中发送。
Lax: 允许 Cookie 与由第三方网站发起的 GET 请求一起发送。
None: 允许 Cookie 从任何第三方域发送。
请记住,在配置 Cookie 时,理解这些属性可以帮助确保它们在不同场景中按预期行为。
表格来自 Invicti 并稍作修改。 具有 SameSite 属性的 Cookie 将 减轻 CSRF 攻击,其中需要登录会话。
*请注意,从 Chrome80(2019年2月)开始,未设置 SameSite 属性的 Cookie 的默认行为将是 lax (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/). 请注意,临时情况下,应用此更改后,Chrome 中 没有 SameSite **策略的 Cookie 将在 前 2 分钟内被 视为 None,然后在顶级跨站点 POST 请求中被视为 Lax。
这避免了 客户端 访问 Cookie(例如通过 Javascript: document.cookie
)
如果页面 将 Cookie 作为请求的响应发送(例如在 PHPinfo 页面中),可以利用 XSS 发送请求到此页面并 窃取响应中的 Cookie(请查看示例 https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/)。
这可以通过 TRACE HTTP 请求绕过,因为服务器的响应将反映发送的 Cookie(如果此 HTTP 方法可用)。此技术称为 跨站点跟踪。
现代浏览器通过不允许从 JS 发送 TRACE 请求来避免此技术。然而,在特定软件中发现了一些绕过方法,例如向 IE6.0 SP2 发送 \r\nTRACE
而不是 TRACE
。
另一种方法是利用浏览器的零日漏洞。
可以通过执行 Cookie Jar 溢出攻击来 覆盖 HttpOnly Cookie:
可以使用 Cookie Smuggling 攻击来外泄这些 Cookie
请求将 仅 在通过安全通道(通常是 HTTPS)传输时发送 Cookie。
以 __Secure-
开头的 Cookie 必须与通过 HTTPS 保护的页面的 secure
标志一起设置。
对于以 __Host-
开头的 Cookie,必须满足以下几个条件:
必须设置 secure
标志。
必须来自通过 HTTPS 保护的页面。
禁止指定域,防止其传输到子域。
这些 Cookie 的路径必须设置为 /
。
重要的是要注意,以 __Host-
开头的 Cookie 不允许发送到超级域或子域。此限制有助于隔离应用程序 Cookie。因此,使用 __Host-
前缀为所有应用程序 Cookie 是增强安全性和隔离性的良好做法。
因此,__Host-
前缀 Cookie 的保护之一是防止它们被子域覆盖。例如,防止 Cookie Tossing 攻击。在演讲 Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (论文) 中,展示了可以通过欺骗解析器从子域设置 __HOST- 前缀的 Cookie,例如,在开头或结尾添加 "=":
或者在 PHP 中,可以在 Cookie 名称的开头添加 其他字符,这些字符将被 替换为下划线 字符,从而允许覆盖 __HOST-
Cookie:
如果自定义 Cookie 包含敏感数据,请检查它(特别是如果您正在进行 CTF),因为它可能存在漏洞。
嵌入 Cookie 的敏感数据应始终受到审查。以 Base64 或类似格式编码的 Cookie 通常可以被解码。这种漏洞允许攻击者更改 Cookie 的内容,并通过将其修改后的数据重新编码回 Cookie 来冒充其他用户。
此攻击涉及窃取用户的 Cookie,以获得对其在应用程序中的帐户的未经授权访问。通过使用被盗的 Cookie,攻击者可以冒充合法用户。
在这种情况下,攻击者诱使受害者使用特定的 Cookie 登录。如果应用程序在登录时不分配新的 Cookie,攻击者就可以使用原始 Cookie 冒充受害者。此技术依赖于受害者使用攻击者提供的 Cookie 登录。
如果您在 子域中发现了 XSS 或 控制了子域,请阅读:
在这里,攻击者说服受害者使用攻击者的会话 Cookie。受害者相信他们已登录自己的帐户,将无意中在攻击者的帐户上下文中执行操作。
如果您在 子域中发现了 XSS 或 控制了子域,请阅读:
点击上面的链接访问解释 JWT 可能存在缺陷的页面。
用于 Cookie 的 JSON Web Tokens (JWT) 也可能存在漏洞。有关潜在缺陷及其利用方法的详细信息,建议访问有关黑客 JWT 的链接文档。
此攻击强迫已登录用户在他们当前已认证的 Web 应用程序上执行不必要的操作。攻击者可以利用自动随每个请求发送到易受攻击站点的 Cookie。
(请查看原始研究中的更多详细信息)浏览器允许创建没有名称的 Cookie,这可以通过 JavaScript 进行演示,如下所示:
结果在发送的 cookie 头中是 a=v1; test value; b=v2;
。有趣的是,如果设置了一个空名称的 cookie,这允许对 cookies 进行操控,通过将空 cookie 设置为特定值,可能控制其他 cookies:
这导致浏览器发送一个 cookie 头,每个 web 服务器将其解释为名为 a
,值为 b
的 cookie。
在 Chrome 中,如果 Unicode 代理代码点是设置的 cookie 的一部分,document.cookie
会变得损坏,随后返回一个空字符串:
这导致 document.cookie
输出一个空字符串,表明永久性损坏。
(查看原始研究的更多细节)包括 Java(Jetty、TomCat、Undertow)和 Python(Zope、cherrypy、web.py、aiohttp、bottle、webob)在内的多个网络服务器,由于对过时的 RFC2965 支持,错误处理 cookie 字符串。它们将双引号的 cookie 值视为单个值,即使它包含分号,而分号通常应分隔键值对:
(查看原始研究的更多细节) 服务器对 cookies 的错误解析,特别是 Undertow、Zope 以及使用 Python 的 http.cookie.SimpleCookie
和 http.cookie.BaseCookie
的服务器,创造了 cookie 注入攻击的机会。这些服务器未能正确分隔新 cookie 的开始,允许攻击者伪造 cookies:
Undertow 期望在带引号的值后立即出现新 cookie,而不需要分号。
Zope 寻找逗号以开始解析下一个 cookie。
Python 的 cookie 类在空格字符上开始解析。
这种漏洞在依赖基于 cookie 的 CSRF 保护的 web 应用程序中尤其危险,因为它允许攻击者注入伪造的 CSRF-token cookies,可能绕过安全措施。这个问题因 Python 对重复 cookie 名称的处理而加剧,最后一个出现的名称会覆盖之前的名称。它还引发了对不安全上下文中 __Secure-
和 __Host-
cookies 的担忧,并可能导致在将 cookies 传递给易受伪造攻击的后端服务器时绕过授权。
每次 登录 时 cookie 都是 相同 的。
登出并尝试使用相同的 cookie。
尝试用 2 个设备(或浏览器)使用相同的 cookie 登录同一账户。
检查 cookie 中是否有任何信息并尝试修改它。
尝试创建多个几乎相同用户名的账户并检查是否可以看到相似之处。
检查是否存在 "记住我" 选项以查看其工作原理。如果存在并可能存在漏洞,始终使用 "记住我" 的 cookie,而不使用其他 cookie。
检查即使在更改密码后,之前的 cookie 是否仍然有效。
如果在登录时 cookie 保持相同(或几乎相同),这可能意味着该 cookie 与您账户的某个字段(可能是用户名)相关。然后您可以:
尝试创建许多用户名非常 相似 的 账户 并尝试 猜测 算法的工作原理。
尝试 暴力破解用户名。如果 cookie 仅作为您用户名的身份验证方法保存,那么您可以创建一个用户名为 "Bmin" 的账户,并 暴力破解 您的 cookie 的每一个 位,因为您尝试的其中一个 cookie 将属于 "admin"。
尝试 Padding Oracle(您可以解密 cookie 的内容)。使用 padbuster。
Padding Oracle - Padbuster examples
Padbuster 将进行多次尝试,并会询问您哪个条件是错误条件(无效的条件)。
然后它将开始解密 cookie(可能需要几分钟)
如果攻击成功执行,则您可以尝试加密您选择的字符串。例如,如果您想要 encrypt user=administrator
此执行将为您提供正确加密和编码的 cookie,其中包含字符串 user=administrator。
CBC-MAC
也许一个 cookie 可以有某个值,并且可以使用 CBC 签名。然后,值的完整性是使用相同值的 CBC 创建的签名。由于建议使用空向量作为 IV,这种完整性检查可能会受到攻击。
攻击
获取用户名 administ 的签名 = t
获取用户名 rator\x00\x00\x00 XOR t 的签名 = t'
在 cookie 中设置值 administrator+t' (t' 将是 (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00 的有效签名)
ECB
如果 cookie 使用 ECB 加密,则可能会受到攻击。 当您登录时,您收到的 cookie 必须始终相同。
如何检测和攻击:
创建 2 个几乎相同数据的用户(用户名、密码、电子邮件等),并尝试发现给定 cookie 中的某些模式。
创建一个名为 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 的用户,并检查 cookie 中是否存在任何模式(由于 ECB 使用相同的密钥加密每个块,如果用户名被加密,则相同的加密字节可能会出现)。
应该有一个模式(与使用的块的大小相同)。因此,知道一堆 "a" 是如何加密的,您可以创建一个用户名:"a"*(块的大小)+"admin"。然后,您可以从 cookie 中删除一个块的 "a" 的加密模式。您将拥有用户名 "admin" 的 cookie。
学习和实践 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) 学习和实践 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
请求类型
示例代码
发送 Cookie 的条件
链接
<a href="..."></a>
NotSet*, Lax, None
预渲染
<link rel="prerender" href=".."/>
NotSet*, Lax, None
表单 GET
<form method="GET" action="...">
NotSet*, Lax, None
表单 POST
<form method="POST" action="...">
NotSet*, None
iframe
<iframe src="..."></iframe>
NotSet*, None
AJAX
$.get("...")
NotSet*, None
图片
<img src="...">
NetSet*, None