Log4j远程代码执行漏洞分析
一、前言
刚刚过去的2021年,工作中哪件事最让你难忘?
回答可能各种各样,但是对于IT研发,尤其是安全相关人员来说,2021年底爆出的Log4j远程代码执行漏洞,绝对让人印象深刻。一时间,开发圈炸了锅,“核弹级漏洞”、“超高危漏洞”、“史诗级漏洞” 等词汇看的让人瑟瑟发抖,不少公司开发人员更是连夜加班修复漏洞。
Log4j维护团队行动也很迅速,很快推出了修复版本,从2.15.0-RC2到2.15.0正式版,再到2.17.0版本,本想这事应该告一段落了吧,没想到。
2021年12月28日,Log4j又发布了2.17.1版本,Log4j v2.17.0又出现了远程代码执行漏洞,加上本次的漏洞,这是Log4j近期爆发的第4个漏洞了(官网截图如下):
■CVE-2021-44832(远程代码执行漏洞)
■CVE-2021-45105(拒绝服务攻击漏洞)
■CVE-2021-45046(远程代码执行漏洞)
■CVE-2021-44228(远程代码执行漏洞)
我们来看看这个最新的CVE-2021-44832漏洞是个什么鬼!
官网的描述翻译过来大意是:
Apache Log4j2 2.0-beta7 到 2.17.0 版本(不包括安全修复版本 2.3.2 和 2.12.4)容易受到远程代码执行(RCE)攻击,其中有权修改日志配置文件的攻击者可以构建恶意配置将 JDBC Appender 与引用 JNDI URI 的数据源一起使用,该 JNDI URI 可以执行远程代码。
二、漏洞复现
分析原因之前,我们首先在本地编写一段代码,使用java 远程代码执行框架 RMI(Remote Method Invocation)来复现 Log4j的漏洞。本地新建一个maven工程,pom文件中引入存在安全漏洞的log4j版本:
工程中主要有三个类:
第一步,写一个恶意代码类,代码里执行了打开一张本地照片的命令。
第二步,在本地启动一个RMI服务,这个服务的作用是让被入侵方调用。代码中通过java反射机制将恶意代码对象注册到RMI服务上。
第三步,创建一个可执行类,使用Log4j日志记录功能。由于Log4j存在安全漏洞,记录日志时会调用上一步中启动的RMI服务。从输出结果可以看出,程序执行了恶意类中的代码,打开了本机中的一张照片。
需要注意的是,如果本机安装了杀毒软件,需要将杀毒软件关闭,否则执行代码时可能会被拦截:
三、原因分析
下面我们就来分析一下漏洞产生的原因:
1、lookup
Log4j是一个功能非常强大的开源日志组件,提供方便的日志记录功能。通过上面的漏洞复现代码可以看到,执行类里逻辑非常简单,定义了一个变量“test”,通过log4j记录日志,打印这个变量,这是再正常不过的操作了。
“test”变量是我们自己定义的,当然也可以是从外界输入的,如果从外界输入的变量是“${java:os}”,日志会输出什么呢?我们修改代码看一下:
从输出结果可以看到,日志打印出了操作系统相关的信息。为什么会产生这种现象呢?原来,log4j提供了一个lookup机制,对lookup机制不熟悉也没关系,只需要知道这个功能可以把一些系统变量放到日志中就可以了。
2、JNDI
前言中介绍Log4j漏洞的时候,提到了JNDI,有的同学可能对JNDI不是很了解,简单说一下,JNDI全称为Java Naming and Directory Interface,即 Java 名称与目录接口,这个接口的作用是通过名称查找实际对象的服务,比如我们漏洞复现代码中的rmi://127.0.0.1:1099/evil。
如果被攻击的服务器访问了这个RMI服务,那么服务器就会执行RMI服务中的evil方法中的代码。
下面通过一个图来解释一下:
通过上面的分析,我们应该基本了解了Log4j远程代码执行漏洞发生的原因。简单来说就是,Log4j中提供了lookup机制,允许记录日志时将一些系统变量放到日志中。如果变量中包含JNDI,攻击方就可以利用JNDI功能去查找并执行某些不安全的服务,比如RMI,该服务可以允许远程代码执行,从而导致该漏洞。
四、结束语
我们的项目中可能使用了各种开源软件,开源软件在给我们带来方便的同时,带来的风险也在增加。像Log4j这样作为软件系统基石的开源软件还有很多,一旦这些开源软件发生安全漏洞,波及面将会非常广泛。
安全漏洞伴随着软件的诞生而产生,是无法避免的,就我们的能力来说,可能很难发现开源软件中的漏洞,我们能做的就是在漏洞爆出后迅速行动,及时修复漏洞,避免自己所在的企业遭受因安全漏洞带来的重大安全风险甚至经济损失。
往期回顾
EBCloud