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

相关推荐
两个人的幸福8 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo11 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack11 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820711 天前
PHP 扩展——从入门到理解
php
鹏仔先生12 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下12 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip12 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒12 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25012 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis12 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel