DedeCMS 前台任意用户密码修改漏洞(CNVD-2018-0109)修复教程

一、漏洞说明

该漏洞属于「账号接管类高危漏洞」,攻击者无需知道用户账号密码,仅需构造恶意请求,即可绕过验证,直接修改任意用户(包括管理员)的密码,进而登录网站后台,控制整个网站。

  • 漏洞编号:CNVD-2018-0109
  • 危害等级:高危
  • 影响版本:DedeCMS V5.7 SP2 全版本(含各类衍生版本)
  • 漏洞文件:/member/resetpassword.php
  • 漏洞场景:前台会员中心「密码重置」功能,未对请求参数进行有效验证,缺少token校验和身份验证,导致攻击者可越权修改任意用户密码。

二、代码分析

漏洞核心原因:resetpassword.php 文件中,密码重置逻辑仅校验「用户ID」和「邮箱」,但未校验请求的合法性,且未加入随机token防止伪造请求,攻击者可通过构造用户ID和邮箱参数,直接提交密码重置请求。

关键漏洞代码(原文件片段):

复制代码
<?php
// 原漏洞代码
if($_POST['submit']){
    $uid = $_POST['uid'];
    $email = $_POST['email'];
    $newpwd = $_POST['newpwd'];
    // 仅校验用户ID和邮箱是否匹配,无其他验证
    $row = $dsql->GetOne("SELECT * FROM `#@__member` WHERE mid='$uid' AND email='$email'");
    if($row){
        // 直接修改密码,无token校验、无身份验证
        $newpwd = md5($newpwd);
        $dsql->ExecuteNoneQuery("UPDATE `#@__member` SET pwd='$newpwd' WHERE mid='$uid'");
        echo '密码修改成功';
    }else{
        echo '用户ID或邮箱错误';
    }
}

代码问题分析:

  1. 缺少 token 校验:未生成随机token并绑定用户会话,攻击者可直接伪造POST请求,提交任意uid和email参数;
  2. 缺少身份验证:未验证请求者是否为该用户本人,仅校验uid和email匹配,而uid和email可通过其他途径获取(如会员列表、文章作者信息);
  3. 参数未过滤:uid参数未进行intval强转,存在SQL注入风险(虽本漏洞核心为密码重置,但可被连带利用)。

三、修复方法(原位修复,不升级、不影响模板)

本修复方案通过添加token校验、身份验证、参数过滤,彻底封堵漏洞,不改动网站原有功能,步骤如下:

步骤1:备份漏洞文件

备份 /member/resetpassword.php 文件,避免修改错误导致密码重置功能异常。

步骤2:修改漏洞文件代码

打开 /member/resetpassword.php 文件,替换为以下修复后的代码(保留原有页面样式,仅修改核心逻辑):

复制代码
<?php
session_start(); // 启动会话,用于token校验
if($_POST['submit']){
    // 修复1:添加token校验,防止伪造请求
    $token = $_POST['token'];
    if($token != $_SESSION['reset_token'] || empty($token)){
        echo '非法请求,请刷新页面后重试';
        exit;
    }
    // 修复2:参数过滤,uid强转int,防止SQL注入
    $uid = intval($_POST['uid']);
    $email = addslashes($_POST['email']);
    $newpwd = addslashes($_POST['newpwd']);
    // 修复3:验证请求者身份(需登录后才能重置密码)
    if(empty($_SESSION['mid']) || $_SESSION['mid'] != $uid){
        echo '请登录后重置自己的密码';
        exit;
    }
    // 原有校验逻辑保留,增加安全性
    $row = $dsql->GetOne("SELECT * FROM `#@__member` WHERE mid='$uid' AND email='$email'");
    if($row){
        $newpwd = md5($newpwd);
        $dsql->ExecuteNoneQuery("UPDATE `#@__member` SET pwd='$newpwd' WHERE mid='$uid'");
        // 修复4:重置token,防止重复提交
        unset($_SESSION['reset_token']);
        echo '密码修改成功,请重新登录';
    }else{
        echo '用户ID或邮箱错误';
    }
}else{
    // 生成随机token,用于提交校验
    $token = uniqid(mt_rand(), true);
    $_SESSION['reset_token'] = $token;
    // 原有页面展示代码(保留,不修改)
    // ......(此处保留原文件中的HTML页面代码)
}
?>

步骤3:修改前端提交表单

在 resetpassword.php 的HTML表单中,添加token隐藏字段,确保提交时携带token(找到表单form标签内,添加以下代码):

复制代码
<input type="hidden" name="token" value="<?php echo $_SESSION['reset_token']; ?>" />

步骤4:验证修复效果

  1. 未登录状态下,尝试提交密码重置请求,提示「请登录后重置自己的密码」,修复生效;
  2. 伪造token提交请求,提示「非法请求」,修复生效;
  3. 登录会员后,仅能重置自己的密码,无法修改其他用户密码,修复生效。

四、注意事项

  • 修改后务必测试会员密码重置功能,确保正常用户可重置自己的密码;
  • 若网站开启了会话缓存,需清理缓存,避免token失效;
  • 建议同时修改管理员账号的邮箱,避免攻击者通过邮箱信息构造请求(虽修复后已无法利用,但可进一步提升安全性)。

本文由 流觞运维 整理,https://www.lnmpweb.cn/archives/7481

相关推荐
niucloud-admin5 小时前
PHP V6 单商户常见问题——如何修改访问域名默认跳转端口
php
catchadmin5 小时前
使用 PHP TrueAsync 改造 Laravel 协程异步化的可行路径
开发语言·php·laravel
郑州光合科技余经理6 小时前
同城O2O海外版二次开发实战:从支付网关到配送算法
开发语言·前端·后端·算法·架构·uni-app·php
niucloud-admin7 小时前
PHP V6 单商户常见问题——在线升级版本失败后如何回退版本数据
php
0xR3lativ1ty8 小时前
关闭公网IP的两种方式
网络协议·tcp/ip·php
白晨并不是很能熬夜9 小时前
【PRC】第 2 篇:Netty 通信层 — NIO 模型 + 自定义协议 + 心跳
java·开发语言·后端·面试·rpc·php·nio
2401_8734794010 小时前
固件升级如何按地区分批推送?IP地址查询定位决定升级策略
网络协议·tcp/ip·php
阿桂有点桂13 小时前
Laravel队列,使用redis驱动器
php·laravel
淘矿人14 小时前
2026年4月-DeepSeek V4 vs GPT-5.5深度对比测评:weelinking一键切换实测
服务器·数据库·人工智能·python·gpt·学习·php
森总202015 小时前
如何优雅处理 DB 事务提交后的不可控后置逻辑?记一次订单流程的架构重构
php