结论:后台与数据库均可被完全接管 — 核心攻击链已实际验证成功
一、攻击链总览(已验证 ✅)
数据库弱口令 → 伪造管理员 Cookie → 免密接管后台
zb_users/c_option.php 含 zb / 123123 弱口令;该文件平时不可通过 HTTP 读取,但任意一次「任意文件读取/写入」漏洞都会导致全失守。本测试基于本地环境直接取证。zb/123123 对库 zb 有完整读写权限。zbp_member:用户 adminx(ID=1,管理员)、用户盐 mem_GUId、密码哈希 mem_Password;zbp_config:站点密钥 ZC_BLOG_CLSID。token = HMAC_SHA256(key=mem_Guid, 时间戳+ID+md5(mem_Password+站点CLSID)) + 时间戳/zb_system/admin/index.php?act=admin 返回HTTP 200「后台首页」,登录身份 adminx,无需密码、无需验证码。证据文件:case_zblog/ 下已存取的响应(已清理)。二、漏洞明细
MySQL 业务账号弱口令 + 3306 端口对外监听
证据:端口扫描 0.0.0.0:3306 LISTENING;凭证 zb/123123 登录成功,可完整读写库 zb(8 张表)。
影响:同一局域网(或端口暴露到公网时)任何攻击者可直接拖库:zbp_member 拿到管理员哈希与盐,结合发现 2 直接免密进后台;zbp_post/zbp_comment 全部内容可被篡改。拿到 DB 等价于拿到整站。
对比:root 账号已改强密码(4 组常见弱口令均失败),说明只有业务账号存在弱口令——这是典型的「root 加固了,业务账号忘了」。
登录态 Token 可离线伪造(设计层弱点)
依据(白盒):[引用] zblogphp.php:1609-1616 GenerateUserToken → c_system_common.php:2690-2702 CreateWebToken:Token 的 HMAC key 与消息因子全部来自 mem_Guid、mem_Password(数据库字段)与 ZC_BLOG_CLSID(配置项)。
影响:认证强度实际 = 数据库保密性。只要 DB 被拖(弱口令/SQLi/任意文件读),攻击者无需破解密码哈希即可构造任意用户的合法登录 Cookie,绕过密码、验证码、CSRF 三道防线。密码哈希(MD5 + 盐)本身也已被证明可「直接利用而非破解」。
建议:登录态签名加入「数据库之外的服务器侧秘密」(如 c_option.php 中的独立随机密钥),使拖库不等于接管后台。
验证码为「可自校验哈希」设计,一旦泄露站点 CLSID 即可离线伪造
依据(白盒):[引用] zblogphp.php:3839-3902 ShowValidCode/CheckValidCode · validatecode.php:96(字符集 29 位):验证码校验 = 比对 Cookie md5(CLSID+path[+IP] + 时间 + 验证码),服务器不存储任何状态。
影响:当前 CLSID 未泄露则无法利用(无法离线穷举);但只要出现一次任意文件读取读到 c_option.php/DB 配置,验证码即形同虚设,登录/评论爆破无成本。属于「放大器」型弱点。
指纹与组件版本全量暴露
响应头直接暴露 Server: nginx/1.15.11、X-Powered-By: PHP/7.3.4、Product: Z-BlogPHP 1.7.5、后台页面精确 Build 号 173540。攻击者可精确匹配已知 CVE/N-day。建议 nginx server_tokens off; + PHP expose_php=Off,Z-BlogPHP 关闭版本 Meta。
安装脚本与日志目录可被 HTTP 访问
/zb_install/index.php 返回 200(有安装锁,提示"不能重复安装",无重装接管风险);/zb_users/logs/ 返回 200 空页。两者当前无实质危害,建议 nginx 直接 deny all,缩小暴露面。
三、 tested-and-secure 项(黑盒+白盒均未打通)
| 攻击面 | 结果 | 说明 |
|---|---|---|
| 重装接管(/zb_install) | ✅ 安全 | 安装锁有效,拒绝重装 |
| SQL 注入(search/评论/前台) | ✅ 未发现 | sleep 探测无延迟差异;ORM 参数化([引用] UNABLE TO CITE: 逐模块污点分析未展开,仅黑盒探测) |
| 反射 XSS(搜索) | ✅ 被转义 | <script> 输出 0 次命中 |
| REST API(/zb_system/api.php) | ✅ 已关闭 | 返回 503 "API 未启用" |
| XML-RPC | ✅ 不可达 | 404 |
| UEditor 插件接口 | ✅ 需鉴权 | controller.php 未登录一律"没有权限" |
| nginx pathinfo 解析(phpstudy 经典 GetShell) | ✅ 已加固 | /x.jpg/x.php 返回 404,不执行 |
| 备份/.git/探针文件 | ✅ 未发现 | 常见 11 个路径均 404 |
| MySQL root 弱口令 | ✅ 已加固 | root/root、空、123456、password 均失败 |
| 后台爆破(验证码 OCR 路线) | — 未执行 | 验证码 5 位/29 字符集([引用] validatecode.php:96)固定 arial 字体可模板匹配,但被 Token 伪造链短路,无需爆破 |
四、攻击链复现(关键命令)
# 1. 直连数据库(从 webroot 配置取证) mysql -h127.0.0.1 -uzb -p123123 zb # 2. 导出关键数据 SELECT mem_ID, mem_Name, mem_Guid, mem_Password FROM zbp_member; SELECT conf_Value FROM zbp_config WHERE conf_Name='system' AND conf_Key='ZC_BLOG_CLSID'; -- mem_Password = 密码哈希( 盐=mem_Guid );CLSID = s:32:"b367****"; # 3. 伪造 Token(PHP/Python 均可) # md5path = md5(mem_Password + CLSID) # token = hash_hmac('sha256', 过期时间戳 + mem_ID + md5path, mem_Guid) + 过期时间戳 # 4. 免密进后台 cuRL -H 'Cookie: username_482cf6c8=adminx; token_482cf6c8=' \ 'http://127.0.0.1:7788/zb_system/admin/index.php?act=admin' # → HTTP 200 "企鹅企鹅企鹅 - 后台首页"
验证脚本(db_probe.py / forge_token.py)测试后已按约定清理,复现代码如上。
五、修复建议(按优先级)
| # | 措施 | 解决什么 |
|---|---|---|
| 1 | 立即更换 zb/123123 强密码;3306 绑定 127.0.0.1 或防火墙仅放行本机 | 切断 CRITICAL 主链入口 |
| 2 | 已泄露过的 DB/CLSID 视同失效:重装站点生成新 CLSID 与用户盐(或后台修改密码触发哈希更新) | 旧凭证/旧 Token 全部作废 |
| 3 | nginx:server_tokens off;php.ini:expose_php=Off;/zb_install/*、/zb_users/logs/* deny all | 缩小暴露面 |
| 4 | 长期:给 Z-BlogPHP 上游反馈——登录态/验证码签名因子加入「数据库之外的独立密钥」 | 根治「拖库=接管后台」 |
| 5 | PHP 7.3.4 与 nginx 1.15.11 均已 EOL,建议升级 phpstudy 内的运行时 | 消除组件层 N-day 风险 |
- 数据库弱口令 → 伪造管理员 Cookie → 免密接管后台
- MySQL 业务账号弱口令 + 3306 端口对外监听
- 登录态 Token 可离线伪造(设计层弱点)
- 验证码为「可自校验哈希」设计,一旦泄露站点 CLSID 即可离线伪造
- 指纹与组件版本全量暴露
- 安装脚本与日志目录可被 HTTP 访问

发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。