ImageMagick記憶體洩漏漏洞分析(CVE-2018-16323)
概述
在本文中,我們主要對ImageMagick的記憶體洩漏漏洞進行分析。
ImageMagick是用於建立、編輯、轉換點陣圖影象的軟體,它可以讀取和寫入超過200種格式的影象,包括PNG、JPEG、GIF、HEIC、TIFF、DPX、EXR、WebP、Postscript、PDF和SVG。使用ImageMagick還可以對影象進行調整大小、翻轉、映象、旋轉、扭曲、剪裁和變換,可以調整影象顏色、應用各種特殊效果,可以繪製文字、線條、多邊形、橢圓和Bézier曲線。
這是一個具有豐富功能的影象處理庫,如果我們在搜尋引擎中查詢“如何在PHP中調整圖片大小”和“如何剪裁影象”,那麼很可能會搜到關於使用ImageMagick的建議。然而,這個庫長期存在安全問題,我們本次對一個新發現的漏洞進行分析,同時會回顧一些此前發現的漏洞。
CVE-2018-16323的PoC生成工具(通過ImageMagick中的XBM影象實現記憶體洩漏)請參考: ofollow,noindex">https://github.com/ttffdd/XBadManners
記憶體洩漏漏洞分析
在過去兩年中,幾乎每個月都會爆出一個ImageMagick庫的漏洞。幸運的是,其中的許多漏洞都是某種不適用的DoS漏洞,並不會造成嚴重的安全問題。但是最近,我們注意到一個有趣的漏洞,其編號是CVE-2018-16323。
這一漏洞聽起來很簡單,但我們沒有找到關於此漏洞利用的任何資訊。
我們引用CVE的提交內容:
如果畫素的十六進位制值為負,則XBM編碼器會將十六進位制影象資料保留為未初始化的模式。
接下來,我們對XBM檔案格式進行分析,常見的XBM影象如下所示:
這與C語言程式碼非常相似。這是一種非常老的格式,在X Window System中用於儲存X GUI中使用的游標和圖示點陣圖。keyboard16_bits陣列中的每個值都代表8個畫素,每個畫素是一個位元,其中編碼黑色或白色這兩種顏色中的一種。所以,並沒有值為負的畫素,因為一個畫素只有兩個可能的值。在下文中,我們將該陣列稱為XBM主體陣列(XBM Body Array)。
我們分析ImageMagick的程式碼,並嘗試找出“畫素為負”具體代表什麼含義。在這裡,需要ReadXBMImage()函式,該函式用於讀取影象,並準備用於影象處理的資料。似乎變數image中包含正在處理的影象資料(第225行)。
接下來,在第344-348行的位置是記憶體分配,並且指標資料現在指向所分配的儲存器的起始地址,指標p也指向了同一地址。
接下來的第352-360行和第365-371行,程式碼相同,但它們分別負責處理不同版本的XBM影象。從提交中可以看出,兩個分支都存在相同的漏洞,因此我們僅選取其中一個進行分析。XBM主體陣列的讀取過程發生在函式XBMInteger()中,它將int返回給變數c。此外,在第358行,儲存在變數c中的值被賦值給p指標指向的變數,然後該指標將遞增。
根據提交,我們看到先前版本中,會檢查變數c是否為負值。如果c為負值,那麼將會中斷迴圈過程,這也就是記憶體洩漏的原因。如果XBM主體陣列的第一個值為負,那麼所有分配的記憶體都將保持未初始化,並且其中可能包含來自記憶體的敏感資料,這些資料將會進一步處理,以生成新的影象。在修復後版本中,這一問題已經被修復,現在如果XBM主體陣列的值為負,那麼ImageMagick將會丟擲錯誤。
接下來,我們認真分析XBMInteger()函式。該函式將指標影象和指標hex_digits作為引數。後者是在第305行初始化的陣列。該函式允許將值儲存為XBM主體陣列中的十六進位制值。XBMInteger()讀取XBM主體陣列中定義的下一個位元組,並將其賦值給無符號INT型變數。這一函式讀取十六進位制字元,直至出現停止標記。這也就意味著,我們可以指定任意長度的十六進位制值,而不是char型別的0-255之間的預期長度範圍。我們可以設定任何無符號INT值,它將儲存在變數中,並且隨後會將該變數值轉換為有符號的INT型別。
所以,我們只要為XBM主體陣列設定一個特定值(大於2147483647,或十六進位制的0x80000000),該陣列將轉換為INT型別負數值。PoC如下:
#define test_width 500 #define test_height 500 static char test_bits[] = { 0x80000001, };
洩露的記憶體數量取決於攻擊者設定高度和寬度引數的方式。如果設定為500×500,那麼將會洩露31250(500*500/8)位元組!但實際上,這取決於應用程式如何使用ImageMagick,它可能會將影象剪裁到一定的寬度和高度。
當我們在測試這個PoC時,遇到了一個問題。正如CVE的漏洞細節中所描述的那樣,並非在7.0.8-9之內的所有ImageMagick版本都易受攻擊。我們發現了一個用於修復另一個漏洞(CVE-2017-14175,XBM影象處理過程中DoS漏洞)的提交版本,正是這個特定的提交版本才將漏洞引入到程式碼中。
接下來,讓我們嘗試執行PoC。我們首先安裝一個易受攻擊的版本(例如6.9.9-51)。接下來,執行poc.xbm到poc.png的轉換過程,我們將在xbm.c檔案中呼叫處理XBM影象,從而呼叫存在漏洞的程式碼。
生成的影象如下所示:
我們可以在生成的影象中,看到一些噪點,這些噪點就是洩露的記憶體內容,每個黑色或白色畫素實際上都是洩露記憶體中的一些資訊。如果我們重複轉換過程,可能會得到另一個影象,因為會捕獲另一個記憶體塊。
那麼,我們如何提取洩露的記憶體位元組呢?
只需要將其轉換回來,將poc.png轉換為leak.xbm。現在,就能在XBM主體陣列中找到洩露的記憶體位元組,這種格式非常易於解析,我們進行解壓縮,即可獲取到洩露的記憶體位元組。
所以,總結一下我們的攻擊思路:
1、生成PoC;
2、在存在漏洞的應用上,將PoC上傳到頭像;
3、儲存生成的PNG/JPG/GIF影象;
4、從影象中提取資料。
Ttffdd為這個名為XBadManners的漏洞編寫了一個簡單易用的工具,該工具會生成PoC,並且從影象中恢復洩露的資料。
注意,ImageMagick是一個比較智慧的庫,我們可以將包含XBM影象資料的poc.png上傳到伺服器,如果沒有正確檢查影象型別,那麼ImageMagick會將poc.png作為XBM影象處理。因此,如果只將上傳檔案的字尾名改為“*.png”,那麼可能將無法實現漏洞利用。
ImageMagick安全性分析
CVE-2018-16323並不是ImageMagick軟體中發現的第一個嚴重漏洞。該軟體此前曾經發現過大量漏洞,目前已經有近500個已經修復的漏洞。每個月可能都會發現一些難以利用或不適用的新漏洞,每年都會發現一些具有較大影響的嚴重漏洞。
ImageMagick最嚴重的漏洞包括遠端程式碼執行漏洞、SSRF漏洞、svg和mvg檔案本地檔案讀取/移動/刪除漏洞。這些漏洞在2016年4月由stewie和Nikolay Ermishkin發現。
· CVE-2016-3714 遠端程式碼執行漏洞
· CVE-2016-3718 SSRF漏洞
· CVE-2016-3715 檔案刪除漏洞
· CVE-2016-3716 檔案移動漏洞
·CVE-2016-3717 本地檔案讀取漏洞
在ImageMagick的6.9.3-9(2016年4月30日釋出)版本中,已經實現補丁的修復。這一漏洞廣泛受到漏洞賞金獵人的歡迎。
· Yahoo ImageTragick: https://www.zdnet.com/article/yahoos-polyvore-vulnerable-to-imagemagick-flaw-researcher-receives-little-reward/
· HackerOne ImageTragick: https://hackerone.com/reports/135072
· Facebook ImageTragick 2017: https://4lemon.ru/2017-01-17_facebook_imagetragick_remote_code_execution.html
CVE-2017-15277是由Emil Lerner在2017年7月發現,該漏洞是GIF影象處理過程中存在記憶體洩漏漏洞。如果不存在全域性調色盤或區域性調色盤,那麼ImageMagick會將調色盤保持在未初始化的狀態,從而導致記憶體洩漏在調色盤的位置發生。這一漏洞同樣受到賞金獵人的歡迎。
· HackerOne: https://hackerone.com/reports/302885
· Twitter: https://hackerone.com/reports/315906
· MailRu: https://hackerone.com/reports/251732
GhostScript型別混淆遠端程式碼執行漏洞(CVE-2017-8291)是在2017年5月發現的,它並不是ImageMagick的漏洞,但該漏洞會影響ImageMagick,因為ImageMagick使用GhostScript來處理PostScript的某些型別的影象,例如EPS、PDF檔案。
· Metasploit模組: https://www.rapid7.com/db/modules/exploit/unix/fileformat/ghostscript_type_confusion
CVE-2018-16509是GhostScript中的另一個遠端程式碼執行漏洞,在2018年8月被發現,同樣影響ImageMagick。
· Google Project Zero對該漏洞的分析: https://bugs.chromium.org/p/project-zero/issues/detail?id=1640
· 漏洞細節: https://medium.com/@NumbShiva/imagemagic-rce-f364a9f50a14
· ExploitDB: https://www.exploit-db.com/exploits/45369/
到底有多少嚴重的安全漏洞我們仍然未知?我們並不清楚。但是,根據已經發現的漏洞,我們繪製了一個ImageMagick的安全漏洞時間軸。
如何以安全的方式使用ImageMagick
當然,最安全的方式是停止使用ImageMagick。但作為負責任的安全人員,我們不會向用戶提出這樣的建議,而是建議使用者以安全的方式來執行該程式,從而降低安全風險。
大家已經注意到,ImageMagick有很多漏洞接連出現,因此它也會經常進行更新。如果使用ImageMagick,請留意新版本更新,並確保始終使用最新版本,需要注意的是,ImageMagick並不會在官方儲存庫中頻繁更新,因此其中可能包含舊的存在漏洞版本,因此最好能從原始碼安裝穩定的ImageMagick版本。
但是,如之前看到的,修復舊的漏洞可能會產生新的漏洞。因此,僅更新到最新版本可能無法確保安全。
在這種情況下,我們建議使用者在Docker這類隔離環境中執行ImageMagick,並設定使用ImageMagick服務所需的最小許可權,將其放置於具有最小網路許可權的隔離網段中,並且僅使用這一隔離環境來執行使用ImageMagick處理自定義使用者影象的特定任務。
此外,ImageMagick也配置了一些安全策略: https://imagemagick.org/source/policy.xml
在這裡,可以找到關於ImageMagick安全性的詳細開發人員指南: https://imagemagick.org/script/security-policy.php