壹、摘要

隨著 CDN 技術的普及,使網站的載入速度加快,並提供安全性的防護,但因其解析方式上的差異,也增加了攻擊者的攻擊面。本技術分析報告將針對 Martin Doyhenard 在 Black Hat 2024 的演講《Gotta Cache ‘em all: bending the rules of web cache exploitation》中提出的技術進行分析,並著重在 Web Cache Deception(網頁快取欺騙)。

貳、分析動機

為了增加伺服器的隱蔽性同時降低伺服器的壓力,我通常習慣為自己的網站掛上 Cloudflare 的免費 CDN 服務。本以為 CDN 能夠提高安全性,沒想到竟然也帶來了新的攻擊面。

參、背景知識

一、Web Cache

有些靜態資源需要重複請求,但由於其資源之更換頻率低,因此不需要每次都請求原始伺服器,此時就可以將資源暫存在快取伺服器中。當客戶端請求資源時,就可以直接存取快取伺服器而不需要向原始伺服器再次請求資源。

二、CDN

CDN 全名 Content Delivery Network,是由分布在全球各地的伺服器節點組成,其主要目的是將資源暫存在距離使用者最近的伺服器以加快存取速度。同時因為其大量的節點,經常也會提供 DDoS 流量清洗、Web 防火牆(WAF)、SSL/TLS 加密等功能。

三、Web Cache 攻擊類型

  • Web Cache Poisoning(網頁快取中毒):攻擊者嘗試在快取中儲存惡意內容,當受害者嘗試存取網頁時,就會收到被污染的回應。

  • Web Cache Deception(網頁快取欺騙):攻擊者透過一些技術,使受害者敏感資料被快取伺服器判定為靜態資源,從而將其儲存。接著,攻擊者再此存取相同資源即可取得受害者的敏感資料。

肆、URL 的解析方式

為了能夠讓快取儲存不應該被儲存的靜態資源,可以透過 URL 解析方式的差異加以利用。以下為一個簡單的範例:

  1. CDN 會儲存路徑 /assets 下面的資源的所有請求。但不會進行正規化處理,因此 /assets/../admin 也會被認定為 /assets 中的資源。
  2. 然而,原始伺服器收到請求後會進行正規化處理,回應 /admin 的資料。
  3. 因此攻擊者僅需使受害者存取 /assets/../admin,接著再快取移除前存取相同的路徑,就能夠取得受害者的 /admin 頁面並取得敏感資料。

一、分隔符號

為了達到 URL 解析不一致的目的,可以嘗試使用不同的分隔符號,觀察快取伺服器及原始伺服器如何解析。例如:快取伺服器可能預設不會對任何分隔符號進行截斷,但原始伺服器遇到分號 ; 則會將其截斷,因此當請求 /admin;style.css 時,快取伺服器就會將管理者頁面的回應判斷成靜態資源 CSS 檔並將其儲存。

常見的分隔符號有:;#? 等。在進行測試時,可參考 PortSwigger 提供的分隔符號列表。若使用 BurpSuite 的 Intruder,要記得將 URL 編碼取消勾選。

alt text

二、正規化

遇到 ../ 時,有些伺服器會回到父路徑,有些則不會,因此可透過正規化的差異進行網頁快取的利用。例如:在向不會進行正規化的快取伺服器請求 /static/../admin 時,快取伺服器會將其認定為靜態資源,然而原始伺服器會將其解析成 /admin,造成正規化的不一致。

以下是常見的 CDN 及原始伺服器對於 /static/..%2fadmin 請求的解析結果。

CDN提供商 解析結果
CloudFlare /static/..%2fadmin
CloudFront /admin
GCP /static/..%2fadmin
Azure /admin
Imperva /admin
Fastly /static/..%2fadmin
原始伺服器 解析結果
Apache /static/..%2fadmin
Nginx /admin
IIS /admin
Gunicore /static/..%2fadmin
OpenLite /admin
Puma /static/..%2fadmin

伍、漏洞利用

一、靜態副檔名

有許多 CDN 提供商或快取伺服器都會儲存具有靜態副檔名的資源,如果請求路徑的結尾為 .js.css 等,就會被視為靜態資源儲存。以下提供一個範例:

  • 瀏覽器請求資源 /admim%23a.css
  • 快取伺服器偵測到結尾為 .css 因此將其判定為靜態資源
  • 原始伺服器將 %23 解析為 #,回應資源 /admin
  • 攻擊者可誘使受害者存取 /admin%23a.css,隨後立即存取 /admin,就能夠取得受害者的 /admin 頁面。

