官术网_书友最值得收藏!

3.2.2 CVE-2018-15664:符號鏈接替換漏洞

在18.06.1-ce-rc2版本之前的Docker中,docker cp命令對應的后端API存在基于競爭條件的符號鏈接替換漏洞,能夠導致目錄穿越。攻擊者可利用此漏洞以root權限實現宿主機文件系統的任意讀寫,CVSS 3.x評分為7.5分。

CVE-2018-15664實際上是一個TOCTOU(time-of-check to time-of-use)問題,屬于競態條件漏洞。簡單來說,這個問題指的是在程序對某對象進行安全檢查和使用該對象的步驟之間存在間隙,攻擊者可以先構造并放置一個能夠通過安全檢查的合法對象,順利通過目標程序的安全檢查流程,然后立即使用惡意對象替換之前的合法對象。這樣一來,目標程序真正使用的實際上是被替換后的惡意對象。

下面用流程圖來表示這一過程,假設某程序需要使用“/xxx”文件,為了避免安全風險,需要先對該文件進行合法性檢查,如果檢查不通過,程序將報錯或執行其他操作,只有在檢查通過后才會繼續使用該文件。在圖3-2中,左側流程展示了正常的處理情況,右側流程展示了攻擊者利用TOCTOU問題將“/xxx”文件替換為惡意文件的情況。

圖3-2 正常流程(左)與TOCTOU惡意利用流程(右)

以上就是TOCTOU問題的原理。對于CVE-2018-15664來說,當用戶執行docker cp命令后,Docker守護進程收到這個請求,就會對用戶給出的復制路徑進行檢查。如果路徑中有容器內部的符號鏈接,則先在容器內部將其解析成路徑字符串,留待后用。

一眼看上去,該流程似乎正常,但要考慮到容器內部環境是不可控的。如果在Docker守護進程檢查復制路徑時,攻擊者先在這里放置一個非符號鏈接的常規文件或目錄,檢查結束后,攻擊者趕在Docker守護進程使用這個路徑前將其替換為一個符號鏈接,那么這個符號鏈接就會于被打開時在宿主機上解析,從而導致目錄穿越。

理解了漏洞原理之后,我們使用漏洞發現者Aleksa Sarai提供的PoC[1]來實踐一下[2]

大家可以使用我們開源的metarget靶機項目[3],在Ubuntu服務器上一鍵部署漏洞環境,在參照項目主頁安裝metarget后,直接執行以下命令:


./metarget cnv install cve-2018-15664

即可安裝好存在CVE-2018-15664漏洞的Docker。

下載并解壓PoC后,PoC目錄結構如下:


.
├── build
│   ├── Dockerfile
│   └── symlink_swap.c
├── run_read.sh
└── run_write.sh

其中,build目錄包含了用來制作惡意鏡像的Dockerfile和容器內漏洞利用源代碼symlink_swap.c。

Dockerfile的主要內容是構建漏洞利用程序symlink_swap并將其放在容器根目錄下,并在根目錄下創建一個w00t_w00t_im_a_flag文件,內容為“FAILED -- INSIDE CONTAINER PATH”。容器啟動后執行的程序(Entrypoint)即為/symlink_swap。

symlink_swap.c的任務是在容器內創建指向根目錄“/”的符號鏈接,并不斷地交換符號鏈接(由命令行參數傳入,如“/totally_safe_path”)與一個正常目錄(例如“/totally_safe_path-stashed”)的名字。這樣一來,在宿主機上執行docker cp時,如果首先檢查到“/totally_safe_path”是一個正常目錄,但在后面執行復制操作時“/totally_safe_path”卻變成了一個符號鏈接,那么Docker將在宿主機上解析這個符號鏈接。

CVE-2018-15664屬于競態條件漏洞,不是每次都能復現。為了增大漏洞被觸發的幾率,我們需要在宿主機上不斷執行docker cp命令(高頻使用docker cp命令在現實中十分不常見,這里主要是為了驗證可行性,證明“至少現實中這種漏洞是有機會被利用的”)。run_read.sh和run_write.sh腳本正是用于模擬受害者在宿主機上不斷執行docker cp命令。那么,為什么會有兩個腳本呢?事實上,這兩個腳本模擬的是不同的場景:

