rootdirective-sec/CVE-2026-34234-Lab

GitHub: rootdirective-sec/CVE-2026-34234-Lab

这是一个用于在本地 Docker 中演示和验证 CtrlPanel 安装程序未授权 RCE 漏洞(CVE-2026-34234)的安全实验环境,并附带了无害的概念验证脚本。

Stars: 0 | Forks: 0

# CVE-2026-34234 - CtrlPanel 安装程序 RCE 实验环境 用于在 CtrlPanel 中演示 CVE-2026-34234 的本地 Docker 实验环境。 本仓库对比了以下内容: - `vuln`:通过摘要固定的 CtrlPanel `1.1.1` - `patched`:通过摘要固定的 CtrlPanel `1.2.0` 本实验环境仅限本地使用,并将服务绑定到 `127.0.0.1`。 ## 摘要 CVE-2026-34234 是 CtrlPanel Web 安装程序中的一个未授权 RCE。 该问题是由于两个 bug 链式触发的: 1. 安装程序的表单处理器在 `install.lock` 验证关卡之前即可访问。 2. 安装程序的输入被直接插入到 shell 命令字符串中。 在本实验环境中,易受攻击的容器会执行一个无害的验证命令,并将其输出写入容器内部。已修复的容器会接收到相同的请求,但不会创建验证文件。 预期结果: ``` vulnerable => proof file created patched => no proof file ``` ## 根本原因 ### 1. `1.1.1` 中存在漏洞的 shell 执行 原始存在漏洞的文件: ``` public/installer/src/functions/shell.php ``` `1.1.1` 中相关的上游代码: ``` function run_console(string $command, ...) { $path = dirname(__DIR__, 4); $handle = proc_open("cd '$path' && bash -c 'exec -a ServerCPP $command'", ...); } ``` 问题所在: - `run_console()` 接受单个 shell 命令字符串。 - 该字符串被传递给 `bash -c`。 - 用户可控的安装程序值可能会成为该命令字符串的一部分。 - shell 元字符可以改变命令结构。 ### 2. 存在漏洞的安装程序表单路径 原始存在漏洞的文件: ``` public/installer/src/forms/pterodactyl.php ``` `1.1.1` 中相关的上游行为: ``` run_console("php artisan settings:set 'PterodactylSettings' 'panel_url' '$url'", ...); run_console("php artisan settings:set 'PterodactylSettings' 'admin_token' '$key'", ...); run_console("php artisan settings:set 'PterodactylSettings' 'user_token' '$clientkey'", ...); ``` 问题所在: - `url`、`key` 和 `clientkey` 来源于安装程序的 POST 数据。 - 这些值被嵌入到 shell 命令字符串中。 - 安装程序的 endpoint 无需身份验证即可访问。 ### 3. 安装程序验证关卡顺序 安全通告指出,`public/installer/index.php` 仅在加载/执行安装程序表单逻辑之后才检查 `install.lock`。这使得安装程序处理器在已安装的实例上依然可被访问。 ## 补丁 / 修复 ### 1. 提前进行安装程序锁定检查 该修复将 `install.lock` 检查移至加载表单处理器之前。 修复后的行为: ``` if (file_exists('../../install.lock')) { exit("The installation has been completed already. Please delete the File 'install.lock' to re-run"); } ``` ### 2. 避免 shell 字符串执行 原始修复后的文件: ``` public/installer/src/functions/shell.php ``` `1.2.0` 中相关的上游代码: ``` function run_console(array $command, ...): string { $cwd = $cwd ?? $path; $handle = proc_open($command, $descriptors, $pipes, $cwd, null, $options); } ``` 为何此修复能解决问题: - `run_console()` 现在接受 argv 风格的数组。 - 命令不再被组合为单个 shell 字符串。 - 诸如 `$()` 之类的 payload 语法将保持为字面输入,而不会被解释为 shell 语法。 `1.2.0` 中修复后的表单行为使用了数组风格的命令执行方式: ``` run_console(['php', 'artisan', 'settings:set', 'PterodactylSettings', 'panel_url', $url], ...); run_console(['php', 'artisan', 'settings:set', 'PterodactylSettings', 'admin_token', $key], ...); run_console(['php', 'artisan', 'settings:set', 'PterodactylSettings', 'user_token', $clientkey], ...); ``` ## 实验环境设计 ``` 127.0.0.1:8081 -> vulnerable CtrlPanel 1.1.1 127.0.0.1:8082 -> patched CtrlPanel 1.2.0 127.0.0.1:9100 -> fake Pterodactyl API ``` 服务: - `vuln`:真实的 CtrlPanel `1.1.1` - `patched`:真实的 CtrlPanel `1.2.0` - `fake-api`:本地伪造的 Pterodactyl API,仅用于满足安装程序检查 - `mysql_vuln` / `mysql_patched`:独立的 MariaDB 实例 - `redis_vuln` / `redis_patched`:独立的 Redis 实例 本实验环境未修改 CtrlPanel 应用程序的源代码。 Dockerfiles 仅包装了原始容器的 entrypoint,以规范化 Docker Desktop runtime 的权限: ``` /var/www/html/storage /var/www/html/bootstrap/cache ``` 在修复权限后,wrapper 会执行原始产品的 entrypoint。 ## PoC 设计 主要的 PoC: ``` poc/poc_http_only.py ``` 特性: - 仅发送 HTTP POST 请求 - 不使用 `docker exec` - 不检查容器 - 不启动反弹 shell - 仅使用无害命令:`id`、`whoami`、`hostname` 辅助脚本: ``` poc/poc_lab.py ``` 用途: - 发送相同的 HTTP 请求 - 使用 `docker compose exec` 验证容器内部的验证文件 - 仅用于演示和回归测试 App 容器内部的验证文件: ``` /var/www/html/storage/logs/cve_2026_34234_proof.txt ``` ## 运行 从干净的实验环境状态开始: ``` docker compose down -v --remove-orphans docker compose up -d --build ``` 等待 app 容器启动,然后运行: ``` python3 poc/poc_lab.py ``` 预期输出: ``` == Testing vulnerable == proof_exists: True result: PASS expected_proof=True == Testing patched == proof_exists: False result: PASS expected_proof=False [+] Expected result reached: vulnerable => proof file created patched => no proof file ``` ## 手动 HTTP 专属测试 向易受攻击的目标发送 HTTP 专属 PoC: ``` python3 poc/poc_http_only.py --target http://127.0.0.1:8081 ``` 手动验证验证文件: ``` docker compose exec vuln sh -lc 'cat /var/www/html/storage/logs/cve_2026_34234_proof.txt' ``` 预期的验证文件: ``` uid=1000(laravel) gid=1000(laravel) groups=1000(laravel) laravel ``` 对已修复的容器运行相同的请求: ``` python3 poc/poc_http_only.py --target http://127.0.0.1:8082 ``` 验证修复后的行为: ``` docker compose exec patched sh -lc 'test -f /var/www/html/storage/logs/cve_2026_34234_proof.txt && cat /var/www/html/storage/logs/cve_2026_34234_proof.txt || echo "no proof file"' ``` 预期: ``` no proof file ``` ## 清理 移除容器、网络和实验环境数据卷: ``` docker compose down -v ``` ## 注意事项 - 本实验环境仅供本地安全研究使用。 - 请勿对您不拥有或未经授权测试的系统运行 PoC。 - 验证文件被有意限制为仅在容器内部输出命令结果。 - 存在漏洞和已修复的服务使用独立的数据库和 Redis 实例。 - fake API 的存在仅仅是为了模拟安装程序流程所需的最低限度的 Pterodactyl API 响应。 ## 免责声明 本仓库仅供教育性安全研究和防御性验证使用。 所有演示均旨在提供的本地 Docker 实验环境内运行。概念验证避免了破坏性操作、持久化、凭据窃取、数据泄露和针对现实世界的攻击。 未经明确授权,请勿将此项目用于任何系统。对于因使用本材料而造成的误用或损害,作者不承担任何责任。 ## 参考 - GitHub 安全通告:https://github.com/Ctrlpanel-gg/panel/security/advisories/GHSA-jmhr-q9q5-fqwh - CVE 记录 / NVD:https://nvd.nist.gov/vuln/detail/CVE-2026-34234 - 修复版本:https://github.com/Ctrlpanel-gg/panel/releases/tag/1.2.0 - 上游仓库:https://github.com/Ctrlpanel-gg/panel
标签:Docker, Go语言工具, OpenVAS, PHP, 安全防御评估, 搜索引擎查询, 漏洞复现环境, 版权保护, 请求拦截, 远程命令执行, 逆向工具