最近一天被log4j2刷屏了,多說一句,這個(gè)漏洞其實(shí)非常考驗(yàn)安全人員的應(yīng)急能力,代碼能力和社交能力。漏洞都三天了,竟然還有人在要exp,現(xiàn)在做安全的人都這么水了嗎?
我們向開發(fā)者給出安全建議的時(shí)候,一定要結(jié)合業(yè)務(wù)方具體需求,不要給出不切合實(shí)際的修復(fù)方案。即不能宕機(jī),又要保證安全性。
還有很多寫規(guī)則的乙方waf同學(xué),漏洞自己都沒研究明白,就要寫規(guī)則,結(jié)果誤報(bào)一大堆。
修復(fù)方法1,升級(jí)
這種方案是最簡(jiǎn)單的,但是需要關(guān)閉應(yīng)用,重新打包,提測(cè)。但是這種修復(fù)方案是最徹底的。當(dāng)然,如果因?yàn)槟承┰虿环奖汴P(guān)閉應(yīng)用,那么下面幾種方法可能最適合業(yè)務(wù)方。
修復(fù)方法2,修改配置文件
這個(gè)修復(fù)方法也需要暫時(shí)關(guān)閉應(yīng)用,配置方法 log4j2.formatMsgNoLookups=True。當(dāng)然,既然選擇這種修復(fù)方案,那還不如選擇第一種修復(fù)方案比較徹底。
修復(fù)方法3,javaagent
這個(gè)方法,需要給JDK注入一個(gè)jar,在jar中將存在漏洞的class代碼直接修改。缺點(diǎn)?有可能業(yè)務(wù)方不愿意用你的rasp。畢竟拖拖拉拉,萬一影響業(yè)務(wù)性能巴拉巴拉怎么整?
但是優(yōu)點(diǎn)不需要關(guān)閉站點(diǎn),不會(huì)影響線上業(yè)務(wù)。
修復(fù)方法4,反射修改屬性
這種方法同樣也不需要重啟應(yīng)用,只需要可以在對(duì)方的JVM中執(zhí)行代碼,就可以修復(fù)。無任何風(fēng)險(xiǎn)。當(dāng)然前提一定是可以執(zhí)行代碼,方式包括jsp文件等。
這東西其實(shí)就是內(nèi)存馬的核心思想,包括DFS搜索對(duì)象等等~
既然我們已經(jīng)知道了,最終根據(jù)前綴來找到最終的處理程序,也就是lookup。那么我們通過反射,直接修改strLookUPMap不就可以。
在log4j2中,配置文件是用單例模式,所以非常容易修改。。
通過反射修改這個(gè)對(duì)象,首先我們要拿到這個(gè)對(duì)象的引用。
使用我這段通過DFS搜索對(duì)象的工具。
選擇一個(gè)我們喜歡的對(duì)象查找路徑,然后將其變成反射代碼就可以了。代碼大概如圖
把這段代碼包裝成jsp文件,直接上傳到web站點(diǎn)運(yùn)行就行。當(dāng)然如果是springboot的話,想辦法執(zhí)行代碼也是可以的。
最終成功的沒有觸發(fā)jndi請(qǐng)求。
代碼
Object obj = LogManager.getLogger();
Field contextF = obj.getClass().getDeclaredField("context");
contextF.setAccessible(true);
Object context = contextF.get(obj);
Field configurationF = context.getClass().getDeclaredField("configuration");
configurationF.setAccessible(true);
Object configuration = configurationF.get(context);
Field substF = configuration.getClass().getSuperclass().getDeclaredField("subst");
substF.setAccessible(true);
Object subst = substF.get(configuration);
Field variableResolverF = subst.getClass().getDeclaredField("variableResolver");
variableResolverF.setAccessible(true);
Object variableResolver = variableResolverF.get(subst);
Field strLookupMapF = variableResolver.getClass().getDeclaredField("strLookupMap");
strLookupMapF.setAccessible(true);
HashMap strLookupMap = (HashMap) strLookupMapF.get(variableResolver);
strLookupMap.remove("jndi");
以上幾種方法僅供參考