INFO

關於 Cloudflare CDN 預設的靜態副檔名請見官方文件:https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions

二、靜態資源

一些常見的路徑下通常只會儲存靜態資源,此時也可透過這點搭配分隔符號或正規化的差異進行利用。常見的靜態目錄包含:

  • /static
  • /assets
  • /wp-content
  • /media
  • /templates

除了靜態目錄外,也有一些特定的檔案不在上述的靜態目錄中,但其變更的次數並不頻繁。包含:robots.txtfavicon.ico 等。

陸、防護方式

身為一個網站開發者,可以透過以下常見方式避免網頁快取欺騙攻擊:

  1. 將 Cache Header 設定為 no-storeprivate
  2. 確保 CDN 和原始伺服器的快取規則相同。

柒、深入學習

一、PortSwigger Academy Lab

alt

為了能夠深入了解漏洞之原理及利用方式,我嘗試完成 PortSwigger Academy 中 Web cache deception 主題的所有 Lab 並撰寫 Writeup。Writeup 如下:

Lab: Exploiting path mapping for web cache deception

  1. 偵查目標
    1. 使用帳號 wiener、密碼 peter 登入。
    2. 發現回應包含 API key
  2. 辨識路徑解析不一致
    1. 發送 /my-account/abc 路徑的請求,發現回應資料仍然包含你的 API Key,表示原始伺服器將其解析成 /my-account
    2. 在 URL 路徑加上副檔名,例如:/my-account/abc.js,接著發送請求。發現回應包含 X-Cache: miss(表示回應不是從快取提供)和 Cache-Control: max-age=30(表示會被儲存 30 秒)表頭。
    3. 在 30 秒內重新傳送請求,發現表頭 X-Cache 的數字變成 hit,表示回應資料來自快取。由此可以推斷快取解釋 URL 路徑為 /my-account/abc.js 並符合 .js 副檔名的快取規則。所以可以使用這個 payload 進行利用。
  3. 進行漏洞利用
    1. 在網站中點擊 Go to exploit server
    2. Body 部分讓受害者(carlos)跳轉到你製作的惡意 URL。需注意應修改路徑後方的參數,以避免受害者存取到你之前存取的快取回應。
      <script>document.location="https://YOUR-LAB-ID.web-security-academy.net/my-account/wcd.js"</script>
    3. 點擊 Deliver exploit to victim。當受害者存取該 URL,回應會儲存在快取。
    4. 前往提供給受害者(carlos)存取的路徑(https://YOUR-LAB-ID.web-security-academy.net/my-account/wcd.js),就可以看到 carlos 的 API Key 了。

Lab: Exploiting path delimiters for web cache deception

  1. 偵查:使用 Burp Intruder 嘗試不同分隔字元,判斷原始伺服器會解析哪些分隔符號
    1. 將請求傳送到 Intruder
    2. 加上參數
    3. Web cache deception lab delimiter list 中的字元貼上到 payload 的地方
    4. 取消勾選 URL-encode these characters 選項
    5. 點擊 Start attack 完成攻擊後,會發現只有字元 ?; 回應 200,其他都是 404
  2. 偵查:判斷是否會被快取儲存
    1. 使用 ? 字元作為分隔符號會發現 header 沒有快取的痕跡
    2. 使用 ; 字元作為分隔符號連續請求兩次,發現 header 有被快取儲存的跡象

  3. 漏洞利用
    1. 在 Go to exploit server 的 body 撰寫 payload
      <script>document.location="https://YOUR-LAB-ID.web-security-academy.net/my-account;wcd.js"</script>
    2. 接著前往路徑 https://YOUR-LAB-ID.web-security-academy.net/my-account;wcd.js 就可以拿到受害者的 API key 了!

Lab: Exploiting origin server normalization for web cache deception

  1. 偵查原始伺服器標準化
    1. 前往路徑 /my-account,會回傳個人資料頁面並顯示 API Key
    2. 前往路徑 /aaa/..%2fmy-account 仍成功回傳個人資料頁面並顯示 API Key,且路徑列顯示 /aaa/..%2fmy-account,表示原始伺服器會解析 %2f
  2. 偵查快取伺服器標準化
    1. 尋找一個正確的靜態資源並確保其有被快取,這裡選擇:/resources/labheader/js/labHeader.js
    2. 前往路徑 /aaa/..%2fresources/labheader/js/labHeader.js 發現快取並不會將其儲存
    3. 判斷快取伺服器不會解析 %2f 且快取規則包含開頭為靜態資源路徑之規則
  3. 利用
    1. 製作 Payload:
      <script>document.location.href="https://YOUR-LAB-ID.web-security-academy.net/resources/..%2fmy-account";</script>
    2. 將其傳送給受害者後攻擊者再次前往路徑 https://YOUR-LAB-ID.web-security-academy.net/resources/..%2fmy-account 即可得到受害者的 API Key

Lab: Exploiting cache server normalization for web cache deception

  1. 偵查原始伺服器解析的路徑分隔符號
    1. 使用 Intruder 發送請求
    2. Payload 使用 /my-account§§abc
    3. 分隔符號參數可參考 Web cache deception lab delimiter list
    4. 發現 #?%23%3f 回應狀態碼 200。但 # 不可使用,因為會在請求前就被瀏覽器當作分隔符號。
  2. 偵查標準化不一致
    1. 對路徑 /aaa/..%2fmy-account 請求,回應狀態碼 404,表示原始伺服器不會解析 ..%2f
    2. 使用 Payload /aaa/..%2fresources/YOUR-RESOURCE 發現會被快取,表示快取會解析 ..%2f 且快取規則匹配開頭為 /resources 的請求
  3. 漏洞利用
    1. 使用 Payload:/my-account%23%2f%2e%2e%2fresources?wcd
      • 原始伺服器將會解析分隔符號 %23,並將路徑解析為 /my-account 回應 API Key
      • 快取伺服器會解析 ..%2f,所以將路徑解析為 /resources 並將回應儲存在快取
    2. 製作 Payload 並發送給受害者,接著攻擊者再次存取即可獲得受害者的 API Key
      <script>document.location.href="https://0a2800ef0485f50b8033ad7a00b0005f.web-security-academy.net/my-account%23%2f%2e%2e%2fresources?wcd"</script>

Lab: Exploiting exact-match cache rules for web cache deception

  1. 偵查快取伺服器檔案名稱快取規則
    1. 前往路徑 /robots.txt 發現會被快取
  2. 偵查分隔符號不一致
    1. 前往路徑 /robots.txt;aaa 發現會回應 robots.txt 的內容,但不會被快取,表示快取伺服器不會解析 ;,但原始伺服器會解析。
  3. 嘗試漏洞利用
    1. 前往 https://0ae5006803083ae3a2794be300d00087.web-security-academy.net/my-account;%2f%2e%2e%2frobots.txt
    2. 發現回應個人資料頁面,但不會被快取,表示:
      • 原始伺服器將 ; 解析為分隔符號
      • 快取伺服器不會解析 ;
      • 快取伺服器會解析路徑遍歷部分 %2f%2e%2e%2,並將此請求解析為 /robots.txt
    3. 發送 Payload 給受害者:
      <script>document.location="https://0ae5006803083ae3a2794be300d00087.web-security-academy.net/my-account;%2f%2e%2e%2frobots.txt?wcd"</script>
    4. 使用 Repeater 將原本的 /my-account 請求修改成路徑 /my-account;%2f%2e%2e%2frobots.txt?wcd 並發送請求
    5. 將回應被快取的 administrator 使用者個人資料頁面,並在當中找到 csrf 值

二、CTF 出題

在完成 PortSwigger Academy Lab 的過程中,我發現關於 Web Cache Deception 的 CTF 題目均圍繞著快取伺服器和原始伺服器的解析方式差異。因此我想嘗試寫一個能夠自定義解析規則的快取伺服器,讓出題者能夠快速的設計 CTF 題目。但由於時間關係,目前只完成初步的計畫,後續更新請見 GitHub 專案:https://github.com/1PingSun/Custom-Cache-Server-for-WCD

捌、參考資料

  1. Black Hat(2025 年 2 月 8 日)。Gotta Cache Em All: Bending the Rules of Web Cache Exploitation。YouTube。https://youtu.be/9gvxEhugnVM
  2. 1PingSun(無日期)。網頁快取詐欺(Web Cache Deception)。PortSwigger Academy 翻譯。2025 年 7 月 27 日,取自 https://web-security.1ping.org/Server-side/Web_Cache_Deception.html
  3. PortSwigger(無日期)。Web cache deception。PortSwigger Web Security Academy。2025 年 7 月 27 日,取自 https://portswigger.net/web-security/web-cache-deception