某不知名博客 某不知名博客
首页
  • 《vulcat文档》
  • Web安全

    • 《BurpSuite及官方实验室》
    • 《OSWE学习历程》
  • 云原生安全

    • 《Docker命令大全》
    • 《CKS考试学习指南》
    • 《旧-Kubernetes教程》
漏洞库
  • 《渗透工具大全》
  • 《云安全》
事件库
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carsaid

安全界的小学生
首页
  • 《vulcat文档》
  • Web安全

    • 《BurpSuite及官方实验室》
    • 《OSWE学习历程》
  • 云原生安全

    • 《Docker命令大全》
    • 《CKS考试学习指南》
    • 《旧-Kubernetes教程》
漏洞库
  • 《渗透工具大全》
  • 《云安全》
事件库
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前言

  • 服务器端主题(翻译)

  • 客户端主题(翻译)

  • 高级主题(翻译)

    • 高级主题
    • 不安全的反序列化

    • Web LLM攻击

    • GraphQL API漏洞

    • 服务端模板注入

    • Web缓存投毒

      • Web缓存投毒
      • 利用缓存设计缺陷
      • 利用缓存实现缺陷
        • 利用缓存实现缺陷
        • 缓存键缺陷
        • 缓存探测方法
          • 识别合适的缓存预言机
          • 探测键处理
          • 识别可利用的Gadgets
        • 利用缓存键缺陷
          • 无键端口
          • 无键查询字符串
          • 检测无键查询字符串
          • 利用无键查询字符串
          • 无键查询参数
          • 缓存参数伪装
          • 利用参数解析差异
          • 利用畸形 GET 支持
          • 利用资源导入中的动态内容
          • 缓存键规范化
          • 缓存键注入
        • 内部缓存投毒
          • 如何识别内部缓存
          • 安全地测试内部缓存
    • HTTP主机头攻击

    • HTTP请求走私

    • OAuth身份验证漏洞

    • JWT攻击

    • 原型链污染

    • 基本技能

  • 扩展阅读(翻译)

  • 个人学习笔记

  • 实验室做题记录

  • BurpSuite及官方实验室
  • 高级主题(翻译)
  • Web缓存投毒
carsaid
2023-11-18
目录

利用缓存实现缺陷

翻译

原文:https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws

- name: 翻译
  desc: 原文:https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws
  bgColor: '#F0DFB1'
  textColor: 'green'
1
2
3
4

# 1利用缓存实现缺陷

在我们之前的实验中,你学习了如何操纵典型的无键输入(如 HTTP 标头和 Cookie)来利用 Web 缓存投毒漏洞。虽然这种方法是有效的,但它只触及了 Web 缓存投毒的表面。

在本节中,我们将演示如何利用 缓存系统特定实现 中的差异,来访问更广大的 Web 缓存投毒攻击面。特别是,我们将研究缓存键生成方式的缺陷,为什么这种缺陷会使网站容易受到缓存投毒的影响,这些漏洞通常被认为是不可利用的。我们还将展示 如何进一步利用经典技术,来潜在地破坏应用程序级的缓存,这通常会带来毁灭性的结果。

我们的研究总监 James Kettle 在 BlackHat USA 2020 上的演讲主题 “Web 缓存纠缠:投毒的新途径” 中首次记录了这些技术。如果你有兴趣了解 他是如何在野外发现和利用这些漏洞的,你可以从我们的研究页面 访问此演示文稿的录音以及随附的白皮书。

Research

  • Web 缓存纠缠:投毒的新途径 (opens new window)

# 2缓存键缺陷

一般来说,网站从 URL 路径和查询字符串中获取大部分输入。因此,这是各种黑客技术的一个广为人知的攻击面。然而,由于请求行通常是缓存键的一部分,因此这些输入在传统上,被认为不适合缓存投毒。任何通过键控输入来注入的有效载荷,都将充当缓存破坏器,这意味着你毒害的缓存条目,几乎不会提供给任何其他用户。

