Log4j漏洞源碼分析


Log4j漏洞源碼分析

  1. 這幾天Log4j的問題消息滿天飛,今天我們就一起來看看從源碼角度看看這個漏洞是如何產生的。

  2. 大家都知道這次問題主要是由於Log4j中提供的jndi的功能。

具體涉及到的入口類是log4j-core-xxx.jar中的org.apache.logging.log4j.core.lookup.StrSubstitutor這個類。

原因是Log4j提供了Lookups的能力(關於Lookups可以點這里去看官方文檔的介紹),簡單來說就是變量替換的能力。

在Log4j將要輸出的日志拼接成字符串之后,它會去判斷字符串中是否包含${},如果包含了,就會當作變量交給org.apache.logging.log4j.core.lookup.StrSubstitutor這個類去處理。

相關的代碼下面這個

首先是org.apache.logging.log4j.core.pattern.MessagePatternConverter這個類的format方法

圖中標注1的地方就是現在漏洞修復的地方,讓noLookups這個變量為true,就不會進去里面的邏輯,也就沒有這個問題了。

圖中標注2的地方就是判斷字符串中是否包含${,如果包含,就將從這個字符開始一直到字符串結束,交給圖中標注3的地方去進行替換。

圖中標注3的地方就是具體執行替換的地方,其中config.getStrSubstitutor()就是我們上面提到的org.apache.logging.log4j.core.lookup.StrSubstitutor

StrSubstitutor中,首先將${}之間的內容提取出來,交給resolveVariable這個方法來處理。

我們看下resolver的內容,它是org.apache.logging.log4j.core.lookup.Interpolator類的對象。

它的lookups定義了10中處理類型,還有一個默認的defaultLoopup,一種11中。如果能匹配到10中處理類型,就交給它們去處理,其他的都會交給defaultLookup去處理。

匹配規則也很簡單,下面簡單舉個例子。

1.如果我們的日志內容中有${jndi:rmi://127.0.0.1:1099/hello}這些內容,去掉${},傳遞給resolver的就是jndi:rmi://127.0.0.1:1099/hello

2.resolver會將第一個:之前的內容和lookups做匹配,我們這里獲取到的是jndi,就會將剩余部分jndi:rmi://127.0.0.1:1099/hello交給jdni的處理器JndiLookup去處理。

圖中標注1的地方入參就是jndi:rmi://127.0.0.1:1099/hello

圖中標注2的地方就是jndi

圖中標注3的地方就是rmi://127.0.0.1:1099/hello

圖中標注4的地方就是處理器JndiLookup類的對象

圖中標注5的地方就是jndi來處理的入口

關於jndi相關的,以及漏洞如何復現網上有一大把的教程,這里就不展開了。


  1. 關於漏洞的修復。

主要是通過設置noLookups變量的值,不讓它進去這個if里面的邏輯。

這個變量的值是來自下面這個屬性

所以在在代碼中加入System.setProperty("log4j2.formatMsgNoLookups","true");這句也就可以了。當然網上有更多其他的修復方法,這里就不討論了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM