CVE-2019-12180 – ReadyAPI & SoapUI command execution via malicous project file

In early 2019, I had to pentest a couple of SOAP WebServices of a client and, as usual, I requested them some example requests as a baseline for my analysis. The client suggested to use a SoapUI / ReadyAPI project instead of giving to me single XML example requests: a good way to keep everything organized in a comprehensive way.

I had only a very basic experience with SoapUI at that time (and still is the same…), because I never used it for more than parsing a WSDL descriptor or organize basic requests for my tests (I do everything using BurpSuite).

However, that day something caught my attention: I noticed that the web service I was testing required the current date to work, otherwise it would return an error. So, I asked myself how my SoapUI project could know how to calculate the correct date every time the test case is launched or, more generally, add dynamic generated data to test case requests: the answer is the Apache Groovy Language script.

Groovy Expression inside Test Case

Apache Groovy is an Expression Language and this immediately reminded me of many Web vulnerabilities (https://portswigger.net/kb/issues/00100f20_expression-language-injection).  

After some basic testing, I figured out that the programs (either SoapUI and ReadyAPI) allow to execute OS commands with no restrictions everywhere the EL code is permitted and interpreted. Woah, not bad for an “innocent” XML project.

However, imagining a phishing attack scenario, sending a project with a malicious payload inside test case requests would require user interaction to trigger the payload. While this would still be a vulnerability, I wouldn’t consider it really “exploitable”.

Luckily for us, both SoapUI and ReadyAPI offer a nice feature that can be (ab)used for our goal of limiting to the bone the user interaction required for our attack: the “LoadScript” project setting (con:afterLoadScript element of the XML project file).

“Load Script” feature

As the names suggests, these scripts are executed every time the project is loaded and also when it’s imported for the first time, making our attack really “exploitable”!

Calc.exe PoC:

Calc.exe PoC

Example payload to execute a reverse shell (Windows):

Shell PoC:

Shell PoC

Note: a similar behavior can be obtained using the “SaveScript” feature, that triggers the script once the project is saved. Also, there are plenty of “minor insertion points” to achieve command execution, but they require user interaction (e.g.: project properties, custom properties, variables…). Basically, every scriptable property/variable/configuration can be a valid place to insert your payload.

At the time of writing, this is a 0day vulnerability, since (multiple) proposed disclosure dates have passed with no patch release by the vendor.

To avoid potential exploitation, before loading project files, open them with a text editor and check for suspicious Groovy Scripts, especially in <con:afterLoadScript> and <con:afterLoadScript> elements.

Disclosure timeline:

Link to Advisory: https://lab.mediaservice.net/advisory/2020-04-readyapi-soapui.txt

Link to PoC: https://github.com/0x-nope/CVE-2019-12180