hacktricks/pentesting-web/hacking-with-cookies/README.md

17 KiB
Raw Blame History

Cookies Hacking

从零开始学习AWS黑客技术成为专家 htARTEHackTricks AWS Red Team Expert

支持HackTricks的其他方式

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}


Cookie属性

Cookie带有几个属性控制它们在用户浏览器中的行为。以下是这些属性的概述使用更加被动的语气

过期时间和Max-Age

Cookie的过期日期由Expires属性确定。相反,Max-age属性定义了直到删除Cookie的时间以秒为单位选择Max-age,因为它反映了更现代的实践。

Domain属性指定接收Cookie的主机。默认情况下这设置为发出Cookie的主机不包括其子域。但是当显式设置Domain属性时,它也包括子域。这使得指定Domain属性成为一个不太限制的选项适用于需要在子域之间共享Cookie的情况。例如设置Domain=mozilla.org会使Cookie在其子域developer.mozilla.org)上可访问。

路径

Path属性指示必须在请求的URL中存在的特定URL路径以便发送Cookie头。该属性将/字符视为目录分隔符,允许在子目录中进行匹配。

排序规则

当两个Cookie具有相同的名称时发送的Cookie基于以下内容进行选择

  • 请求的URL中匹配最长路径的Cookie。
  • 如果路径相同则选择最近设置的Cookie。

SameSite

  • SameSite属性规定了是否在来自第三方域的请求上发送Cookie。它提供三种设置
  • Strict限制Cookie在第三方请求中发送。
  • Lax允许Cookie随第三方网站发起的GET请求发送。
  • None允许从任何第三方域发送Cookie。

请记住在配置Cookie时了解这些属性可以帮助确保它们在不同情况下的行为符合预期。

请求类型 示例代码 发送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

表格来源于Invicti稍作修改。带有_SameSite_属性的Cookie将减轻需要登录会话的CSRF攻击

*请注意从Chrome802019年2月开始没有Cookie 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标志

HttpOnly

这可以防止客户端访问Cookie例如通过Javascriptdocument.cookie

绕过方式

  • 如果页面正在将Cookie作为请求的响应发送例如在PHPinfo页面中可以滥用XSS发送请求到此页面并从响应中窃取Cookie(在https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/中查看示例)。
  • 可以通过TRACE HTTP请求绕过此限制因为服务器的响应将反映发送的Cookie。这种技术称为跨站点跟踪
  • 现代浏览器通过不允许从JS发送TRACE请求来避免此技术。但是已经在特定软件中找到了一些绕过方法例如向IE6.0 SP2发送\r\nTRACE而不是TRACE
  • 另一种方法是利用浏览器的零/日漏洞。
  • 可以通过执行Cookie Jar溢出攻击来覆盖HttpOnly Cookie

{% content-ref url="cookie-jar-overflow.md" %} cookie-jar-overflow.md {% endcontent-ref %}

Secure

只有在通过安全通道传输请求时(通常是HTTPS请求才会发送Cookie。

Cookie前缀

__Secure-为前缀的Cookie必须与受HTTPS保护的页面一起设置secure标志。

对于以__Host-为前缀的Cookie必须满足几个条件

  • 必须使用secure标志设置。
  • 必须来自通过HTTPS保护的页面。
  • 不能指定域,防止将其传输到子域。
  • 这些Cookie的路径必须设置为/

重要的是要注意,以__Host-为前缀的Cookie不允许发送到超级域或子域。此限制有助于隔离应用程序Cookie。因此考虑将__Host-前缀用于所有应用程序Cookie可以被视为增强安全性和隔离的良好实践。

覆盖 cookies

因此,__Host- 前缀的 cookie 之一的保护措施是防止它们被子域覆盖。例如,防止 Cookie Tossing 攻击。在讲座 Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper) 中提到,通过欺骗解析器,例如在开头或开头和结尾添加 "=",可以从子域设置 __HOST- 前缀的 cookie

或者在 PHP 中,可以在 cookie 名称的开头添加其他字符,这些字符将被下划线字符替换,从而允许覆盖 __HOST- cookies

Cookies 攻击

如果自定义 cookie 包含敏感数据,请检查它(特别是在参加 CTF 时),因为它可能存在漏洞。

解码和操纵 Cookies

应始终审查嵌入在 cookie 中的敏感数据。经过 Base64 或类似格式编码的 cookie 通常可以解码。这种漏洞允许攻击者更改 cookie 的内容,并通过将修改后的数据重新编码到 cookie 中来冒充其他用户。

会话劫持

此攻击涉及窃取用户的 cookie 以未经授权地访问其在应用程序中的帐户。通过使用窃取的 cookie攻击者可以冒充合法用户。

会话固定

在这种情况下,攻击者欺骗受害者使用特定的 cookie 登录。如果应用程序在登录时不分配新的 cookie则拥有原始 cookie 的攻击者可以冒充受害者。此技术依赖于受害者使用攻击者提供的 cookie 登录。

如果在子域中发现 XSS 或者控制子域,请阅读:

{% content-ref url="cookie-tossing.md" %} cookie-tossing.md {% endcontent-ref %}

会话捐赠

在这里,攻击者说服受害者使用攻击者的会话 cookie。受害者认为他们已登录到自己的帐户将无意中在攻击者的帐户上执行操作。

如果在子域中发现 XSS 或者控制子域,请阅读:

{% content-ref url="cookie-tossing.md" %} cookie-tossing.md {% endcontent-ref %}

JWT Cookies

单击上面的链接以访问解释 JWT 中可能存在缺陷的页面。

在 cookie 中使用的 JSON Web Tokens (JWT) 也可能存在漏洞。建议访问有关如何利用这些潜在缺陷的详细信息的链接文档,以获取深入信息。

跨站请求伪造 (CSRF)

此攻击强制已登录用户在当前已认证的 Web 应用程序上执行不需要的操作。攻击者可以利用自动发送到易受攻击站点的每个请求的 cookie。

(在原始研究中查看更多详细信息)浏览器允许创建没有名称的 cookie可以通过 JavaScript 示例如下:

document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"

发送的cookie头中的结果是 a=v1; test value; b=v2;。有趣的是如果设置了一个空名称cookie这将允许操纵cookie潜在地通过将空cookie设置为特定值来控制其他cookie

function setCookie(name, value) {
document.cookie = `${name}=${value}`;
}

setCookie("", "a=b"); // Setting the empty cookie modifies another cookie's value

这会导致浏览器发送一个名为 a 值为 b 的 cookie 头,被每个 Web 服务器解释为一个名为 a 值为 b 的 cookie。

Chrome Bug: Unicode Surrogate Codepoint Issue

在 Chrome 中,如果一个 Unicode 代理码点是一个设置的 cookie 的一部分,document.cookie 会变得损坏,随后返回一个空字符串:

document.cookie = "\ud800=meep";

这导致 document.cookie 输出一个空字符串,表明永久性损坏。

由于解析问题导致的Cookie走私

(请查看原始研究中的更多细节一些Web服务器包括JavaJettyTomCatUndertow和PythonZopecherrypyweb.pyaiohttpbottlewebob由于过时的RFC2965支持而错误处理Cookie字符串。它们将双引号括起的Cookie值视为单个值即使其中包含分号分号通常用于分隔键值对

RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";

(查看原始研究中的更多细节) 服务器对cookie的不正确解析特别是Undertow、Zope以及使用Python的http.cookie.SimpleCookiehttp.cookie.BaseCookie会导致cookie注入攻击的机会。这些服务器未能正确界定新cookie的开始允许攻击者伪造cookie

  • Undertow期望在带引号的值后立即出现新cookie而不带分号。
  • Zope寻找逗号来开始解析下一个cookie。
  • Python的cookie类在空格字符上开始解析。

这种漏洞在依赖基于cookie的CSRF保护的Web应用程序中尤为危险因为它允许攻击者注入伪造的CSRF令牌cookie可能绕过安全措施。Python处理重复cookie名称的方式进一步加剧了这个问题最后出现的覆盖了先前的。在不安全的环境中__Secure-__Host- cookie也引发了担忧当cookie传递给容易伪造的后端服务器时可能导致授权绕过。

额外易受攻击的Cookie检查

基本检查

  • cookie 每次登录都是相同的。
  • 注销然后尝试使用相同的cookie。
  • 尝试使用两台设备或浏览器使用相同的cookie登录同一帐户。
  • 检查cookie中是否有任何信息并尝试修改它。
  • 尝试创建几个几乎相同用户名的帐户,并检查是否存在相似之处。
  • 检查是否存在“记住我”选项看看它是如何工作的。如果存在且可能存在漏洞始终只使用“记住我”cookie而不使用其他cookie。
  • 检查即使在更改密码后先前的cookie是否仍然有效。

高级cookie攻击

如果在登录时cookie保持不变或几乎不变这可能意味着cookie与您帐户的某个字段相关可能是用户名。然后您可以

  • 尝试创建许多非常相似的用户名帐户,并尝试猜测算法是如何工作的。
  • 尝试暴力破解用户名。如果cookie仅保存为您用户名的身份验证方法那么您可以创建一个用户名为“Bmin”的帐户,并暴力破解您cookie的每一位因为您尝试的cookie之一将属于“admin”。
  • 尝试填充****Oracle您可以解密cookie的内容。使用padbuster

填充Oracle - Padbuster示例

padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf

# If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example:
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Padbuster将尝试多次并询问您哪个条件是错误条件即无效条件

然后它将开始解密cookie可能需要几分钟

如果攻击成功执行,那么您可以尝试加密您选择的字符串。例如,如果您想要加密 user=administrator

padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator

这个执行将给出正确加密和编码的 cookie其中包含字符串 user=administrator

CBC-MAC

也许一个 cookie 可能会有一些值,并且可以使用 CBC 进行签名。然后,值的完整性是使用相同值使用 CBC 创建的签名。由于建议使用一个空向量作为 IV这种完整性检查可能会有漏洞。

攻击

  1. 获取用户名 administ 的签名 = t
  2. 获取用户名 rator\x00\x00\x00 XOR t 的签名 = t'
  3. 在 cookie 中设置值 administrator+t't' 将是 (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00 的有效签名)

ECB

如果使用 ECB 加密 cookie可能会有漏洞。
当您登录时,收到的 cookie 必须始终相同。

如何检测和攻击:

创建两个几乎相同数据的用户(用户名、密码、电子邮件等),并尝试发现给定 cookie 中的某种模式

创建一个名为例如 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 的用户,并检查 cookie 中是否有任何模式(因为 ECB 使用相同的密钥加密每个块,如果用户名被加密,则相同的加密字节可能会出现)。

应该有一个模式(与使用的块大小相同)。因此,知道一堆 "a" 是如何加密的,您可以创建一个用户名:"a"*(块的大小)+"admin"。然后,您可以从 cookie 中删除一个块的加密模式 "a",然后您将得到用户名为 "admin" 的 cookie。

参考资料

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}

从零开始学习 AWS 黑客技术,成为专家 htARTE (HackTricks AWS Red Team Expert)!

支持 HackTricks 的其他方式: