其实这里主要是OID及attrtyp的转换,可以参考官方文档,笔者这里直接复用了mimikatz相关代码,大致流程如下:
首先DRS_MSG_GETCHGREQ结构体相关生成直接利用kull_m_rpc_drsr_MakeAttid,然后域控制器返回的响应消息是一个DRS_MSG_GETCHGREPLY结构体,这里使用的是DRS_MSG_GETCHGREPLY_V6版本,根据结构体的描述,可以知道,相关信息在pObjects属性中,这是一个REPLENTINFLIST结构的表链,在mimikatz中kull_m_rpc_drsr_ProcessGetNCChangesReply对这个链表进行了遍历,最后kull_m_rpc_drsr_ProcessGetNCChangesReply_decrypt(其实就是文档的反向解密)进行RC4解密。
然后继续调用kuhl_m_lsadump_dcsync_descrObject,调用kuhl_m_lsadump_dcsync_descrUser,针对哈希,微软在使用rId对unicodepwd等进行了加密,所以最终会调用kuhl_m_lsadump_dcsync_decrypt,再利用kull_m_string_wprintf_hex打印。
当然这个过程中利用 kull_m_rpc_drsr_findMonoAttr、kull_m_rpc_drsr_findAttr、kull_m_rpc_drsr_findAttrNoOID等函数进行了数据结构相关转换读取,具体过程可以参考mimikatz源码,有点复杂…
实现效果:
7月20号,ZDI官方Blog公布了一个名为abusing-java-remote-protocols-in-ibm-websphere 的文章,文章中提到了Websphere的两个漏洞,一个是RCE,另外一个是XXE,根据Blog中的内容来看,漏洞属于IIOP协议的反序列化,也是基于JNDI的利用,但是跟常规的JNDI利用有一些不同之处,一方面是Websphere将IIOP替换成自己的实现,另外就是Websphere严格的类加载机制导致大部分公开的利用链都没法利用,这个漏洞利用需要访问至少2809端口以及两次外连请求,从红队利用角度来看稍微有点鸡肋,但是漏洞的利用思路以及EXP的构造都非常的有意思,是一个值得研究的漏洞。
漏洞环境准备
经常做分析的同学都有深刻体会,针对有些不了解、不熟悉的系统进行分析时往往在环境准备上会耗费大量时间,而且有部分漏洞的利用需要在特定的条件和环境下进行,经常是”环境准备1天,分析调试10分钟“
Websphere的安装有两种方式:
在线安装,直接在https://www.ibm.com/support/pages/installation-manager-and-packaging-utility-download-documents下载Installation Manager工具就可以在线安装,国内的网速环境比较慢,需要挂代理然后多刷新几次,直到出来以下界面,说明就OK了。
离线安装,这种方式现在官方基本上不推荐,而且离线的安装包基本上都是8.X的相对来说比较老,离线安装基本上需要将低包和安装程序都全部下载下来。
注:尽量不要选择基于Docker的安装环境,JAVA大部分RMI通信会依赖其他端口(一般是高端口)进行通信,安装的时候一定不要选补丁,不然复现不了,在线安装的版本是自带补丁的版本,本次测试的环境主要覆盖了两个版本,8.5.5.0以及9.0.0.2版本,这两个版本基本上涵盖了主流的版本。
注:尽量不要选择基于Docker的安装环境,JAVA大部分RMI通信会依赖其他端口(一般是高端口)进行通信,安装的时候一定不要选补丁,不然复现不了,在线安装的版本是自带补丁的版本,本次测试的环境主要覆盖了两个版本,8.5.5.0以及9.0.0.2版本,这两个版本基本上涵盖了主流的版本。
漏洞分析
一般情况下调试之前我们要看下端口对应是哪些进程启动,然后给对用的进程加上远程Remote Debug选项,Websphere的远程调试直接在后台对应Application Server下面设置Remote Debug就可(2809的端口以及其它几个端口PID都一样),Websphere之前没有针对性的看过,根据官方的描述我们直接将断点打在com.ibm.ws.Transaction.JTS.TxServerInterceptor#receive_request上,然后用IIOP客户端直接连接,触发断点之后,就可以在堆栈里面看到完整请求的触发路径。
到这里不由得让我们想起了之前那个RMIBYPASS的场景https://www.veracode.com/blog/research/exploiting-jndi-injections-java ,倒着我们就可以自定义一个RMI服务,将bind的内容设置成我们可以控制的org.apache.wsif.naming.WSIFServiceStubRef类型,就可以到最下面的函数,为什么上面那个org.apache.wsif.naming.WSIFServiceRef不行,因为前面提到了这个类必须要是EJBHOME的实现类,上面的明显不符合要求,下面的是通过动态代理来生成一个指定接口的类,而且接口的类型我们也可以控制,所以接下来就是如何利用wsif服务来进行代码执行了。
这里ctx.lookup里面的jndi的地址可以设置为自定义rmi的服务,具体的RMI服务代码如下