Alpine Linux:從漏洞發現到代碼執行
Alpine Linux是一個面向安全應用的輕量級Linux發行版。它採用了musl libc和busybox以減小系統的體積和運行時資源消耗,同時還提供了自己的包管理工具apk。Alpine Linux的內核都打了grsecurity/PaX補丁,並且所有的程序都編譯為Position Independent Executables (PIE) 以增強系統的安全性。
在過去幾年中Alpine Linux越來越受歡迎,這主要是因為它在容器內使用,特別是在Docker中。大多數官方Docker存儲庫都具有Alpine 版本,而Alpine存儲庫本身也有超過一千萬次的使用頻率。
Alpine Linux是一個面向安全的輕型的Linux發行版,關鍵的是,相比於其他Linux的Docker鏡像,它的容量非常小,僅僅只有5MB。為了實現這些目的,其開發人員付出了大量的努力,例如,通過包括內核方面的防禦機制,並通過編譯所有現代二進位保護的用戶空間包。正是由於Alpine Linux的這些優勢,我們在Twistlock中使用Alpine,Twistlock 的創建目的就是掃描容器,對照CVE資料庫檢查容器中的軟體。此外,它還會檢查容器環境,比如,如果容器不應該在第一時間連接網路,那麼它就會斷開網路連接。
作為安全研究員,我決定探索一下Alpine的內部組成,並尋找可能危及所有Alpine用戶的重大漏洞。
定位apk並查找錯誤
由於Alpine提供了自己的包管理工具apk,所以我決定重點探索一下它。如果我以某種方式在安裝之前修改其程序包,或讓程序包管理器降級為程序包,我就可以在目標系統上執行代碼了。
經過一些初步研究,我最終決定嘗試模糊特定部分的apk。於是我修補了apk,並進行了一些修改,並為afl編譯(確切地說,我寫了我自己的applet,使用一個文件作為輸入)。過去我經常通過使用afl來解決零日漏洞,所以我決定使用該方法,通過模糊假設的潛在易受攻擊的特定功能來找到apk中的漏洞。
由於我寫的小程序專門針對於tar解析代碼,所以利用 apk接受gzip壓縮tarballs(tar.gz)的更新文件,我分離出了一個tar流(tar-stream),並給了它一個文件的代碼。應該說,這是一個完美的模糊點,有很多代碼來處理解析用戶輸入,任何程序的崩潰都應該發生在簽名過程之前。為了方便比較,解析特定包中的崩潰將不太重要,因為apk會檢查文件簽名。
不到一天的時間,我的apk小程序中就發現大量的崩潰。我開始調試崩潰並很快找出了漏洞,我在tar解析函數中發現了兩個可能導致堆溢出的代碼。
兩個漏洞的描述
溢出可能發生在以下行中,這些行來自archive.c:
首先,讓我們了解上下文。代碼片段來自archive.c中的函數apk_parse_tar。此函數接收一個apk_istream的tar流,經過解析它,並在每個已解析的代碼塊( block)上運行一個回調函數。
一般來說,tar流由512位元組的代碼塊組成,從文件數據塊之後的tar頭代碼塊開始。其中一個標題欄位是一個typeflag,表示以下文件的類型。它還用於指示使用特殊代碼塊,例如longname或「GNU long name extension」標誌,這意味著下一個位元組包含隨後文件的名稱且當文件名長度大於100位元組時使用。
所以當解析器遇到一個longname代碼塊時,它應該分配給定大小的緩衝區,並將該名稱從流中複製過來。這個緩衝區是longname,如果需要,blob_realloc也可用於擴展緩衝區大小的函數。
我們來看看blob_realloc:
關於這個函數的令人煩惱的事情是它接受一個int類型的大小,這個大小是自然簽名的。 b-> len是long類型,這意味著它也被簽名。
嘗試模擬任何大小大於0x80000000的情況是菲常有用的,0x80000000是2147483648作為無符號int和-2147483648作為簽名的int。換句話說,當大小大於最大有符號int大小時,它將被視為負數,所以blob_realloc返回0時,可以不用修改緩衝區。
在以下調用is-> read中,大量的位元組將被複制到緩衝區,溢出其分配的大小並覆蓋堆上的任何後續數據。只要讀取函數將大小視為無符號,並且在tar.gz的情況下,該函數是來自gunzip.c 的gzi_read,其目標為size_t(無符號)。
還值得一提的是,將blob_realloc定義更改為接受size_t而不是int是不足以解決此問題的,因為當向最大entry.size添加1時可能會發生整數溢出,這將發生緩衝區溢出。
可以利用這種緩衝區溢出來實現代碼執行,攻擊者可以通過將堆上的函數偏移量覆蓋到具有參數的任何函數上來預測執行時的內存布局。雖然我還沒有發布我的PoC,但是我已打算在不久的將來寫下這個開發過程,一旦這個漏洞被修正了,就不可能在野外被利用,MITR已經把此漏洞定義為了CVE-2017-9669。而CVE-2017-9671則可以在處理tar pax標頭的代碼中找到對blob_realloc的另一個調用,其中緩衝區溢出可能以相同的方式發生。
攻擊範圍
這些漏洞是可以利用這些特定緩衝區溢出的方式,顯而易見的是嘗試在系統上實現代碼執行。攻擊的唯一先決條件是找出程序的內存布局,所以像ASLR這樣的保護措施可能會阻止攻擊者成功的進行攻擊,但攻擊者可能會繞過它,仍然可以執行。
實際的攻擊情形將是攻擊者通過製作惡意的APKINDEX.tar.gz文件(Alpine的更新文件)並將其託管在他的HTTP伺服器上。不管該設備是否包含容器,網路上的任何用戶都可以在任何設備中運行apk更新或基於Alpine(調用後面的命令)構建容器映像,這就造成了攻擊者的惡意代碼將在受害者的設備上執行。攻擊者可以執行隱藏攻擊的代碼,這樣受害者可能永遠都不知道他的設備是否被盜用。
2.5.0_rc1之後的所有版本的apk都容易受到這個兩個CVE的攻擊。而且我已經查看了舊的代碼,似乎舊版本也可能會遇到類似的問題。
應對方案
我已告知Alpine的開發商這兩個漏洞,並與他們一起合作發布了一個快速修復的補丁。
除此之外,開發商還提到要為apk增加了一些額外的強化功能,這可能會進一步限制攻擊者利用這種和類似的漏洞,如控制流完整性。
本文翻譯自:Alpine Linux: From vulnerability discovery to code execution (Pt 1 of 2) | Twistlock ,如若轉載,請註明來源於嘶吼: Alpine Linux:從漏洞發現到代碼執行 更多內容請關注「嘶吼專業版」——Pro4hou
推薦閱讀:
※淺談動態爬蟲與去重(續)
※Atom也爆遠程代碼執行漏洞?就問你怕不怕!
※聖誕節專題 | 躲得過初一、躲得過十五,卻躲不過Cyber Monday!
TAG:信息安全 |