LWN:從Log4j事件得到的教訓(xùn)!
關(guān)注了就能看到更多這么棒的文章哦~
Lessons from Log4j
By Jonathan Corbet
December 16, 2021
DeepL assisted translation
https://lwn.net/Articles/878570/
最近,多數(shù)讀者可能已經(jīng)了解到了一些關(guān)于 Log4j 漏洞的信息,這個漏洞自從 12 月 9 日披露出來之后,不斷給系統(tǒng)管理員增加煩惱。這個漏洞比較容易利用,可以用來進行遠程代碼執(zhí)行,而且整個互聯(lián)網(wǎng)上的服務(wù)器中到處都有這個問題。把它稱為近年來被披露的最糟糕的漏洞之一,并不算夸張。從某種意義上來說,從 Log4j 中得到的教訓(xùn)并沒有什么新的內(nèi)容,但這個漏洞確實進一步明確地突出了自由軟件生態(tài)系統(tǒng)中的一些問題。
What went wrong
有很多文章詳細描述了這個 bug 的機制,以及如何利用。在這個頁面(https://www.techsolvency.com/story-so-far/cve-2021-44228-log4j-log4shell/) 上就收集了很多。簡而言之:Log4j? 是一個 Java logging package,由 Apache 軟件基金會注冊了商標并進行發(fā)布。它已經(jīng)被包含進了許多其他項目,在互聯(lián)網(wǎng)上到處都可以找到 Log4j。事實上,根據(jù)這篇文章(https://blog.sonatype.com/why-did-log4shell-set-the-internet-on-fire),Log4j 已經(jīng)被下載了超過 2800 萬次(僅僅統(tǒng)計了過去四個月里的情況)并且是將近 7000 個其他項目的依賴項。因此,Log4j 中的漏洞很可能就會成為碰巧使用了的那些其他系統(tǒng)中的漏洞。
正如 Apache 軟件基金會在 6 月份自豪地發(fā)出的一條推文所說,它甚至也存在于火星上的 Ingenuity 直升機之中。
通常情況下,人們認為一個日志工具(logging utility)應(yīng)該只是把感興趣的數(shù)據(jù)接收下來并可靠地記錄下來。Log4j 似乎做到了這一點,但它也做了一些可以說是任何日志系統(tǒng)都不應(yīng)該做的事情:它主動地對要記錄的數(shù)據(jù)進行解釋、并相應(yīng)地采取行動。它可以做的事情之一就是是查詢遠程服務(wù)器的數(shù)據(jù),并將其納入日志信息中。例如,它可以從 LDAP 服務(wù)器獲取并加入日志信息中,這樣在人們希望在日志中加入某個用戶的詳細賬戶信息的數(shù)據(jù)時,這個功能就會很有用。
然而,事實上遠程目錄服務(wù)器(remote directory server)可以提供更多形式的數(shù)據(jù),比如說可以提供一個序列化處理(serialized)的 Java 對象,被后續(xù)重新組裝起來進行執(zhí)行。這就把這個功能變成了一個向正在運行的應(yīng)用程序注入代碼的一種方式,而本來這個日志工具只是希望記錄一些數(shù)據(jù)而已。為了利用這個漏洞,攻擊者需要做兩件事:
架設(shè)一個精心構(gòu)建好的運行相關(guān)協(xié)議的服務(wù)器,確保攻擊目標系統(tǒng)能訪問到這個服務(wù)器。LDAP 似乎是目前的攻擊首選協(xié)議,但其他協(xié)議也同樣可能受到攻擊。對 LWN 服務(wù)器的 log 進行 grep,就看到也有嘗試利用 DNS 協(xié)議的。
說服要攻擊的目標系統(tǒng)來記錄一個由攻擊者提供的包含特殊“咒語”的字符串,這樣就能從惡意服務(wù)器中加載和執(zhí)行對象了。
上面的第二步看起來困難,其實很容易。許多系統(tǒng)都會樂意記錄用戶所提供的數(shù)據(jù)。這些惡意字符串可能就是偽裝成最終會出現(xiàn)在日志中的用戶名,而另一個流行的選擇是偽裝成瀏覽器的 user-agent 字符串。一旦目標上鉤,記錄了惡意字符串,游戲就結(jié)束了。
換句話說,這是一個對來自互聯(lián)網(wǎng)所提供的未經(jīng)清理的數(shù)據(jù)直接使用的典型案例,后果可想而知。在任何一個正常 review 過程中都應(yīng)該發(fā)現(xiàn)這個問題。請注意,惡意字符串也可以是由前端軟件傳遞給內(nèi)部系統(tǒng)的,然后內(nèi)部系統(tǒng)可能決定要不要記錄。換句話說,僅僅是不直接暴露在互聯(lián)網(wǎng)上,并不一定就能對這個脆弱的系統(tǒng)實現(xiàn)充分的防御。每一個使用 Log4j 的系統(tǒng)都需要進行 fix,要么升級,要么就采用上面鏈接中提供的文章中所說的某種其他緩解措施。請注意,最初的 fix 措施已被證明不足以解決 Log4j 的所有問題,用戶需要不斷保持這個工具的最新更新。
對這個漏洞的響應(yīng)是迅速而且強烈。一些評論家斷言 "open source is broken"。之前如果沒有看過 xkcd #2347 (https://xkcd.com/2347/?)的話,現(xiàn)在碰到的其實就是這種情況。我們的社區(qū)是否像某些人所說的那樣出現(xiàn)了嚴重的問題?簡而言之,這一幕之中似乎展示了開源項目的兩個廣為人知的缺點,分別跟依賴性和維護者有關(guān)。
Dependencies galore (太多依賴)
在自由軟件的早期,根本就沒有什么自由代碼(free code),所以幾乎所有內(nèi)容都要從零開始寫。因此,在那個時候,幾乎沒有什么(脆弱的)軟件包可供人們免費下載和使用,所以每個項目的安全漏洞都是自己寫出來的。社區(qū)就面臨這一挑戰(zhàn),即使在過去那些人們都比較單純的日子里,也經(jīng)??吹桨踩珕栴}(security problems)。
LWN 編者在這一領(lǐng)域浸淫的時間有多長(比他愿意承認的時間還要長),那么開發(fā)者和學(xué)術(shù)界談?wù)摽芍赜密浖暮锰幘陀卸嗑谩6嗄陙?,人們的這個夢想確實已經(jīng)實現(xiàn)了。許多語言的社區(qū)已經(jīng)為各種常見的(和不常見的)工作積累了大量的模塊(module)。編寫程序往往只是需要找到正確的模塊并將它們正確地組合在一起。用來從模塊庫自動下載的這些接口,使得獲取所需模塊(以及它們進一步所依賴的模塊)的過程都自動化了。對于我們這些很久以前就習(xí)慣了不斷重復(fù)運行 configure 然后手動安裝下一個尚未就緒的依賴模塊的人來說,現(xiàn)代化的開發(fā)環(huán)境簡直就是對我們過去做法的碾壓。當初我們的困難,現(xiàn)在已經(jīng)消失了。
這對我們的社區(qū)來說是一個巨大的成就。我們已經(jīng)創(chuàng)造了可以在其中快樂工作的開發(fā)環(huán)境,它允許我們以幾十年前完全無法想象到的生產(chǎn)力水平來繼續(xù)工作。但是,這里潛伏著一個問題:這種結(jié)構(gòu)使得項目很容易積累對外部模塊的依賴,而每個模塊都可能帶來一些自身的風(fēng)險。事實上你是在將互聯(lián)網(wǎng)上的一段隨機代碼直接 import 到你自己的程序之中,這可能會出現(xiàn)很多種后果。也許其中的某個模塊可能干脆就是一個公開用來進行惡意攻擊的模塊(就像 event-stream 事件),也許這個模塊就是直接消失了(left-pad 案例),或者它僅僅是不再受到重視和維護了,就像 Log4j 這次的情況。
當一個人所使用的東西非常重視質(zhì)量時,人們往往會去使用已知的品牌。Log4j 是在 Apache 軟件基金會的品牌下開發(fā)的,因此人們認為這能代表著它有著很好的質(zhì)量,并且也在積極維護之中。不過,外表經(jīng)常是可以欺騙人的。我們都不用提 Apache OpenOffice,它一直在持續(xù)被人們下載和使用,盡管多年來幾乎完全沒有針對它所進行的開發(fā)工作了。不過,OpenOffice 的用戶很欣慰地獲悉(根據(jù)該項目 2021 年 10 月的報告)OpenOffice 終于提出了新的使命的宣言草案。Log4j 比它還是要更活躍一些,但它仍然是依賴于無償工作的維護者的個人空閑時間的工作。無論是否有 Apache 品牌,這個被廣泛依賴的項目都沒有人付費來支持維護工作。
但是,哪怕今后品牌真的能代表著更高的可靠性,可是很難在擁有數(shù)百個依賴庫之后仍然保持穩(wěn)定。一個依賴庫,在被采用時可能看起來很穩(wěn)固、維護得很好,但是在一兩年后看起來就不那么吸引人了。但是這些缺乏良好維護的項目往往不會引起人們的注意,直到出了嚴重的問題才為人所知。這種項目的用戶可能不會意識到風(fēng)險在增加,直到最終發(fā)生問題時才知道,已經(jīng)為時已晚了。我們的工具使得添加依賴關(guān)系變得很容易(甚至我們可能都沒有意識到有這些依賴);但在評估現(xiàn)有的 dependency 模塊的當前維護狀態(tài)是否良好這個方面,工具卻沒有提供多大的幫助。
Maintainers
還有一個相關(guān)的問題,就是對這些人們所嚴重依賴的項目的開發(fā)和維護工作缺乏支持。過去常說的自由軟件和自由小狗(free software and a free puppy)之間的比較仍然是正確的:小狗當然很好,但如果有人不注意的話,它們肯定會在地毯上撒尿、咬壞你的鞋子。很容易就能利用自由軟件的不收費的特性,來加入大量功能強大的代碼,但每一個依賴項其實都是一只小狗,需要有人看管。
作為一個社區(qū)來說,我們獲取小狗的能力遠比訓(xùn)練它們的能力要強。各個商業(yè)公司總會很高興地把我們所提供的軟件收下來,但是卻不覺得有必要對他們系統(tǒng)中最關(guān)鍵的組件給出一些貢獻和支持。事實上,我們都是這樣做的,沒有人可以對他們所依賴的每一個項目都給出支持。我們從自由軟件中得到的東西遠遠多于我們可能投入的東西,這當然是一件好事。
盡管如此,我們的生態(tài)系統(tǒng)中的企業(yè)一方事實上也不應(yīng)該這么快就把自由軟件的這些好處視為理所當然的。如果一個公司在自由軟件的基礎(chǔ)上建立了一個重要的產(chǎn)品或服務(wù),那么該公司就應(yīng)該確保該軟件得到了良好的支持,在有必要的時候就應(yīng)該站出來使之成為現(xiàn)實。一般來說,這樣做總是正確的做法,但這遠遠不是一種利他主義(altruistic act)的行為。否則的話,就會不斷地出現(xiàn)類似 Log4j 這樣的危機。正如目前許多公司都意識到的,這種危機都會付出昂貴的代價。
"站出來" 就意味著既要支持維護者,也要支持開發(fā)者。最嚴重的問題往往出在維護者這一邊。即使是像 Linux 內(nèi)核這樣的項目,也有成千上萬的開發(fā)人員正在為他們所做的工作而獲得報酬,但卻很難找到對維護者的支持。公司最好的觀點也是認為維護者的工作就是一些 overhead (開銷),最壞的觀點是認為支持維護者就是在幫助競爭對手,而通常的觀點來說都認為這是別人的責(zé)任。很少有公司會對他們的員工擔(dān)任維護者這個工作給出獎勵,所以他們中的許多人最終都在用自己的時間來做這些工作。而工作的成果也許會有數(shù)百萬次下載,而這個維護工作其實是在某人的空閑時間內(nèi)完成的(如果它真的完成了的話)。
這些問題并不是自由軟件所特有的。也不是沒有過發(fā)現(xiàn)某個專有軟件并不像所宣稱的那樣得到很好的支持。自由軟件,至少,即使是在其創(chuàng)造者并不配合的情況下,也可以得到 fix。但是,我們社區(qū)創(chuàng)造的大量軟件使其中的一些問題變得更糟糕。有大量的代碼需要維護,而許多用戶卻沒有動力去幫助實現(xiàn)這一目標。我們大概會在未來某個時間點能處理好這些問題,但現(xiàn)在還完全不清楚該如何處理。在這之前,我們只能將繼續(xù)向火星(以及更遠的地方)部署那些缺乏支持的軟件。
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~
