Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apache Solr Backup Restore RCE [CVE-2023-50386] #19046

Merged
merged 5 commits into from Apr 23, 2024

Conversation

jheysel-r7
Copy link
Contributor

@jheysel-r7 jheysel-r7 commented Apr 1, 2024

Apache Solr from 6.0.0 through 8.11.2, from 9.0.0 before 9.4.1 is affected by an Unrestricted Upload of File with Dangerous Type vulnerability which can result in remote code execution in the context of the user running Apache Solr. When Apache Solr creates a Collection, it will use a specific directory as the classpath and load some classes from it. The backup function of the Collection can export malicious class files uploaded by attackers to the directory, allowing Solr to load custom classes and create arbitrary Java code.

Verification Steps

  1. Start msfconsole
  2. Do: use apache_solr_backup_restore
  3. Set the RHOST, LHOST and if required, the USERNAME, and PASSWORD options
  4. Run the module
  5. Receive a Meterpreter session as the solr user.

Reason for extra files in data

When you upload a backup configuration (which is how you upload the payload) a number of checks get run on the contents the config. The managed-schema.xml defines references to a variety of different fields and if the references aren't present (say you try and delete the lang folder) the configuration upload fails:

 "failure":{
    "192.168.32.2:8983_solr":"org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException:Error from server at null: Error CREATEing SolrCore 'GlRYHeVV_shard1_replica_n1': Unable to create core [GlRYHeVV_shard1_replica_n1] Caused by: Can't find resource 'lang/contractions_it.txt' in classpath or '/configs/jlandpsl', cwd=/opt/solr-9.0.0/server"},`

If you try and delete all the references inside the schema all together then it's also unhappy:

  "failure":{
    "192.168.48.2:8983_solr":"org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException:Error from server at null: Error CREATEing SolrCore 'NymWCcrx_shard1_replica_n1': Unable to create core [NymWCcrx_shard1_replica_n1] Caused by: _version_ field must exist in schema and be searchable (indexed or docValues) and retrievable(stored or docValues) and not multiValued (_version_ does not exist)"},

The PR was originally 49 files due to the extra files required to successfully upload the conf.zip + exploit. I've spent some time trying to minimize the schema and the extra files it references.

Apache Solr Mixin

Reusable Apache Solr code was taken from solr_velocity_rce.rb. I'd be happy to refactor that module to use the new mixin once this has been merged.

Windows Support (and why there is none, my apologies)

When writing an exploit module for an application that runs on multiple operating systems I always try and write the module so that it will work regardless of the OS the application is running on. However, in this case I've left out support for Windows. Some of the reasons being:

  1. When trying to upload a .zip file created by Rex::Zip::Archive.new or by using "Send to Compressed Folder" in the Windows UI, or via Compress-Archive in PowerShell, Apache Solr errors. Uploading a zip created by 7zip works just fine, this seems to be a known issue. We need to edit a malicious .class file inside the zip in order to exploit the application and because Rex::Zip::Archive's are incompatible with the application well then I think that's a good enough reason to drop support for Windows.

  2. The ClassLoader mixin wasn't working for me so I used a precompiled java class and hot-swapped the metasploit payload into it and substituted the spaces in the payload for {$IFS} which wouldn't work on Windows.

  3. When you run the .msi installer the default install location of Apache Solr is the directory in which you run the installer - you need to know where the DataDir is to exploit successfully. On Linux the DataDir default install location seems to be /var/solr which is convenient, where as on Windows it's a bit more complicated. We could set a datastore option for this DataDir or possibly grab the information needed from an error message or a webpage although it's an added layer of complexity.

  4. I was unable to verify Windows targets were vulnerable via manual exploitation.

For the reasons above I decided to pass on adding Windows support. Though I would be happy to help test a PR that adds support for Windows if someone is passionate enough to submit one.

@jheysel-r7 jheysel-r7 changed the title Apache solr backup restore Apache Solr Backup Restore RCE [CVE-2023-50386] Apr 2, 2024
Writing file to disk working

working on linux

wip authentcaiton

Consolodated conf folders into one

Renamed conf1 to conf in msf data dir

Randomize the configuration name

Docs plus finishing touches

rubocop

Updated exploit file location

Removed unused external dir

Reduced conf folder
@h00die
Copy link
Contributor

h00die commented Apr 2, 2024

I had looked at this, but due to the number of files involved decided to pass.
Without looking at this, some ideas:

  1. Can you download a backup from target, poison it, then reupload? This may help from overwriting some files that may have been customized
  2. Can you just put all the files in a zip in framework, then modify the one you need in memory. Since most these files are text, it should compress well and make framework a bit less messy only adding one file instead of a bunch

@jheysel-r7
Copy link
Contributor Author

I had looked at this, but due to the number of files involved decided to pass. Without looking at this, some ideas:

  1. Can you download a backup from target, poison it, then reupload? This may help from overwriting some files that may have been customized
  2. Can you just put all the files in a zip in framework, then modify the one you need in memory. Since most these files are text, it should compress well and make framework a bit less messy only adding one file instead of a bunch

Hey @h00die thanks for the suggestions.

  1. You can only download a config from the target if a collection has been created that references a config. You can't always count on that being present so the module needs to ship with it's own valid config. Also you need not worry about overwriting anything - the module uploads it's own unique backup config with a randomized name/ identifier and then deletes it immediately after delivering the payload.

  2. I had considered this but after not finding any .zip files in the /data directory I assumed it might not be best practice.

➜  metasploit-framework git:(apache_solr_backup_restore) ✗ find . -name "*.zip"
./external/source/rdll_template/Reflective DLL.zip
./external/source/DLLHijackAuditKit.zip
./tmp/xmlexport-20231120-222322-4.zip

I'll double check with the team and see what they think.

@jheysel-r7 jheysel-r7 marked this pull request as ready for review April 2, 2024 19:48
ports:
- "8983:8983"
- "5005:5005"
command: sh -c "solr start -c -a '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005' && tail -f /dev/null"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After running docker-compose I'm hitting ms-1 | [-] Failed to connect to the Postgres data service: could not translate host name "db" to address: Name does not resolve - Any idea what's going on there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @zgoldman-r7, not exactly sure what's going on there. Just to confirm, you're running docker-compose up in the same directory as the docker-compose.yml?

It's interesting the error pertains to Postgres. Maybe the issue has something to do with your environment, docker/ docker-compose version or possibly existing configurations/ containers. I just retested this container on a fresh Ubuntu 22.04 VM and it seemed to work without any issues:

msfuser@msfuser-virtual-machine:~$ uname -a
Linux msfuser-virtual-machine 6.5.0-28-generic #29~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr  4 14:39:20 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
msfuser@msfuser-virtual-machine:~$ docker-compose -version
docker-compose version 1.29.2, build unknown
msfuser@msfuser-virtual-machine:~$ docker -v
Docker version 24.0.5, build 24.0.5-0ubuntu1~22.04.1
msfuser@msfuser-virtual-machine:~$
msfuser@msfuser-virtual-machine:~$ cat docker-compose.yml
version: '3'

services:
  solr:
    image: solr:9.0.0
    ports:
      - "8983:8983"
      - "5005:5005"
    command: sh -c "solr start -c -a '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005' && tail -f /dev/null"
msfuser@msfuser-virtual-machine:~$ sudo docker-compose up
[sudo] password for msfuser:
Creating network "msfuser_default" with the default driver
Pulling solr (solr:9.0.0)...
9.0.0: Pulling from library/solr
3c67549075b6: Pull complete
b3cda026f111: Pull complete
d0316070ed7b: Pull complete
5f6a8ff6cd7e: Pull complete
fb9ffccab5f5: Pull complete
6fc2e145c3fe: Pull complete
f345603f3fa0: Pull complete
9f10439f23a4: Pull complete
9c3461a5022e: Pull complete
a14f01cd9e96: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:5103aea19a40a3462f612cd816d8ba6d0f58ff3ff5bf3930298393068797e83d
Status: Downloaded newer image for solr:9.0.0
Creating msfuser_solr_1 ... done
Attaching to msfuser_solr_1
solr_1  | Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require
solr_1  | RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'.
solr_1  |
solr_1  | Waiting up to 180 seconds to see Solr running on port 8983 [-]
solr_1  | Started Solr server on port 8983 (pid=59). Happy searching!
solr_1  |

It's also working on my MacOS host with the following docker versions:

➜  apache_solr docker-compose -v
Docker Compose version v2.24.6-desktop.1
➜  apache_solr docker -v
Docker version 25.0.3, build 4debf41
➜  apache_solr
➜  apache_solr docker-compose up
[+] Running 1/0
 ✔ Container apache_solr-solr-1  Created                                                                                                                                                                                               0.0s
Attaching to solr-1
solr-1  | Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require
solr-1  | RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'.
solr-1  |
solr-1  | Waiting up to 180 seconds to see Solr running on port 8983 [\]
solr-1  | Started Solr server on port 8983 (pid=61). Happy searching!
solr-1  |

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking a look at the PR! Let me know if testing on Ubuntu works or if you have any other questions :)

Copy link
Contributor

@zgoldman-r7 zgoldman-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - above error I got was my own fault, not the code. Nice work!

@zgoldman-r7 zgoldman-r7 merged commit 26a108a into rapid7:master Apr 23, 2024
48 checks passed
@zgoldman-r7 zgoldman-r7 added the rn-modules release notes for new or majorly enhanced modules label Apr 23, 2024
@zgoldman-r7
Copy link
Contributor

Release Notes

Adds apache_solr_backup_restore module, taking advantage of a Unrestricted Upload of File with Dangerous Type vulnerability, allowing the user to gain a session in a Apache Solr instance for remote code execution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants