一、漏洞说明
该漏洞属于后台中高危恶意恢复漏洞,影响DedeCMS全版本,攻击者登录后台后,可利用数据库恢复功能,上传恶意数据库备份文件(含恶意SQL语句),恢复后篡改数据库(如修改管理员密码、植入恶意内容、删除网站数据),导致网站瘫痪、后台被控制,危害极大。
- 漏洞类型:恶意恢复、数据库篡改
- 危害等级:中高危
- 影响版本:DedeCMS 全版本(含V5.7 SP2 ~ 5.7.118及衍生版本)
- 漏洞文件:/dede/database_restore.php
- 漏洞场景:后台数据库恢复功能中,程序未对上传的备份文件进行合法性校验,未限制备份文件的来源和内容,攻击者可上传含恶意SQL语句的备份文件,恢复后篡改数据库,获取后台控制权。
二、代码分析
漏洞核心原因:database_restore.php 文件中,后台数据库恢复功能未对上传的备份文件进行合法性校验,未过滤备份文件中的恶意SQL语句,未限制备份文件的格式和来源,攻击者可上传含恶意SQL的备份文件,恢复后执行恶意语句,篡改数据库。
关键漏洞代码(原文件片段):
<?php
// 原漏洞代码(后台数据库恢复逻辑,存在恶意恢复漏洞)
require_once(dirname(__FILE__)."/config.php");
$file = $_FILES['backupFile'];
$filename = $file['tmp_name'];
// 未校验备份文件合法性,直接读取并执行SQL
$fp = fopen($filename, 'r');
$sql = fread($fp, filesize($filename));
fclose($fp);
$dsql->ExecuteNoneQuery($sql);
echo '数据库恢复成功';
?>
代码问题分析:
- 未校验文件合法性:未校验上传的文件是否为合法的数据库备份文件(.sql格式),允许上传任意格式文件;
- 未过滤恶意SQL:未过滤备份文件中的恶意SQL语句(如 UPDATE、DELETE、DROP),直接执行文件中的所有SQL;
- 无权限校验:未对数据库恢复权限进行细分,普通管理员也可执行恢复操作,扩大漏洞利用范围;
- 无文件大小限制:未限制上传的备份文件大小,允许上传大型恶意备份文件;
- 无操作日志:未记录数据库恢复操作,出现数据库被篡改后无法追溯。
漏洞利用示例(仅用于学习,请勿非法测试):
// 1. 构造恶意备份文件(.sql格式),写入恶意SQL语句:UPDATE `#@__admin` SET pwd=’md5加密密码’ WHERE id=1;
// 2. 普通管理员登录后台,访问数据库恢复页面,上传该恶意备份文件;
// 3. 点击恢复,恶意SQL语句被执行,超级管理员密码被篡改;
// 4. 攻击者使用篡改后的密码登录超级管理员账号,获取后台控制权,进一步篡改数据库。
三、修复方法(原位修复,不升级、不影响模板)
本修复方案无需升级DedeCMS版本,仅修改database_restore.php文件,通过校验文件合法性、过滤恶意SQL、添加权限校验,封堵恶意恢复漏洞,不影响正常数据库恢复功能,步骤如下:
步骤1:备份漏洞文件
备份 /dede/database_restore.php 文件,备份路径示例:/dede/database_restore.php.bak,避免修改错误导致后台数据库恢复功能异常,便于后续回滚操作。
步骤2:核心修复(文件校验+SQL过滤+权限管控)
打开 /dede/database_restore.php 文件,替换为以下修复后的代码,核心是校验备份文件合法性、过滤恶意SQL语句、添加权限校验和操作日志:
<?php
require_once(dirname(__FILE__)."/config.php");
// 修复1:添加权限校验,仅允许超级管理员执行数据库恢复操作
if($cuserLogin->getUserType() != 1){
exit('无权限操作,请联系超级管理员');
}
// 修复2:校验上传文件合法性,仅允许.sql格式备份文件
$file = $_FILES['backupFile'];
if(empty($file['name']) || $file['error'] != 0){
exit('请上传合法的数据库备份文件');
}
// 校验文件格式(仅允许.sql后缀)
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
if(strtolower($ext) != 'sql'){
exit('仅允许上传.sql格式的数据库备份文件');
}
// 校验文件大小(限制最大50M,可根据实际调整)
$maxSize = 50 * 1024 * 1024; // 50M
if($file['size'] > $maxSize){
exit('备份文件过大,最大支持50M');
}
$filename = $file['tmp_name'];
// 修复3:读取备份文件,过滤恶意SQL语句
$fp = fopen($filename, 'r');
$sql = fread($fp, filesize($filename));
fclose($fp);
// 禁止执行的恶意SQL语句(可根据实际补充)
$forbidSql = array('DROP TABLE', 'DROP DATABASE', 'UPDATE `#@__admin`', 'DELETE FROM `#@__arctype`', 'TRUNCATE TABLE');
foreach($forbidSql as $forbid){
if(strpos(strtoupper($sql), strtoupper($forbid)) !== false){
exit('备份文件包含恶意SQL语句,禁止恢复');
}
}
// 修复4:获取当前登录管理员信息,添加操作日志
$currentAdmin = $cuserLogin->getUserInfo();
$adminName = $currentAdmin['adminname'];
$backupFileName = addslashes($file['name']);
$logContent = "管理员【$adminName】于".date('Y-m-d H:i:s')."上传并恢复数据库备份,文件名:$backupFileName";
$dsql->ExecuteNoneQuery("INSERT INTO `#@__admin_log` (adminname, action, logtime, content) VALUES ('$adminName', 'database_restore', ".time().", '$logContent')");
// 保留原有恢复逻辑,确保正常恢复功能
$dsql->ExecuteNoneQuery($sql);
echo '数据库恢复成功';
?>
步骤3:额外加固(可选,提升安全性)
- 限制备份文件来源:仅允许上传本地备份文件,禁止从远程URL获取备份文件,防止远程恶意文件注入;
- 添加备份文件校验码:备份数据库时生成校验码,恢复时校验文件校验码,确保备份文件未被篡改;
- 定期备份数据库:定期自动备份数据库,存储在安全目录,若出现恶意恢复,可及时恢复正常数据;
- 限制恢复频率:禁止短时间内多次执行恢复操作,防止攻击者快速尝试恶意恢复。
步骤4:验证修复效果
- 恶意文件测试:上传非.sql格式文件(如.txt、.php),提示「仅允许上传.sql格式」,修复生效;
- 恶意SQL测试:上传含DROP、UPDATE管理员表等恶意SQL的.sql文件,提示「包含恶意SQL语句」,修复生效;
- 低权限测试:使用非超级管理员账号尝试恢复,提示「无权限操作」,修复生效;
- 正常恢复测试:上传合法.sql备份文件,可正常恢复,说明功能未受影响;
- 日志测试:查看后台操作日志,可看到数据库恢复操作记录,修复生效。
四、注意事项
- 该漏洞危害极大,可直接导致数据库被篡改、后台被控制,修复后务必全面测试,确保恶意恢复漏洞被彻底封堵;
- 若网站需要执行UPDATE、DELETE等操作的备份文件,可在forbidSql数组中临时删除对应限制,操作完成后及时恢复;
- 修复后需测试正常数据库备份和恢复功能,确保不影响网站数据备份需求;
- 定期查看数据库恢复操作日志,排查异常恢复记录,若发现可疑操作,及时检查数据库是否被篡改;
- 若修复后出现恢复失败、文件无法上传的情况,可恢复备份文件,检查代码修改是否有误,或联系技术人员协助排查。
本文由 流觞运维 原创整理,如需 DedeCMS 该漏洞代修复、全站点漏洞扫描、安全加固、挂马清理服务,可联系微信:lnmp_wuyi(备注:dede修复)。