Last updated on 30. Mai 2022
In a recent penetration test we had the task to test a client-server-application in Java. The application was used by external people for interaction with our clients employees (clerks). The following picture shows the basic architecture of the application:
Both, customers and clerks, use the same Swing UI to communicate with the backend. The application provides different functionality, so we started testing the basics.
Port scans were inconspicious, we found an old webserver version in the backend, but no usable exploits were available for the Tomcat used in our application. Other basic tests also did not reveal any special findings or vulnerabilities, so we started to inspect the applications different functions.
We created so called files, which contains information the client submits to the internal clerk for further processing. We tested the invoicing and payment functionalities, but none of this has given us any indication for security vulnerabilities, so we kept looking for other functions that we could use as an attack vector.
Then we discovered a file upload functionality, available for every customer in the Swing UI. This functionality was introduced to allow customers bulk upload of files. Customers should wrap their information for a single file into an XML structure and so they can submit multiple files in one single XML. The backend reads the uploaded XML and creates the files.
So we found two possible vulnerabilities to investigate: XML external entities and a file upload, we started to test the XXE, but without success.
The file upload seemed to be interesting though, because we noticed that you could upload any file format. During our upload tests we noticed that the uploaded files are checked by Clam AV, so a lot of our malicious uploads were blocked. So we looked at the clerk’s view of the UI and noticed, that there was a button to view files that have been uploaded by customers. That was logical for us at first (clerks process the information provided, so maybe they need to check the unprocessed uploaded data), but when we clicked the according button in the Swing UI to view an XML upload, our Visual Studio Code popped up. We had a hunch why this was so, so we looked at the code of the Swing UI and our suspicions were confirmed: Javas Desktop.getInstance().openFile() was used to open the file uploaded by customers. This method opens a file with the systems associated program.
So we adapted our strategy: the goal was now to upload a reverse shell in a file format, that has an associated program on the clerks computers. We tried different formats, most of them were blocked by Clam AV but then we ended up with Visual Basic Script. We took a reverse shell from https://github.com/bitsadmin/revbshell and uploaded it. It was not blocked by Clam AV and when we clicked the view button in the clerks UI, our reverse shell was activated:
We were now able to query information about the system, download files and so on. We gained full control over an computer in the internal network from the outside.
How can we prevent this?
The first mistake is to allow any file extension. You should specify allowed extensions and strictly enforce them. In our situation, the only needed file format is XML, so why should other formats be allowed? If you enforce the file type, you need to validate it, don’t trust the content type header or other information that could be spoofed. You should also enforce length limits for both file name and size. If neccessary, run the uploaded files through an antivirus solution or some other sandbox, but be aware this does not provide complete protection: there are always files that are not classified correctly, for example our reverse shell in Clam AV 🙂
For more information, check out the OWASP Cheat Sheet for file uploads.
This article shows how a single vulnerability in a file upload can compromise an internal network, because a reverse shell is opened from an internal computer.