Numpy反序列化命令執行(CVE-2019-6446)淺析
*本文原創作者:nancyy,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載
0×01 前言
NumPy是一個功能強大的Python庫,主要用於對多維陣列執行計算。NumPy提供了大量的庫函式和操作,可以幫助程式設計師輕鬆地進行數值計算。這類數值計算廣泛用於以下任務:
機器學習模型 :在編寫機器學習演算法時,需要對矩陣進行各種數值計算。例如矩陣乘法、換位、加法等。NumPy提供了一個非常好的庫,用於簡單(在編寫程式碼方面)和快速(在速度方面)計算。NumPy陣列用於儲存訓練資料和機器學習模型的引數。
影象處理和計算機圖形學 :計算機中的影象表示為多維數字陣列。NumPy成為同樣情況下最自然的選擇。實際上,NumPy提供了一些優秀的庫函式來快速處理影象。例如,映象影象、按特定角度旋轉影象等。
數學任務 :NumPy對於執行各種數學任務非常有用,如數值積分、微分、內插、外推等。因此,當涉及到數學任務時,它形成了一種基於Python的MATLAB的快速替代。
0×02 影響範圍及利用條件
NumPy <=1.16.0
使用者載入惡意資料來源造成命令執行。
0×03 漏洞分析
我們以ubuntu最新版pip源下載的numpy 1.16.0版本為例進行分析。漏洞點位於npyio.py的第268行,file字串物件經過格式驗證,如果不滿足預設的numpy以及zip格式,將會嘗試使用序列化的方式進行讀取檔案。如果是老司機的話,估計大概知道是什麼問題了。
我們順著pickle.load函式繼續跟進看看。最終會發現他會逐位元組的去讀取命令。
如下圖,pickle預設支援很多命令語句。
有了這些資料,我們就開始構造命令執行了。在構造命令執行之前,我們得先匯入我們所需要的包,以及一個可以執行反射的函式。通過程式碼檢索,發現pickle的操作符號“c”和操作符“R”,分別代表著匯入和呼叫兩個操作。
那接下來我們開始構造執行“ls”的命令函數了。
通過上面的操作符號,我們編寫出對應的命令,熟悉彙編的同學就看出來了,左邊是命令符號,右邊是資料。
然後我們把這個資料轉化成pickle能夠理解的語言。
cposix system p0 (S'ls' p1 tp2 Rp3 .
然後我們把這個payload檔案,用numpy.load函式讀取一下。
就看到對應的效果了。
0×04 修復方案
2019年1月15日,官方在issue中確認了該漏洞,並準備在下一個小版本中修復
暫時緩解措施,將預設支援allow_pickle函式去掉。
參考連結
https://github.com/numpy/numpy/commit/a2bd3a7eabfe053d6d16a2130fdcad9e5211f6bb
https://bugzilla.suse.com/show_bug.cgi?id=1122208
*本文原創作者:nancyy,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載