但是,仔细观察后会发现,各个缓存系统的行为,并不总是像你所期望的那样。在实践中,许多网站和 CDN 在键控组件被保存至缓存键中时,会对它们执行各种转换。这可能包括:

  • 排除查询字符串
  • 筛选出特定的查询参数
  • 对键控组件中的输入进行规范化

这些转换 可能会引入一些意想不到的差异。这些问题主要是数据之间的差异(写入该缓存键的数据 和 传递到应用程序代码中的数据之间),即使它们都源于相同的输入。这些缓存键缺陷可被利用,通过 最初看起来不可用的输入 毒害该缓存。

在完全集成的 应用程序级缓存 中,这些差异可能更加极端。事实上,内部缓存可能非常不可预测,以至于有时,很难在 不毒害实时用户的缓存 的情况下对其进行测试。

# 3缓存探测方法

探测缓存实现缺陷的方法,与经典的 Web 缓存投毒方法略有不同。这些较新的技术依赖于 缓存的特定实现方式和配置中的缺陷,这些缺陷可能因站点而异。这意味着,你需要更深入地了解目标缓存及其行为。

在本节中,我们将概述 缓存探测行为并识别任何潜在缺陷 的高级方法。之后,我们将提供一些更具体的 常见缓存键缺陷示例,以及如何利用它们。

该方法包括以下步骤:

  • 识别合适的缓存预言机 (opens new window)
  • 探测键处理 (opens new window)
  • 识别可利用的 Gadgets (opens new window)

# 3.1识别合适的缓存预言机

第一步,确定一个可用于测试的合适 “缓存预言机”。缓存预言机只是一个页面或端点,提供有关缓存行为的反馈。这需要是可缓存的,并且必须以某种方式指示,你收到的是缓存响应 还是 直接从服务器接收的响应。这种反馈可以采取多种形式,例如:

  • 一个 HTTP 标头,它明确告诉你是否命中了缓存
  • 动态内容的可观察变化
  • 不同的响应时间

理想情况下,缓存预言机还将在响应中反馈整个 URL 和至少一个查询参数。这样可以更容易地注意到 缓存和应用程序之间 的解析差异,这对于以后构建不同的漏洞非常有用。

如果你可以确定,目标正在使用特定的第三方缓存,则还可以查阅相应的文档。这可能包含有关于 如何构造默认缓存键 的信息。甚至,你可能会偶然发现一些方便的提示和技巧,比如允许你直接查看缓存键的功能。举个例子,基于 Akamai 的网站可能支持标头Pragma: akamai-x-get-cache-key,通过使用该标头,你可以在响应标头中显示缓存键:

GET /?param=1 HTTP/1.1
Host: innocent-website.com
Pragma: akamai-x-get-cache-key

HTTP/1.1 200 OK
X-Cache-Key: innocent-website.com/?param=1
1
2
3
4
5
6

# 3.2探测键处理

下一步,调查该缓存 在生成缓存键时,是否对输入执行了任何附加处理。你正在寻找 隐藏在关键组件中的 额外攻击面。

你应该特别关注 正在发生的任何转化。将键控组件添加到缓存键时,是否有任何内容被排除在外?常见的示例包括 排除特定查询参数,甚至整个查询字符串,以及从Host标头中删除端口。

如果你有幸能够直接访问缓存键,则可以在注入不同的输入后,简单地比较这些键。否则,你可以利用对缓存预言机的理解,来推断是否收到了正确的缓存响应。对于要测试的每个案例,你应该发送两个类似的请求并比较响应。

假设,我们的缓存预言机是目标网站的主页。这会自动将用户重定向到特定于区域的页面。它使用Host标头在响应中动态生成Location标头:

GET / HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 302 Moved Permanently
Location: https://vulnerable-website.com/en
Cache-Status: miss
1
2
3
4
5
6

要测试端口是否从该缓存键中排除,我们首先需要请求一个任意端口,并确保我们从 服务器 收到了反馈此输入的新响应:

GET / HTTP/1.1
Host: vulnerable-website.com:1337

