0x00、前言
weblogic远程代码执行漏洞(CVE-2023-21931)复现与分析,同CVE-2023-21839一样由jndi注入导致的漏洞,同时间出的官方修复补丁,漏洞也在同一个类下的不同判断分支中,复现分析一下,CVE-2023-21839后面再补。
0x01、漏洞描述
CVE-2023-21931
Oracle WebLogic Server 是一款Java EE应用服务器。
受影响版本的WebLogic中WLNamingManager#getObjectInstance()存在JNDI查找逻辑,导致攻击者可以通过t3协议传入特定的对象触发反序列化逻辑,执行任意代码。
当传入boundObject 对象是 LinkRef 的实现类时,会调用传入对象 boundObject 的 getLinkName() 方法,并使用 lookup() 方法对getLinkName() 方法返回的 linkAddrType 地址执行远程 JNDI 加载。
0x02、漏洞范围
CVE-2023-21931
Oracle WebLogic Server(Core)@[12.2.1.0.0, 12.2.1.4.0]
Oracle WebLogic Server(Core)@[14.1.1.0.0, 14.1.1.0.0]
Oracle WebLogic Server(Core)@[12.1.2.0.0, 12.1.3.0.0]
Oracle WebLogic Server(Core)@[10.3.6.0, 10.3.6.0]
0x03、环境搭建
环境获取
这里直接拉取的vulhub上4ra1n师傅的环境:
https://github.com/vulhub/vulhub/tree/master/weblogic/CVE-2023-21839
下载进CVE-2023-21839目录下执行
docker-compose up -d
docker启动
成功访问到即可
将源码从docker中拖出来放进idea就可以审计了
相关命令:
【】表示填选项
进入镜像环境
docker exec -it 【进程序号】 /bin/bash
复制镜像文件到主机上
docker cp 【进程序号】:/【目录】 /【主机目录】
调试环境
调试环境(踩坑点也在里面了):
1、对docker-compose.yml文件进行编辑添加调试端口
2、运行启动容器docker-compose up -d
3、命令docker exec -it --user root 86 /bin/bash
进入容器,–user对应使用root身份进入容器(容器没有vim环境,需要root权限运行yum -y install vim安装vim编辑器)
4、安装vim编辑器(如果下载的docker环境有的话忽略)
5、编辑weblogic环境目录下/user_projects/domains/base_domain/bin/setDomainEnv.sh文件
6、在JAVA_DEBUG=”” export JAVA_DEBUG和if [ “${debugFlag}” = “true” ] ; then之间添加调试代码,端口需要与docker-compose.yml中添加的对应
debugFlag="true"
DEBUG_PORT=5556
export debugFlag
7、再将Lib包和weblogic环境依赖打压缩包复制出来导入idea项目库中即可,命令docker cp 【进程序号】:/【目录】 /【主机目录】
8、然后重启容器即可docker restart 86
,86对应我的容器id
9、最后在idea添加运行配置-添加远程jvm调试填选对应的地址端口即可
10、运行调试,显示连接目标即配置正确
11、发包断点即可进行调试
0x04、漏洞复现
poc:
public static void main(String[] agrs) throws Exception { |
执行命令创建文件成功
测试过程中如果遇到目标服务器无法访问或者payload发送不成功,关闭weblogic服务器防火墙
linux命令
//安装ufw
apt-get install ufw
//关闭防火墙
sudo ufw disable
//开启防火墙
sudo ufw enable
0x05、原理分析
当INITIAL_CONTEXT_FACTORY
上下文的工厂为weblogic.jndi.WLInitialContextFactory
类时,
JNDIInitialContext
上下文会对环境变量中读取weblogic.jndi.WLInitialContextFactory
工厂的上下文实现方法去实例化对象
跟下InitialContext
上下文获取比较好理解
获取到环境配置,调用getDefaultInitCtx
方法,调用NamingManager.getInitialContext
获取上下文器
从中读取到上下文工厂
返回调用WLInitialContextFactory.getInitialContext
方法
获取到上下文实现类WLContextImpl
获取到实现类过后,调用WLContextImpl.lookup
方法
向node
(即stub向通信服务器)调用lookup
方法
最后返回管理器处理对象的实例化结果NamingManager.getObjectInstance
再来看服务端对传输过来的t3协议数据的处理
通过weblogic.rmi.internal.BasicServerRef#handleRequest
对数据进行接受处理,会调用动态代理invoke
方法
相关调用栈:
invoke方法再次调用到BasicServerRef#invoke
中间调用过程可参考这篇文章中的lookup执行在weblogic服务器端的接受流程
最后调用到触发位置WLNamingManager#getObjectInstance
方法
通过当传入对象boundObject
属于LinkRef
类时,先会调用LinkRef#getLinkName
方法获取连接名
获取连接名的逻辑:
创建LinkRef
对象时向构造参数传递入连接地址的字符串
构造方法中会调用StringRefAddr
方法,该方法将地址字符串传递给常量contents
然后通过super
方法调用父类构造方法将地址字符串传递添加addrs
,同时将LinkRef
类名传递赋值给className
构造方法看完回到主体调用getLinkName
方法,className
在上文已经赋值存在,且className
等于linkClassName
的值
if条件都满足,最后调用getContent
返回Content
(即创建LinkRef
类时传递的构造参数的地址字符串)
最后执行lookup
实现jndi注入
直接调用实现的效果,因为只需要LinkRef
对象传入即可,其他参数设置空即可触发漏洞演示
public static void main(String[] agrs) throws Exception { |
0x06、漏洞修复
官方4月公布的补丁:
https://www.oracle.com/security-alerts/cpuapr2023.html
0x07、参考链接
https://nosec.org/home/detail/5082.html
https://www.anquanke.com/post/id/201005#h3-11
https://github.com/4ra1n/CVE-2023-21839
https://github.com/vulhub/vulhub/tree/master/weblogic/CVE-2023-21839