hacktricks/pentesting-web/hacking-with-cookies/README.md
2023-08-03 19:12:22 +00:00

16 KiB
Raw Blame History

Cookies Hacking

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Cookies属性

Expires & Max-Age

  • Expires设置了一个cookie被删除的过期日期
  • Max-age设置了一个cookie将被删除的时间使用这个不再是2009年

Domain

Domain属性指定了哪些主机可以接收cookie。如果未指定该属性则默认为设置cookie的同一主机不包括子域。如果指定了Domain,则始终包括子域。因此,指定Domain比省略它更不限制。然而,当子域需要共享关于用户的信息时,它可能是有帮助的。

例如,如果你设置Domain=mozilla.org那么cookie在像developer.mozilla.org这样的子域上是可用的。但如果你不设置cookie将不会发送到子域。

如果子域sub.example.com设置了一个domain属性为.example.com的cookie它将在请求父域发送**。

Path

Path属性指示了必须存在于请求的URL中的URL路径,以发送Cookie头。%x2F ("/")字符被认为是目录分隔符,子目录也匹配。

顺序

当两个cookie具有相同的名称发送的cookie是

  • URL路径最长的路径匹配的那个
  • 如果两个路径相同,则是最新的那个

SameSite

这将告诉浏览器cookie是否可以从其他域发送。它有3个可能的值

  • Strictcookie不会随着第三方网站的请求一起发送。
  • Laxcookie将随着第三方网站发起的GET请求一起发送。
  • Nonecookie从任何第三方域发送
请求类型 示例代码 发送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的默认行为将是laxhttps://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)。
请注意,临时地,在应用此更改后,Chrome中没有SameSite策略的cookie在前2分钟内将被视为None然后在顶级跨站点POST请求中将被视为Lax。

Cookies标志

HttpOnly

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

绕过方法

  • 如果页面正在将cookie作为请求的响应发送例如在PHPinfo页面中可以滥用XSS发送请求到该页面并从响应中窃取cookie(在https://hackcommander.github.io/pentesting-article-1/)中查看示例)
  • 这可以通过TRACE HTTP请求绕过因为服务器的响应将反映发送的cookie如果此HTTP方法可用。这种技术称为跨站点跟踪
  • 现代浏览器通过不允许从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 %}

安全

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

Cookie前缀

__Secure-前缀必须在安全页面HTTPS上使用secure标志设置。

__Host-前缀必须在安全页面HTTPS上使用secure标志设置,不能指定域(因此不会发送到子域),路径必须为/

带有__Host-前缀的cookie不能发送到超域从子域到域或子域从域到子域因此如果您想隔离应用程序的cookie使用__Host-作为前缀不是一个坏主意。

Cookie攻击

如果您发现某种包含敏感数据会话ID、用户名、电子邮件等的自定义cookie您应该尝试利用它。

解码cookie

如果cookie使用某种基本编码如Base64或类似编码您可能能够解码它,更改内容冒充任意用户。

会话劫持

窃取cookie并使用它来冒充用户进入应用程序。

会话固定

攻击者从网页中获取一个cookie并向受害者发送一个链接要求使用相同的cookie进行登录。如果用户登录时cookie没有更改这可能很有用因为攻击者可以通过cookie冒充用户。

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

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

会话捐赠

攻击者向受害者发送自己的会话。受害者将看到自己已经登录,并认为自己在自己的账户中,但操作将在攻击者的账户中执行

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

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

点击上面的链接访问一个页面解释了JWT可能存在的缺陷。

空Cookie

浏览器允许使用空名称的cookie。

document.cookie = "a=v1"
document.cookie = "=test value;" // empty name
document.cookie = "b=v2"

这将导致发送的cookie头

a=v1; test value; b=v2;

更有趣的是,如果你有一种方法可以设置空的cookie,那么你就可以控制任何其他的cookie

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

setCookie("", "a=b"); // this sets the empty cookie to a=b

尽管在浏览器内部这被设置为空命名的cookie但它将导致发送的cookie头

a=b;

意思是每个web服务器都会将其解析为cookie a的值设置为b

Chrome Bug - document.cookie损坏

如果一个Unicode代理代码点在一个设置的cookie中document.cookie将永久损坏并返回一个空字符串。

document.cookie
// "a=b;"
document.cookie = "\ud800=meep";
document.cookie
// ""

Cookie劫持

一些Web服务器包括Java服务器Jetty、TomCat、Undertow和Python Web框架Zope以及Python Web服务器/框架如cherrypy、web.py、aiohttp server、bottle和webob发现由于对RFC2965的残留支持错误解析cookie字符串该机制是一种使用RFC2616定义的过时的cookie引用机制。

具体来说,当这些服务器遇到双引号dquoted的cookie值时即使遇到分号它们仍会继续读取cookie字符串。这是有问题的,因为分号应该用于分隔cookie字符串中的键值对

例如,如果浏览器发送了三个cookieRENDER_TEXT、JSESSIONIDASDF:

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

这些服务器将它们解释为一个单一的cookie值而不是三个独立的cookie。

这导致了一个安全风险如果攻击者获得了跨站脚本XSS访问权限他们可以利用这个漏洞来窃取敏感的cookie如HttpOnly cookie

Cookie注入

许多Web服务器包括Java的UndertowPython的Zope以及使用Python的stdlib http.cookie.SimpleCookie和http.cookie.BaseCookie的服务器被发现错误解析cookie使用错误的分隔符来开始下一个cookie名称/值对。这使得攻击者可以伪造多个cookie同时只控制一个cookie值

Undertow的情况下,它在一个带引号的cookie值结束后立即开始解析下一个cookie而不等待分号

LANGUAGE="en-us" CSRF_TOKEN="SPOOFED_VALUE"

Zope开始解析下一个cookie使用逗号作为分隔符:

LANGUAGE=en-us,CSRF_TOKEN=SPOOFED_VALUE

而Python的SimpleCookie和BaseCookie会立即在空格字符上开始解析下一个cookie

LANGUAGE=en-us CSRF_TOKEN=SPOOFED_VALUE

因此,像cherrypyweb.pyaiohttp服务器、bottlewebobPyramid、TurboGears这样的服务器都容易受到这种类型的攻击。

这个问题带来了重大的安全隐患。例如如果一个Web应用程序使用基于cookie的CSRF保护攻击者可以注入一个伪造的CSRF令牌cookie来绕过这种保护。此外Python的http.cookie包中最后一个重复的cookie名称会覆盖之前的任何cookie使得这种攻击特别容易。

此外在一个将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

如果cookie使用ECB进行加密可能存在漏洞。
当你登录时你收到的cookie必须始终相同。

如何检测和攻击:

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

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

应该有一个模式具有已使用块的大小。因此知道了一堆“a”的加密方式你可以创建一个用户名“a”*(块的大小)+“admin”。然后你可以从cookie中删除一个块的“a”的加密模式。这样你就得到了用户名“admin”的cookie。

参考资料

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