HTTP/1.1 302 Moved Permanently
Location: https://vulnerable-website.com:1337/en
Cache-Status: miss
1
2
3
4
5
6

接下来,我们将发送另一个请求,但这次我们不会指定端口:

GET / HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 302 Moved Permanently
Location: https://vulnerable-website.com:1337/en
Cache-Status: hit
1
2
3
4
5
6

正如你所看到的,即使请求中的Host标头没有指定端口,我们也收到了缓存响应。这证明端口已从缓存键中排除。重要的是,完整的标头仍然会传递到应用程序代码中,并反馈在响应中。

简而言之,尽管Host标头是键控的,但缓存转换它的方式 允许我们将有效载荷 传递到应用程序中,同时,映射到其他用户请求的 “正常” 缓存键仍然会被保留。这种行为是我们将在本节中讨论的,所有漏洞背后的关键概念。

你可以使用类似的方法,来调查缓存对输入的任何其他处理。你的输入是否以任何方式规范化?你的输入是如何存储的?你注意到任何异常了吗?稍后我们将通过具体的示例,来回答这些问题。

# 3.3识别可利用的Gadgets

到现在为止,你应该已经对 目标网站的缓存行为方式 有了相对扎实的了解,并且可能已经在缓存键的构造方式中,发现了一些有趣的缺陷。

最后一步,确定一个合适的 Gadgets,你可以用这个缓存键缺陷来链接它。这是一项重要的技能,因为任何 Web 缓存投毒攻击的严重程度,很大程度上都取决于你能够利用的 Gadgets。

这些 Gadgets 通常是典型的客户端漏洞,例如反射型 XSS 和开放重定向。通过将这些漏洞与 Web 缓存投毒相结合,你可以大幅提升这些攻击的严重性,将反射的漏洞转变为存储的漏洞。对于访问普通的、完全合法的 URL 的任何人,你的有效载荷将自动提供给他们,而不必诱导受害者访问特制的 URL。

也许更有趣的是,这些技术使你能够利用许多未分类的漏洞,这些漏洞通常被视为 “不可利用” 且未修补。这包括在资源文件中使用动态内容,以及需要 “浏览器永远不会发送格式错误的请求” 的攻击。

# 4利用缓存键缺陷

现在,你已经熟悉了高级方法,让我们来看看一些典型的缓存键缺陷,以及如何利用它们。我们将介绍:

  • 无键端口 (opens new window)
  • 无键查询字符串 (opens new window)LABS
  • 无键查询参数 (opens new window)LABS
  • 缓存参数伪装 (opens new window)LABS
  • 缓存键规范化 (opens new window)LABS
  • 缓存键注入 (opens new window)LABS
  • 内部缓存投毒 (opens new window)LABS

# 4.1无键端口

Host标头通常是缓存键的一部分,最初,似乎不太可能注入有效载荷。然而,某些缓存系统会解析标头,并从缓存键中排除端口。

在这种情况下,你可能会将此标头用于 Web 缓存投毒。例如,考虑我们之前看到的情况,其中重定向 URL 是基于Host标头动态生成的。这使你能够简单地向请求添加任意端口,来构建拒绝服务攻击。所有浏览到主页的用户,都将被重定向到一个无用的端口,从而有效地关闭主页,直到缓存过期。

如果网站允许你指定非数字端口,则此类攻击可能会进一步升级。例如,你可以使用它来注入 XSS 有效载荷。

# 4.2无键查询字符串

与Host标头一样,请求行通常是键控的。但是,最常见的缓存键转换之一是,排除整个查询字符串。

# 4.2.1检测无键查询字符串

如果响应显式地告诉你 是否命中了缓存,则这种转换相对容易发现 - 但如果没有呢?这样做的副作用是 使动态页面看起来像是完全静态的,因为很难知道 你是在与目标缓存通信 还是在与服务器通信。

要识别动态页面,通常需要观察 更改参数值时 对响应的影响。但是,如果查询字符串是无键的,那么大多数情况下,无论你添加什么参数,你仍然会获得缓存命中,因此不会得到一个不变的响应。显然,这也使得 经典的缓存破坏查询参数 变得多余。

幸运的是,还有其他方法可以添加缓存破坏器,例如,将其添加到 不会干扰应用程序行为 的键控标头中。一些典型的例子包括:

Accept-Encoding: gzip, deflate, cachebuster
Accept: */*, text/cachebuster
Cookie: cachebuster=1
Origin: https://cachebuster.vulnerable-website.com
1
2
3
4

如果你使用 Param Miner,你也可以选择 “Add static/dynamic cache buster” 和 “Include cache busters in headers” 选项。然后,它将在你使用的 Burp 手动测试工具里、将被发送的任何请求中,自动添加一个缓存破坏器 到 请求的常用键控标头中。

另一种方法是,查看缓存 和 后端规范化请求路径的方式之间,是否存在任何差异。由于路径几乎可以保证是键控的,因此你有时可以利用这一点,发出具有不同键的请求,这些请求仍然会命中同一个端点。例如,以下条目可能都被单独缓存,但在后端被视为等效的GET /:

  • Apache:GET //
  • Nginx:GET /%2F
  • PHP:GET /index.php/xyz
  • .NET:GET /(A(xyz)/

有时,这种转换会掩盖那些 原本非常明显的反射型 XSS 漏洞。如果渗透测试人员 或 自动扫描程序,只接收缓存的响应,而没有意识到这一点,则该页面上可能 看起来好像没有反射型 XSS。

# 4.2.2利用无键查询字符串

从缓存键中排除查询字符串,实际上会使这些反射型 XSS 漏洞更加严重。

通常,这种攻击依赖于 诱导受害者访问恶意制作的 URL。但是,通过毒害无键的查询字符串,本来那些访问正常 URL 的用户,将会自动收到有效载荷。这有可能影响更多的受害者,而攻击者却不需要任何的交互。

实验室-从业者

通过无键查询字符串实现的 Web 缓存投毒 >>

- name: 实验室-从业者
  desc: 通过无键查询字符串实现的 Web 缓存投毒 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-unkeyed-query
  bgColor: '#001350'
  textColor: '#4cc1ff'
1
2
3
4
5
6

# 4.3无键查询参数

到目前为止,我们已经看到,在某些网站上,整个查询字符串都从缓存键中排除。但有些网站只排除 与后端应用程序无关的 特定查询参数,例如 用于分析或提供定向广告的参数。像utm_content这样的 UTM 参数,是在测试期间经过良好测试的候选参数。

已经从缓存键中排除的参数,不太可能会对响应产生重大影响。也许不会有任何有用的 Gadgets 接受来自这些参数的输入。也就是说,某些页面以易受攻击的方式处理整个 URL,从而导致 其中的任意参数 有可能被利用。

实验室-从业者

通过无键查询参数实现的 Web 缓存投毒 >>

- name: 实验室-从业者
  desc: 通过无键查询参数实现的 Web 缓存投毒 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-unkeyed-param
  bgColor: '#001350'
  textColor: '#4cc1ff'
1
2
3
4
5
6

# 4.4缓存参数伪装

如果缓存 从缓存键中排除了无害的参数,并且你无法根据完整的 URL 找到任何可利用的 Gadgets,此时你认为自己已经走到了死胡同。然而,这实际上是事情变得有趣的地方。

如果你能弄清楚,该缓存如何解析 URL 以识别和删除不需要的参数,你可能会发现一些有趣的差异。特别值得关注的是,缓存和应用程序之间的任何解析差异。这有可能允许你将任意参数 “隐藏” 在被排除的参数中,从而使任意参数潜入应用程序逻辑中。

例如,事实上的标准是,如果这个参数 是查询字符串中的第一个字符,则参数前面将带有问号(?),或者带有与号(&)。一些写得不好的解析算法,会将任何?作为新参数的开始,无论它是否是第一个参数。

让我们假设,从缓存键中排除参数的算法,将会以这种方式运行 - 服务器的算法只接受第一个?作为分隔符。请考虑以下请求:

GET /?example=123?excluded_param=这里有坏东西
1

在这种情况下,缓存将标识两个参数,并从缓存键中排除第二个参数。然而,服务器不接受第二个?作为分隔符,而是将其视为单个example参数,其值是查询字符串的整个其余部分,包括我们的有效载荷。如果将example的值传递到有用的 Gadgets 中,那么我们就可以成功注入有效载荷,而不会影响缓存键。

# 4.4.1利用参数解析差异

而在相反的场景中,也可能会出现类似的参数伪装问题,即后端识别到了缓存系统无法识别的不同参数。例如,Ruby on Rails 框架将与号(&)和分号(;)解释为分隔符。当这些符号被结合使用时,如果缓存无法识别它们,则你可以利用另一个差异,来覆盖应用程序逻辑中的键控参数值。

请考虑以下请求:

GET /?keyed_param=abc&excluded_param=123;keyed_param=这里有坏东西
1

顾名思义,keyed_param包含在缓存键中,但excluded_param不包含在缓存键中。许多缓存只会将其解释为两个参数,通过与号分隔:

  1. keyed_param=abc
  2. excluded_param=123;keyed_param=这里有坏东西

一旦解析算法删除了excluded_param,该缓存键将仅包含keyed_param=abc。然而,后端中的 Ruby on Rails 遇到这个查询字符串时,会通过分号将其拆分为三个单独的参数:

  1. keyed_param=abc
  2. excluded_param=123
  3. keyed_param=这里有坏东西

但现在有一个重复的keyed_param。这就是第二个差异发挥作用的地方。如果存在重复的参数,每个参数都有不同的值,则 Ruby on Rails 会优先考虑最后出现的参数。最终的结果是,该缓存键包含一个无害的、预期的参数值,允许缓存的响应被正常提供给其他用户。然而,在后端,相同的参数具有一个完全不同的值,即我们注入的有效载荷。这第二个值将被传递到 Gadgets 中,并反馈在中毒的响应中。

如果你可以控制将要执行的函数,则此漏洞利用可能特别强大。例如,如果一个网站使用 JSONP 发出跨域请求,这通常会包含一个回调参数,用于对返回的数据执行给定的函数:

GET /jsonp?callback=innocentFunction
1

在这种情况下,你可以使用这些技术,来覆盖预期的回调函数,并改为执行任意 JavaScript。

实验室-从业者

参数伪装 >>

- name: 实验室-从业者
  desc: 参数伪装 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking
  bgColor: '#001350'
  textColor: '#4cc1ff'
1
2
3
4
5
6

# 4.4.2利用畸形 GET 支持

在某些情况下,HTTP 方法可能没有键控。这可能允许你在正文中包含恶意负载,并通过POST请求来毒害缓存。然后,你的有效载荷甚至会响应用户的GET请求。尽管这种情况非常罕见,但有时只需向GET请求添加一个正文以创建 “畸形” GET请求即可实现类似的效果:

GET /?param=innocent HTTP/1.1
…
param=这里有坏东西
1
2
3

在这种情况下,缓存键基于请求行,但服务端将从正文中获取参数的值。

实验室-从业者

通过畸形 GET 请求实现的 Web 缓存投毒 >>

- name: 实验室-从业者
  desc: 通过畸形 GET 请求实现的 Web 缓存投毒 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
  bgColor: '#001350'
  textColor: '#4cc1ff'
1
2
3
4
5
6

只有当网站接受具有正文的GET请求时,这才有可能,但也有潜在的变通方法。有时可以通过覆盖 HTTP 方法来推动“畸形GET” 处理,例如:

GET /?param=innocent HTTP/1.1
Host: innocent-website.com
X-HTTP-Method-Override: POST
…
param=这里有坏东西
1
2
3
4
5

只要X-HTTP-Method-Override标头没有键控,就可以提交伪POST请求,同时保留从请求行派生的GET缓存密键。

# 4.4.3利用资源导入中的动态内容

导入的资源文件通常是静态的,但有些文件会反馈来自查询字符串的输入。这通常被认为是无害的,因为在直接查看时,浏览器很少执行这些文件,并且攻击者无法控制 用于加载页面子资源的 URL。但是,将其与 Web 缓存投毒相结合,有时可以将内容注入到资源文件中。

例如,假设有一个页面,在import语句中反馈了当前的查询字符串:

GET /style.css?excluded_param=123);@import… HTTP/1.1

HTTP/1.1 200 OK
…
@import url(/site/home/index.part1.8a6715a2.css?excluded_param=123);@import…
1
2
3
4
5

你可以利用此行为注入恶意 CSS,从导入/style.css的任何页面中泄露敏感信息。

如果导入 CSS 文件的页面没有指定doctype,你甚至可以利用静态 CSS 文件。在配置正确的情况下,浏览器只会在文档中简单地搜索 CSS,然后执行它。这意味着,如果服务器错误地反馈了被排除的查询参数,则你可以毒害静态 CSS 文件:

GET /style.css?excluded_param=alert(1)%0A{}*{color:red;} HTTP/1.1

HTTP/1.1 200 OK
Content-Type: text/html
...
由于以下原因,此请求被阻止...alert(1){}*{color:red;}
1
2
3
4
5
6

# 4.5缓存键规范化

应用于缓存键上的任何规范化,也可能会引入可利用的行为。事实上,它偶尔可以暴露一些原本几乎不可能的漏洞。

例如,当你在一个参数中发现反射型 XSS 时,它在实践中通常是不可利用的。这是因为,现代浏览器在发送请求时,通常会对必要的字符进行 URL 编码,而服务器不会对其进行解码。目标受害者收到的响应中,将仅包含一个无害的 URL 编码字符串。

某些缓存实现特性,在将键控输入添加到缓存键时,会对其进行规范化。在这种情况下,以下两个请求将具有相同的键:

GET /example?param="><test>
GET /example?param=%22%3e%3ctest%3e
1
2

这种行为允许你利用这些原本 “不可利用” 的 XSS 漏洞。如果你使用 Burp Repeater 发送恶意请求,则可以使用未编码的 XSS 有效载荷来毒害该缓存。当受害者访问恶意 URL 时,其浏览器仍然会对负载进行 URL 编码;但是,一旦 URL 被缓存规范化,那么它们(有编码的响应 和 无编码的响应)将被视为相同的缓存键。

因此,缓存将提供中毒的响应,有效载荷会在客户端执行。你只需要确保受害者访问 URL 时,缓存已经中毒。

实验室-从业者

URL规范化 >>

- name: 实验室-从业者
  desc: URL规范化 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-normalization
  bgColor: '#001350'
  textColor: '#4cc1ff'
1
2
3
4
5
6

# 4.6缓存键注入

有时,你会在键控标头中发现客户端漏洞。这也是一个典型的 “不可利用” 问题,但有时可以通过缓存投毒来利用。

键控组件 通常捆绑在一个字符串中,以创建缓存键。如果缓存 没有在组件之间 实现分隔符的正确转义,则你可以利用此行为,来构建具有相同缓存键的两个不同请求。

在以下示例中,使用 双下划线 来分隔缓存键中的不同组件,并且不对它们进行转义。你可以利用这一点,首先创建第一个请求,在相应的键控标头中包含有效载荷,从而毒化缓存:

GET /path?param=123 HTTP/1.1
Origin: '-alert(1)-'__

HTTP/1.1 200 OK
X-Cache-Key: /path?param=123__Origin='-alert(1)-'__

<script>…'-alert(1)-'…</script>
1
2
3
4
5
6
7

随后,如果你诱导受害用户访问以下 URL,他们将收到有毒的响应:

GET /path?param=123__Origin='-alert(1)-'__ HTTP/1.1

HTTP/1.1 200 OK
X-Cache-Key: /path?param=123__Origin='-alert(1)-'__
X-Cache: hit

<script>…'-alert(1)-'…</script>
1
2
3
4
5
6
7

实验室-专家

缓存键注入 >>

- name: 实验室-专家
  desc: 缓存键注入 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-cache-key-injection
  bgColor: '#001350'
  textColor: '#d112fe'
1
2
3
4
5
6

# 5内部缓存投毒

到目前为止,我们已经研究了如何利用外部 Web 缓存实现方式中的缺陷,来暴露 隐藏在关键组件中 的扩展攻击面。但是,除了使用不同的外部组件外,某些网站还 直接在应用程序中 实现缓存行为。这样做有几个好处,例如避免了我们之前看到的那种解析差异。

由于这些集成缓存 是专门为特定应用程序构建的,这在更大程度上,使开发人员可以自由地定制其行为。因此,这些缓存有时可能会以不寻常的方式运行,而在需要与多个应用程序兼容的、更标准化的外部缓存中,你通常不会看到这些运行方式。有时,这些奇怪的行为也可能为一些 高严重性的缓存投毒攻击 提供机会。

这些缓存不是为了缓存整个响应,而是将响应分解为可重用的片段,并分别缓存它们。例如,一个代码段用于导入广泛使用的资源,这可以存储为独立的缓存条目。然后,用户可能会收到一个响应,其中包含来自服务器的混合内容,以及来自该缓存的几个单独片段。

由于这些缓存的片段 旨在 跨多个不同的响应中进行重用,因此缓存键的概念并不真正适用。包含给定片段的每个响应,都将重用相同的缓存片段,即使响应的其余部分完全不同。在这种情况下,毒害缓存可能会产生广泛的影响,尤其是在毒害每个页面上使用的片段时。由于没有缓存键,因此你将通过单个请求,分别对每个用户的每个页面进行毒害。

这通常只需要基本的 Web 缓存中毒技术,例如操纵Host标头。

# 5.1如何识别内部缓存

集成的 应用程序级缓存 带来的挑战之一是,它们可能很难被识别和探查,因为它们通常没有面向用户的反馈。要识别这些缓存,你可以寻找一些可疑的迹象。

例如,你发送了前一个请求,稍后发送了最后一个请求,如果响应反馈了来自这两个响应的混合输入,则表明该缓存 存储的是片段,而不是整个响应,这是一个关键的迹象。如果你的输入 反馈在 多个不同页面的响应中,而且是在你从未尝试过注入的页面上,则这同样是一个迹象。

其他时候,缓存的行为可能非常不寻常,以至于最合乎逻辑的结论是,它必须是唯一且专用的内部缓存。

当网站实现多层缓存时,人们很难了解幕后发生了什么,也很难理解网站的缓存系统是如何工作的。

实验室-专家

内部缓存投毒 >>

- name: 实验室-专家
  desc: 内部缓存投毒 >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-internal
  bgColor: '#001350'
  textColor: '#d112fe'
1
2
3
4
5
6

# 5.2安全地测试内部缓存

在测试普通 Web 缓存时,我们建议使用缓存破坏器,防止将中毒的响应提供给其他用户。但是,如果集成的缓存 没有缓存键的概念,那么传统的缓存破坏器就毫无用处了。这意味着,真正用户的缓存很容易被毒害。

因此,在测试此类漏洞时,请务必尽最大的努力,减轻所带来的潜在损害。在发送每个请求之前,请仔细考虑 注入的有效载荷 是否会产生影响。特别是,你应该只使用你控制的域,而不是一些任意的 “evil-user.net” 来毒害缓存。这样,如果出了问题,你就可以在你的域上,控制接下来会发生什么。

编辑 (opens new window)
利用缓存设计缺陷
HTTP主机头攻击

← 利用缓存设计缺陷 HTTP主机头攻击→

最近更新
01
API测试笔记
04-30
02
msfvenom
03-29
03
Metasploit
03-29
更多文章>
Theme by Vdoing | Copyright © 2023-2024 Carsaid | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式