挖掘 PDF 生成器中的 SSRF 漏洞:从发现到利用
挖掘 PDF 生成器中的 SSRF 漏洞
如果你在网站上看到以下功能之一,很可能遇到了服务器端请求伪造(SSRF)漏洞的热点区域:
打印完成证书
生成报告
提交数字签名
在深入探讨如何发现和利用 PDF 生成器中的 SSRF 漏洞之前,我们先做一个快速的思想实验。我想让你简单了解 Web 应用程序生成 PDF 时发生了什么。
想象你将一个非常基础的网页保存为桌面上的 HTML 文件,命名为 ssrf.html。该网页使用 JavaScript 获取图像并添加到网页中,代码如下:
然后,想象打开该 HTML 文件并使用浏览器的打印功能将其保存为 PDF。
浏览器解析了 HTML,执行了 JavaScript,并请求远程图像文件来生成 PDF。可以想象,如果攻击者能够影响生成 PDF 的 HTML,可能会带来严重的后果。以下是利用 SSRF 漏洞可以攻击的几个方面:
IMDS:如果服务器托管在云中(如 AWS、Azure 或 GCP),很可能能够与其实例元数据服务(IMDS)交互。如果运气好且启用了 AWS IMDSv1,可能从 IAM 端点泄漏 AWS 临时安全凭据,或从用户数据端点泄漏明文凭据。
PDF 生成器:PDF 生成组件本身可能易受攻击。
主机/服务发现:几乎肯定能够与服务器上运行的其他服务或无法公开访问的系统交互。
从哪里开始?
查看 PDF 并注意其中你提供给应用程序的任何数据,如姓名、地址、数字签名等。这些是值得调查的参数。在调查过程中,需要回答以下几个问题:
我可以注入 HTML 吗?
我可以访问远程服务器吗?
我可以执行 JavaScript 吗?
渲染 PDF 的服务器是否托管在云中?
生成 PDF 的组件是否存在已知漏洞?
我可以与其他哪些服务或系统交互?
我是否给了足够的时间?
最后一个问题实际上是一个故事,强调了我寻找难以捉摸的 SSRF 漏洞时遇到的挑战和解决方案。如果你遇到类似情况,这个经验可能有用。
在测试潜在来源时,你会在生成的 PDF 中获得视觉提示、回调到带外服务器(如 Burp Collaborator),或两者兼而有之。
如果你曾经利用过跨站脚本(XSS)漏洞,前几个问题应该很熟悉。利用 PDF 生成器中的 SSRF 漏洞非常类似于利用 XSS 漏洞。最大的区别是你没有 DOM 在眼前,因为一切都在服务器上发生。但思维方式非常相似。
我可以注入 HTML 吗?
你的 payload 可能在服务器上落在三种可能的上下文中:
在 HTML 标签之间
用撇号包裹,在 HTML 实体属性内
用引号包裹,在 HTML 实体属性内
如前所述,你可能看不到注入的内容,因此必须进行一些调查以确定 payload 落在哪个上下文中。以下代码块显示了 payload(高亮显示)。如果给定的 payload 渲染了,那么你就知道 payload 落在哪个上下文中。
关于最后两个上下文,即 payload 落在 HTML 实体属性内,如果你有 Burp 的 Pro 许可证,自动扫描发现“外部 HTTP 交互”很可能表明是最后两个上下文。如果没有 Pro 许可证,尝试将图像 URL 粘贴到 payload 位置。如果图像出现在 PDF 中,那也很好地表明你的 payload 落在最后两个上下文中之一。
在 HTML 标签之间
你的 payload 可能落在几个 HTML 标签之间。在这种情况下,尝试注入一个或两个 HTML 元素。使用两个元素很方便,因为如果 HTML 被渲染,你会在 PDF 中获得视觉提示,表明你的 HTML 被渲染了。
用撇号包裹,在 HTML 实体属性内
用引号包裹,在 HTML 实体属性内
陷阱!Atari 2600, 1982。警告: 在检查最后一个上下文(引号)时,注意你的请求类型。JSON 是一种非常常见的请求格式。不要忘记转义引号!
弄清楚 payload 落在哪个上下文中很重要,因为如果存在语法错误,你可能会看到错误消息,或者根本看不到任何内容。
我可以访问远程服务器吗?
如前所述,尝试将 URL 粘贴到你正在调查的 payload 位置。如果它获取远程资源或与你的 Burp Collaborator 交互,那么你知道你测试的服务器可以访问远程服务器。
如果你确定 payload 落在两个 HTML 标签之间,尝试类似以下的内容:
我还想强调一个你可能没想到易受 SSRF 攻击的功能。数字签名是 SSRF 的一个意外地方,但注意包含类似以下内容的请求:
这是数据 URL 的开始,这是一种应用程序可以内嵌图像的方式,而不是从远程服务器获取。以下是易受攻击的服务器可能期望的内容:
由于数据 URL 只是图像元素的来源,尝试用指向远程资源的 URL 替换数据 URL。
我可以执行 JavaScript 吗?
此时,你已经弄清了 payload 落在哪里,并验证了服务器可以拉取远程资源。接下来,你可以检查 JavaScript 执行。我的首选方法是使用类似以下的内容:
如果你在渲染的 PDF 中看到 BHIS logo,那么你知道 JavaScript 执行了。
现在,要记住一点。与测试 XSS 时一样,注入<script>
标签有可能被应用程序拒绝。你可能需要使用其他技术注入 JavaScript,例如通过事件处理程序。以下 payload 不会在 PDF 中渲染图像,但如果你在 Burp Collaborator 中看到回调,它将证明 JavaScript 执行。确保更新 URL 为你可以监控回调的域名。
渲染 PDF 的服务器是否托管在云中?
展示 SSRF 影响的经典攻击是从实例元数据服务(IMDS)泄漏 AWS IAM 临时安全凭据。具体来说,你需要确定服务器是否托管在 AWS 中并配置为支持 IMDS 版本 1。在这种情况下,你可能能够将临时安全凭据泄漏到 PDF 中。你需要至少发起两个请求来泄漏 AWS 访问密钥。第一个请求是泄漏 IAM 角色名称。使用 iframe 元素在 PDF 中查看响应。
第二个请求是泄漏安全凭据。从 PDF 复制 IAM 角色名称并将其添加到以下片段中。
如果你在 PDF 中看到类似以下的内容,那么你泄漏了 AWS 访问密钥,可能用于切换到 AWS 账户中的其他资源。
除了 AWS 访问密钥,查看用户数据 IMDS 端点中是否有任何敏感数据。BHIS 经常在用户数据端点找到包含明文凭据和秘密的脚本。有关如何掠夺 AWS IMDS 的更多想法,请参见以下内容。
生成 PDF 的组件是否存在已知漏洞?
最近,我找到了一个 SSRF 漏洞,其中 PDF 由无头 Chrome 渲染。在调查过程中,我发现应用程序通过无头 Chrome 生成 PDF 并不罕见。User-Agent 请求头提示了我,其中还包括 Chrome 版本号。令我沮丧的是,它已完全修补。但如果你幸运,可能会遇到未修补的版本,可能被利用进行远程代码执行或从服务器泄漏文件。
检查组件名称和版本的另一个地方是 PDF 本身的元数据。
此示例没有漏洞,但值得你花时间快速 Web 搜索你测试的组件中的漏洞。
我可以与其他哪些服务或系统交互?
这个问题非常开放,取决于上下文,但以下是一些值得思考的事情:
在侦察过程中是否遇到任何未解析的主机名?
应用程序中是否找到任何私有 IP 地址?
是否遇到任何容器技术可能存在的线索?
你是否在多方评估中,另一名测试人员从内部进行黑客攻击?
为了展示更大的影响,也许你可以协作展示如何利用 SSRF 从外部利用内部网络上的漏洞。
逐个检查这些将非常繁琐。幸运的是,PDF 生成器中的 SSRF 漏洞通常允许我们使用一堆 iframe 通过单个请求检查许多系统。这种方法的主要警告是,根据目标系统上启用的框架保护,你可能不会在 PDF 文档中看到响应。
要发送一堆 iframe,我喜欢从常见的 SSRF 目标和主机名列表开始。以下是一个示例起始列表。查看 PayloadAllTheThings 以生成更全面的列表。
接下来,我将使用以下 Bash 函数将每个 SSRF 目标包裹在 iframe 内。为了保持组织,我还包括一个标题元素。标题元素将出现在 PDF 中,以便你可以看到哪个 payload 产生了响应。如果你使用此脚本,请记住根据 payload 落点调整 CRADLE_OPEN 和 CRADLE_CLOSE 变量。如果你的 payload 落在 HTML 标签之间,以下脚本将是合适的。
最后,循环遍历 SSRF payload 文件以生成可以复制到 HTTP 请求中的“超级”payload。
以下是请求中最终 payload 的可能样子。
以下是评估期间使用此技术生成的 PDF 示例。
我是否给了足够的时间?
在最近的评估中,我在 AWS 服务器上找到了一个 SSRF 漏洞,几乎没泄漏 AWS 临时安全凭据。在初步调查期间,我发送了一个“超级”payload,并在 PDF 中看到了http://169.254.169.254/latest/端点的响应。但当我尝试单独访问http://169.254.169.254/latest/meta-data/iam/security-credentials端点,而不是“超级”payload 的其余部分时,我的 PDF 是空的。
我的第一个故障排除步骤是查看是否至少可以查看父目录。那没有用,所以我发送了原始的 IMDS 端点http://169.254.169.254/latest/,因为我有访问它的证明。当我尝试单独查看原始 IMDS 端点时,我的 PDF 仍然是空的。
这没有意义,所以我认为客户可能已经修补了它。但为了确保,我回去发送了原始的“超级”payload。“超级”payload 仍然从 IMDS 返回了响应。我思考了为什么发送“超级”payload 时可以看到响应,而单独发送 IMDS 端点的 payload 时却不行。我认为由于“超级”payload 框架了许多站点,渲染需要更长时间。也许额外的渲染时间允许在生成 PDF 之前从 IMDS 获取响应。我尝试使用 JavaScript 的 setTimeout()函数延迟执行,使用 2 到 30 秒之间的各种延迟。通过 JavaScript 延迟对服务器的响应时间没有影响,PDF 仍然是空的。也许延迟的方式有所不同。我修改了原始的“超级”payload,包括十个指向http://169.254.169.254/latest/meta-data/iam/security-credentials端点的 iframe,它工作了。我可以在 PDF 的所有十页上看到 AWS IAM 角色名称,因此我修改了请求以检索该角色的临时安全凭据。
在测试与其他系统的交互时,我使用 JavaScript 的 fetch() API 发起请求,并将响应(当 CORS 策略允许时)发送到我的 Burp Collaborator 服务器。
使用十个 iframe 时,我没有看到与 Burp Collaborator 的任何交互。在增加到 100 个 iframe 后,我开始看到与 Burp Collaborator 的交互。我得出结论,这必须延迟了 PDF 生成器足够长的时间以执行 JavaScript 并将响应发送到 Collaborator。
我不知道为什么用大量 iframe 引起延迟有效,而 JavaScript 却没有。仅分享以防你遇到这种情况。也许可以用其他元素(如图像)完成相同的操作。如果你知道原因或有替代解决方案,请告诉我!
结束语
当涉及查找和利用 PDF 生成器中的 SSRF 漏洞时,payload 和触发器很可能异步发送。我第一次找到 SSRF 漏洞时,易受攻击的参数在一个请求中发送,但 SSRF 的触发器是两个请求之后,并且并不立即明显哪个请求触发了 SSRF 漏洞。希望你能相信,额外努力寻找难以捉摸的 SSRF 漏洞是值得的——狩猎愉快!
有用资源
https://docs.google.com/presentation/d/1JdIjHHPsFSgLbaJcHmMkE904jmwPM4xdhEuwhy2ebvo/htmlpresent
https://www.jomar.fr/posts/2021/ssrf_through_pdf_generation/
https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/
https://www.triskelelabs.com/microstrategy-ssrf-through-pdf-generator-cve-2020-24815
https://blog.appsecco.com/an-ssrf-privileged-aws-keys-and-the-capital-one-breach-4c3c2cded3af
https://hackerone.com/reports/2262382?s=09
参考文献
https://portswigger.net/burp/documentation/collaborator
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
BHIS logo 的链接在撰写此博客时有效。对于此技术,确保使用存在的图像的 URL。
https://blog.checkpoint.com/security/aws-instance-metadata-service-imds-best-practices/
https://developer.chrome.com/blog/headless-chrome
https://blog.grio.com/2020/08/understanding-pdf-generation-with-headless-chrome.html
https://portswigger.net/daily-swig/severe-chrome-bug-allowed-rce-on-devices-running-remote-headless-interface
https://github.com/xcanwin/CVE-2023-4357-Chrome-XXE
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery
https://developer.mozilla.org/en-US/docs/Web/API/setTimeout 更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)公众号二维码
- 办公AI智能小助手
评论