iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
Security

Agentic Era,一年來 LLM 到底都挖了些什麼洞!系列 第 2

Day2. Imagemagick 的各種往事:轉個圖片怎麼就被駭了!

  • 分享至 

  • xImage
  •  

在正式進入明天的主題前,先來聊聊 Imagemagick 的漏洞歷史吧!

ImageMagick 101

ImageMagick [[1]] 是一套開源的圖片處理工具,除了最常見的格式轉換外,也能做縮放、裁切、合成、旋轉、調色、產生縮圖等操作,並提供 Command Line 與多種語言的 API。

最簡單的使用方式大概長這樣:

magick input.jpg -resize 800x600 output.png

ImageMagick 並不是只把 JPEG 的 Pixel 搬到 PNG 裡而已,它背後還有幾個很重要的角色:

  • Coder:負責讀寫 PNG、JPEG、SVG、MVG 等格式的 Encoder/Decoder。
  • Pseudo-format / Protocol:像是 label:caption:https:,輸入看起來像檔名,實際上卻是在要求 ImageMagick 執行某種動作。
  • Delegate:當 ImageMagick 不自己處理某種格式或協議時,呼叫 curl、Ghostscript 等外部程式來幫忙。

換句話說,ImageMagick 看到的可能是格式、Metadata、URL、外部檔案與其他程式的組合包。這個 Parser Boundary 一旦沒有切乾淨,圖片就不再只是圖片了。
然而,由於 ImageMagick 支援的超兩百種檔案類別加上其免費、開源的生態,導致其被廣泛運用到許多 Web Servers/Applications (甚至包含 Wordpress、Drupal 等大型 CMS),一旦它出了什麼漏洞可都是大新聞呢!

2016:ImageTragick(CVE-2016-3714)

2016 年爆出的 ImageTragick [[2]] 其實是一組漏洞,其中最知名的 CVE-2016-3714 可以讓攻擊者在伺服器處理惡意圖片時做到 Command Injection,最後一路走到 RCE。

在 recall 一次 ImageMagick 中所謂的 delegate 可以註冊外部的 lib 來處理不同類型的協議,其中一條 delegate 長這樣:

<delegate decode="https"
          command="&quot;curl&quot; -s -k -o &quot;%o&quot; &quot;https:%M&quot;"/>

%o 是輸出檔名,而 %M 會被替換成輸入中的 URL。ImageMagick 接著把展開後的整段 Command String 交給 Shell 執行;偏偏當時對 %M 的過濾又不完整,攻擊者只要在圖片中引入的 URL 中跳脫原本的引號達成命令字串拼接就可以 Command Injection。

而 SVG、MVG 這類格式剛好又能在內容中引用外部圖片,例如概念上可以寫成:

push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg";|id ")'
pop graphic-context

整條 Data Flow 就變成:

使用者上傳 SVG/MVG
  -> 圖片內容引用一個 URL
  -> URL 被代入 Delegate 的 %M
  -> Delegate Command 經由 Shell 執行
  -> Command Injection

當年的修補除了更新版本外,也建議透過 policy.xml 關閉不需要的 MVGMSLHTTPS 等 Coder/Delegate。現在 ImageMagick 官方的 Security Policy [[3]] 也仍然建議:如果服務會處理公開來源的檔案,就應限制格式、關閉外部 Delegate、禁止 Indirect Read,並把處理程序放進 Sandbox。

CVE-2022-44268 LFI

其實筆者自己對這漏洞印象算蠻深刻的,這可是我當年第一年在金盾獎(2023 年)解開的題目呢(挺)
註:當年甚至把 flag 放在 /etc/flag,得知的方法是在前端原始碼找到 Base64 Encoded HTML 註解、、、

時間快轉六年,ImageMagick 又出現了 CVE-2022-44268 [[4]]。這次不是 Command Injection,而是 Arbitrary File Read/Information Disclosure:攻擊者可以讓 ImageMagick 在轉換 PNG 時讀取本機檔案,再把內容塞進輸出的圖片中。

PNG 除了 Pixel Data 外,還能帶上 tEXt Chunk。每個 tEXt Chunk 都是一組 Keyword 與文字內容;正常情況下拿來放作者、描述之類的資訊完全沒問題,但如果 Keyword 叫做 profile,事情就開始有趣了。

攻擊者可以準備一張概念上包含以下 Metadata 的 PNG:

Keyword: profile
Value:   /etc/passwd

舊版 PNG Decoder 讀到它後,會把這組資料交給 SetImageProperty(image, "profile", "/etc/passwd", ...)。偏偏 profile 在 ImageMagick 裡不是普通的自由欄位,而是一個有特殊語意的 Property;底層會把 Value 當成檔案路徑,呼叫 FileToStringInfo() 讀取檔案,再透過 SetImageProfile() 把內容內嵌回去圖片。

於是整條 work Flow 變成:

PNG tEXt Chunk(profile=/etc/passwd)
  -> SetImageProperty("profile", "/etc/passwd")
  -> FileToStringInfo("/etc/passwd")
  -> 檔案內容成為 Image Profile
  -> 寫入轉換後的 PNG
  -> 攻擊者下載輸出圖片並還原內容

只要 ImageMagick 的執行身分讀得到目標檔案,而且 Web 服務會把轉換後的圖片回傳,原本沒有任何下載功能的圖片 API 就這樣多出了一個 File Read Oracle。

這個漏洞的 Upstream Patch [[5]] 很短,有點可愛(?):PNG Parser 遇到 profile 時,不再原封不動地把它當成共用 Property,而是改名成 png:profile,一如既往地用禁止來 patch 漏洞(

 if ((LocaleCompare(key,"version") == 0) ||
+    (LocaleCompare(key,"profile") == 0) ||
     (LocaleCompare(key,"width") == 0))
   (void) FormatLocaleString(key,MagickPathExtent,"png:%s",
     text[i].key);

一些 Murmur

在根據考察後,其實 Imagemagick 的漏洞發展史不只這樣,像是在 2016 年以前會發現大多數的研究都是 Memory Corruption (Pwn) 相關:

  • CVE-2007-4985: DIB 解碼器 Heap Overflow
  • CVE-2009-1882: XPixMap Interger Overflow
  • CVE-2014-1947: PSD 解析器 Buffer Overflow
    ... (當然,現在也有,甚至有許多 llm/fuzzer 還整天找出新的 memory bugs)

而因為跟接下來的主題比較無關所以沒寫,但其實 Imagemagick 還發生過在處理 PS/EPS/PDF 等檔案類型時因為使用了 GhostScript 預設的 -dSAFER Sandbox 發生過一系列災難,也值得被好好看一下。Project Zero Issues[6]

所以明天要介紹的 LLM Finding 到底是誰呢~

References


上一篇
Day 1. 緣起
系列文
Agentic Era,一年來 LLM 到底都挖了些什麼洞!2
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言