·run_read.sh模擬受害者不斷使用docker cp將容器內文件復制到宿主機上的場景,一旦漏洞觸發,容器內惡意符號鏈接在宿主機文件系統解析后指向的文件將被復制到受害者設定的宿主機目錄下。

·run_write.sh模擬受害者不斷使用docker cp將宿主機上文件復制到容器內的場景,一旦漏洞觸發,受害者指定的宿主機文件將覆蓋容器內惡意符號鏈接在宿主機文件系統解析后指向的文件。

我們以run_write.sh為例進行講解,內容如下:


SYMSWAP_PATH=/totally_safe_path
SYMSWAP_TARGET=/w00t_w00t_im_a_flag
# 創建flag
echo "FAILED -- HOST FILE UNCHANGED" | sudo tee "$SYMSWAP_TARGET"
sudo chmod 0444 "$SYMSWAP_TARGET"
# 構建鏡像并運行容器
docker build -t cyphar/symlink_swap \
    --build-arg "SYMSWAP_PATH=$SYMSWAP_PATH" \
    --build-arg "SYMSWAP_TARGET=$SYMSWAP_TARGET" build/ &> /dev/null
ctr_id=$(docker run --rm -d cyphar/symlink_swap "$SYMSWAP_PATH")
echo "SUCCESS -- HOST FILE CHANGED" | tee /src_file
# 不斷執行docker cp命令
while true
do
    docker cp /src_file "${ctr_id}:$SYMSWAP_PATH/$SYMSWAP_TARGET"
done

run_write.sh啟動后,惡意容器運行,然后不斷執行docker cp命令,漏洞未觸發時,宿主機上的/w00t_w00t_im_a_flag文件內容為:


FAILED -- HOST FILE UNCHANGED

如果漏洞成功觸發,容器內的符號鏈接“/totally_safe_path”將在宿主機文件系統上解析,因此docker cp實際上是將/src_file文件復制到了宿主機上的/w00t_w00t_im_a_flag文件位置。也就是說,此時宿主機上/w00t_w00t_im_a_flag文件內容將被改寫為:


SUCCESS -- HOST FILE CHANGED

為了更直觀地展示漏洞利用效果,我們手動執行run_write.sh內的命令,docker cp執行一段時間后按Ctrl+C取消,這個過程如圖3-3所示。

圖3-3 CVE-2018-15664漏洞利用截圖

可以看到,漏洞觸發后,/w00t_w00t_im_a_flag文件內容被成功改寫了。Aleksa Sarai提到,宿主機上的攻擊者可以借助這個漏洞來實現提權(如改寫/etc/shadow文件),也可以實現對宿主機上任意文件的讀取。這個說法沒有問題,但如果宿主機上的攻擊者并非root用戶,卻能夠與Docker交互(執行docker cp命令),更簡單的提權方式也許是直接利用Docker運行一個特權容器。

[1] https://seclists.org/oss-sec/2019/q2/131。

[2] 隨書代碼倉庫路徑:https://github.com/brant-ruan/cloud-native-security-book/tree/main/code/0302- 開發側攻擊/02-CVE-2018-15664/symlink_race。

[3] https://github.com/brant-ruan/metarget.git。

主站蜘蛛池模板: 济宁市| 昭通市| 平阳县| 福鼎市| 霸州市| 濮阳县| 瓮安县| 永嘉县| 西华县| 迭部县| 安泽县| 宿州市| 吉首市| 泸水县| 合阳县| 兴化市| 旌德县| 鄱阳县| 江永县| 镇远县| 广河县| 嘉荫县| 延寿县| 岱山县| 东山县| 长兴县| 慈溪市| 广宗县| 司法| 略阳县| 金阳县| 桂东县| 横峰县| 明星| 吉隆县| 高密市| 霞浦县| 历史| 都江堰市| 南昌市| 石景山区|