PbootCMS V3.2.12密码找回漏洞CVE-2026-12066
PbootCMS 是永久开源、免费可商用的国产 PHP 企业建站内容管理系统(CMS),主打中小企业官网、产品展示站,轻量化易上手。
一、基本情况
PbootCMS是一款全新内核且永久开源免费PHP企业网站开发建设管理系统,是一套高效、简洁、 强悍的可免费商用的PHP CMS源码。
PbootCMS采用了简单到想哭的模板标签,只要懂HTML就可快速开发企业网站。为广大开发者和企业提供最佳网站开发建设解决方案。

PbootCMS 作为免费可商用系统,用户通过官网获取免费域名授权码即算授权成功并永久有效,授权后允许删除前后台页面版权标识。
栋科技漏洞库关注到 PbootCMS V3.2.12版本中存在的密码找回漏洞,该漏洞现在已经被追踪为CVE-2026-12066,CVSS 4.0评分6.9。
二、漏洞分析
CVE-2026-12066是位于PbootCMS V3.2.12的 apps/home/controller/MemberController.php 中密码找回功能认证不当致账号劫持漏洞。
该漏洞影响密码处理组件中文件 apps/home/controller/MemberController.php 的取回功能,漏洞利用代码已公开,可被用于实施攻击。
取回接口采用无认证单次POST请求实现密码重置,仅依靠图形验证码作为防护手段,
不校验注册邮箱所有权,直接将攻击者传入的新密码写入数据库。
唯一具备权属校验作用的邮箱字段,在账号邮箱为空时校验逻辑直接失效,而用户名注册模式下账号默认无邮箱。
图形验证码生成接口与邮件验证码接口共用会话验证码存储域,攻击者仅需获取自身可识别的全新图形验证码及受害者用户名,
即可永久篡改目标账号密码。需立即采取修复措施,保障系统安全与会员账号安全。
具体来说,PbootCMS项目文件apps/home/controller/MemberController.php(取回方法)存在账号劫持漏洞:
密码重置流程接收未认证POST请求传入的目标用户名与新密码,仅通过会话存储的图形验证码$_SESSION['checkcode']校验请求,
直接将新密码写入ay_member数据表,未采用任何离线权属验证手段(无邮件令牌、无验证链接)。
(一)漏洞由五项独立缺陷叠加形成:
1、邮箱匹配校验逻辑被!empty($userInfo['useremail'])短路,用户邮箱字段为空的账号(用户名注册模式默认状态)可绕过邮箱校验;
2、即便账号填写邮箱,校验仅为信息核验,仅知晓邮箱字符串即可通过,无需验证邮箱实际控制权;
3、流程全程未生成一次性、时效型重置令牌,不发送验证邮件,控制器接收首次POST请求便直接执行密码更新;
4、图形验证码仅用于验证请求发起方为自然人,无法校验操作者为目标账号持有人;
5、图形验证码接口core/code.php与邮件验证码接口MemberController::sendEmail共用会话验证码键$_SESSION['checkcode'],
取回功能校验逻辑不区分验证码来源,新生成的图形验证码可替代前端界面标注的邮箱验证码完成校验。
未授权远程攻击者仅需获知受害者用户名,即可利用该漏洞覆盖账号密码,完全劫持会员账号。
常规PbootCMS部署场景(电商、社区、内容站点)下,会员订单、积分、收货地址、私信及自定义会员字段等绑定数据将全部泄露,
攻击者可以此为跳板,针对站点需登录访问的功能发起后续渗透攻击。操控用户名、密码、邮箱、验证码参数可造成弱密码重置漏洞。
利用该漏洞无需登录,无需任何权限。
(二)漏洞详情与验证代码
1、漏洞位置:
文件路径apps/home/controller/MemberController.php retrieve方法(第263至301行)
POST请求体危险参数:username、password、email、checkcode
2、漏洞源码(V3.2.12版本,与V3.2.5版本代码一致):
public function retrieve(){
if($_POST){
$checkcode = strtolower(post('checkcode', 'var'));
$email = post('email');
$username = post('username');
$password = post('password');
if (! $checkcode) alert_back('验证码不能为空!');
if ($checkcode != session('checkcode')) alert_back('验证码错误!'); // [flaw 4+5]
$where = ['username' => $username];
$userInfo = object_to_array($this->model->checkUsername($where));
if(!$userInfo) alert_back('该用户不存在!');
if(!empty($userInfo['useremail']) && $userInfo['useremail'] != $email){ // [flaw 1+2]
alert_back('与注册邮箱不匹配,请联系管理员!');
}
$data = [
'useremail' => $email,
'password' => md5(md5($password))
];
$this->model->updatePassword($where, $data); // [flaw 3] direct write, no token
alert_location('修改成功!', Url::home('member/login'), 1);
}
}
三、POC概念验证
1、攻击载荷:
管理员已设置登录后刷新可查看2、漏洞请求数据包
管理员已设置登录后刷新可查看3、服务器响应(HTTP 200状态码)——受害者账号密码被覆盖为123456,程序引导客户端跳转至登录页面:
HTTP/1.1 200 OK
Date: Wed, 13 May 2026 13:10:25 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-UA-Compatible: IE=edge,chrome=1
X-Powered-By: PbootCMS
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Content-Length: 94
{"code":1,"data":"修改成功!","tourl":"\/pbootcms-3.2.12\/?member\/login\/","rowtotal":1}
4、以下为Burp重放工具捕获的请求与响应截图,可佐证账号劫持漏洞:


发送上述请求后,使用受害者用户名与密码123456访问/pbootcms-3.2.12/?member/login/即可成功登录,
完全进入受害者会员中心,账号劫持完成。
5、修复建议
(1)禁止从请求体读取邮箱参数
密码重置流程需根据用户名从ay_member数据表读取账号绑定的注册邮箱,前端表单移除用户输入邮箱项,服务端丢弃该参数。
(2)生成一次性时效重置令牌并增加独立校验步骤
接收重置申请时,生成高安全随机令牌(如bin2hex(random_bytes(32))),存入数据库并绑定用户ID、设置短有效期(如15分钟),
仅向注册邮箱发送带令牌的重置链接/?member/resetPassword&token=<token>。
密码修改操作需通过独立接口resetPassword执行,校验并销毁令牌后方可变更密码。
(3)隔离验证码会话存储域
拆分共用的$_SESSION['checkcode'],采用区分用途的会话键(如登录验证码、注册验证码、邮箱验证码),
避免图形验证码冒充页面标注的邮箱验证码完成校验。
(4)错误提示统一化,禁止泄露账号是否存在
无论查询用户名是否存在,均返回统一提示“若该用户名对应账号已绑定有效邮箱,重置邮件已发送”,
防止攻击者遍历枚举用户名,降低漏洞危害范围。
(5)对密码重置接口启用访问频率限制与操作审计日志
基于客户端IP、目标用户名限制请求频次,记录重置尝试行为(来源IP、目标用户名、操作结果),便于批量劫持攻击行为溯源排查。
四、影响范围
PbootCMS 3.2.12
五、修复建议
PbootCMS ≥ 3.2.16
六、参考链接
管理员已设置登录后刷新可查看