Log4j漏洞深度回顧系列之一:攻擊背景?
開源日志記錄工具Apache Log4j曾被爆出一個嚴重的遠程代碼執行漏洞,攻擊者可以借此構造惡意請求,觸發遠程惡意代碼的執行。消息爆出后,該漏洞引起了極大的關注。小半年過去了,相關熱度逐漸消退,是時候對整個過程進行一個徹底的總結回顧,并從中吸取教訓,避免以后再遭遇類似的問題。
加入Client-Side Protection & Compliance,防范每一次用戶數據外泄!
符合 PCI DSS v4.0 標準,助您嚴防網站惡意代碼和漏洞!
這一系列文章總共分為四篇,Akamai將結合自身技術團隊的了解,Akamai與全球客戶合作過程中應對該漏洞和其他安全隱患所積累的經驗,以及Akamai對整個互聯網流量的洞察,向大家介紹Log4j漏洞的起因、傳播范圍、利用方式、演變路徑,以及最重要的:我們所有人都需要從中吸取的教訓。
這就開始吧,本篇主要介紹Log4j漏洞的一些背景信息。
一、時間線
2021年11月24日,Apache基金會接到通知,稱已被廣泛使用的,基于Java的日志庫工具Log4j存在重大漏洞,可能導致隱私信息泄漏和遠程代碼執行(RCE)。而該漏洞自2013年就一直存在了。
第二天,Apache基金會保留了CVE-2021-44228并開始研究解決方案。接下來的12天里,為了解決此問題,他們對源代碼進行了多處修改,并于2021年12月9日公開披露了這個漏洞。
公布后,圍繞該漏洞開始出現如洪水般的攻擊嘗試,并且在那之后,攻擊規模和范圍一直以驚人的速度增長。
二、Log4j到底是什么?
要真正理解該漏洞,首先需要知道Log4j到底是什么。Log4j是Java社區中一個被開發者廣泛使用的庫,提供了一個簡單但強大的框架,可用于記錄錯誤信息、診斷信息等。
Log4j提供了很多讓人印象深刻的功能,其中之一是將日志記錄至多個目標位置,包括但不限于控制臺、文件、遠程TCP服務器、Syslog、NT Event Log以及電子郵件。此外,它還支持對日志消息、日志事件、自定義布局等內容進行分層過濾。
簡而言之,Log4j提供了完整豐富的功能,使其受到開發者的廣泛歡迎,從而導致從Web應用程序到嵌入式設備,各種地方都能見到Log4j的身影。
三、查找和嵌套
Log4j支持多種強大功能,其中最知名的功能之一應該是查找(Lookup)。該功能使得開發者可以將變量或表達式嵌入到Log4j在進行輸出之前自動評估的文本中。例如,開發者可以編寫代碼將下列文本記入日志:
“${date:MM-dd-yyyy} All Systems Good”
Log4j會將其中的模式${date:MM-dd-yyyy}識別為一種日志查找,并盡職地將該表達式替換為“今天”的日期。舉例來說,如果今天是2021年12月20日,那么在將上述日志輸出到目標位置前,Log4j會將其內容改為:
“12-20-2021 All Systems Good”
對開發者來說這很方便。如果不使用這種功能,開發者必須手工編寫代碼查詢日期,將格式調整為字符串,將其附加到日志行,然后輸出。盡管這樣的代碼寫起來并不麻煩也不費事,但畢竟與軟件的核心業務邏輯毫無關系,并且最終也會在一個個項目中不斷延續下去。
通過使用Log4j庫中現成的功能,開發者可以專注于項目中更重要的開發工作,讓Log4j處理與日志有關的各種任務。
Log4j支持很多這種類型的查找表達式。讓我們再來看看另外兩個與本文內容密切相關的:env和lower。env可以將主機系統上的環境變量包含到日志行中。例如,開發者可以將下列文本記入日志:
“The current user is ${env:USER}”
假設軟件正在以管理員用戶的身份運行,上述日志會輸出如下的內容:
“The current user is Administrator”
與將新數據注入文本的env和date不同,lower可用于操作已經存在的內容。Log4j會直接將表達式中出現的英文字母轉換為小寫形式。例如:
“The lower case text is ${lower:ABCDEFG}”
會輸出為:
“The lower case text is abcdefg”
這個例子本身似乎感覺沒什么意義,為何不自己將字母轉換為小寫呢?別忘了,Log4j還允許將查找表達式嵌套在一起,此時就厲害了。
我們可以將前兩個表達式嵌套為這種形式:
“The lower case current user is ${lower:${env:USER}}”
這會導致Log4j首先將${env:USER}表達式評估為Administrator,隨后將其送入lower,產生小寫的administrator,最終會輸出如下的內容:
“The lower case current user is administrator”
四、JNDI
雖然date、env和lower都很有趣并且實用,但這個漏洞之所以能夠存在,還離不開JNDI查找。JNDI(Java Naming and Directory Interface,Java命名和目錄接口),是一種內置于Java開發和運行時環境中的機制,可通過一個通用接口以簡單的方式查詢各種目錄服務中的信息。
實際上,可支持的目錄服務分為多種類型。例如,JNDI支持查詢DNS服務器以發現主機的IP地址,并能查詢AD和LDAP中的目錄實體。它甚至支持查詢正在運行中的Java環境本身以獲取Environmental Entries,例如當前正在運行的軟件的專用配置選項。
Log4j中的JNDI查找表達式可供開發者通過日志文本中嵌入的表達式直接訪問這個極為強大的子系統。舉例來說,如果開發者試圖將下列字符串記入日志:
“The current mail host is ${jndi:java:comp/env/mailhost}”
Log4j會將${jndi:java:comp/env/mailhost}表達式識別為JNDI查找,并將java:comp/env/mailhost這個偽URL傳遞給JNDI子系統。JNDI會將這種特定的URL類型識別為查詢,進而在當前運行的組件查找一個名為mailhost的配置選項。
假設該選項被配置為http://mymailserver.example.com,JNDI會將該信息回傳給Log4j,隨后Log4j會將查找表達式替換為http://mymailserver.example.com,并產生如下的輸出結果:
“The current mail host is mymailserver.example.com”
五、理解該漏洞的存在
簡而言之,Apache Log4j的這個漏洞為攻擊者提供了一種重大的機會,因為該庫廣受歡迎,尤其是其查找、嵌套和JNDI功能更是如此。雖然這些功能為開發者提供了很大的便利,但也催生了可能借此通過請求泄漏數據或導致遠程代碼執行的機會。了解這些背景信息后,我們可以開始更好地理解這個漏洞,以及攻擊者的利用方式了。