深夜2点,服务器报警邮件如催命符般涌入,我盯着后台那一串不认识的PHP文件,冷汗顺着脊背往下淌——这是第四次被挂马了,作为织梦CMS的运维者,你迟早会面对这样的场景:网页突然跳转到赌博网站,或者莫名其妙多出几个诡异的后台管理员账号。
挂马后的外科手术——清理与恢复
别慌,用Xshell连上服务器,第一步是切断“感染源”,立即修改FTP和数据库密码,并在服务器安全组中临时关闭非必要端口(如21、3306),然后下载最新版织梦CMS的完整包,不要直接覆盖——很多马会藏在核心文件里。
织梦CMS安全运维实战,从应急清理到全站迁移的硬核指南
执行命令:
find /www -name "*.php" -mtime -7
查找最近7天被修改的PHP文件,重点关注/include、/plus、/data目录,用diff命令比对官方同版本文件:
diff /www/include/common.inc.php /backup/clean/common.inc.php
发现差异处往往是后门代码,常见特征为:eval($_POST[)、base64_decode、@assert,用vim直接删除可疑行,但别急着清空——先备份到/tmp/malware_sample.zip供后续分析。
最阴险的马会藏在/data/tplcache模板缓存文件里,执行grep -r "base64_decode\|eval\|include_once.*\.php" /www/data/tplcache/,把命中的文件全部删除,然后重启PHP-FPM,如果权限允许,直接chmod 444核心PHP文件(如dede/config.php),让马没有写入权限。
数据库清理:登录phpMyAdmin,执行:
SELECT * FROM `dede_plus` WHERE `aid` > 0 AND `body` LIKE '%<script%‘
找出所有被注入的恶意脚本字段,用UPDATE语句清空,别忘了查dede_admin表——如果密码被改,直接UPDATE dede_admin SET pwd=MD5('新密码')重置。
后台路径的“隐形斗篷”
默认/dede路径就像在门上贴了“快来黑我”的条幅,修改方法分三步:
- 改名目录:SSH执行
mv /www/dede /www/secretAdmin523(越不像系统目录越好)。 - 修改入口文件:用sed替换
/www/secretAdmin523/index.php中的路径常亮,比如将define('DEDEINC', '/dede/include')改为define('DEDEINC', '/secretAdmin523/include')。 - 修复系统文件:全局搜索旧路径——
grep -r "dede" /www | grep -v ".svn\|.git"
把/www/include/common.inc.php、/www/plus/等文件中的硬编码路径一并替换,终极技巧:在.htaccess中添加RewriteRule ^secretAdmin523(.*)$ /dede/$1 [L],攻守兼备。
文件权限的“铁桶阵”
教条式地给所有文件777是自取灭亡,正确姿势:
- 目录:
/data、/html、/uploads给755,属主为www用户。 - 文件:PHP文件644,图片/JS/CSS文件644。
- 特殊目录:
/data/tplcache和/data/cache必须设为555(可读可执行不可写)。 - 核心防御:
chattr +i /www/dede/config.php——加Immutable属性后,连root都不能删改,要修改时用chattr -i解锁,使用find /www -type f -perm 777扫描越权文件,一条条chmod 644。
整站搬家的“无损手术”
迁移前必须做的事:打包上传目录时排除缓存。
tar -czf /backup/site_$(date +%Y%m%d).tar.gz --exclude='/www/data/tplcache' --exclude='/www/data/cache' /www
在新服务器还原时,注意:
- 保持web根目录路径一致(如
/www),否则所有URL链接都会404。 - 用
rsync -avz --delete /www/ root@新IP:/www/同步数据库外的全部文件,再单独导入SQL。 - 执行SQL替换:
UPDATE `dede_archives` SET `litpic` = REPLACE(litpic,'旧域名','新域名'); UPDATE `dede_addonarticle` SET `body` = REPLACE(body,'旧域名','新域名'); UPDATE `dede_feedback` SET `msg` = REPLACE(msg,'旧域名','新域名');
这步漏了,首页图片会显示旧服务器地址,等于告诉别人你搬家了。
域名更换后的“断骨重接”
不仅是URL替换,绝对路径也要改。
在/www/include/config.php中,修改$cfg_basehost为新域名,然后全站搜索旧域名:
grep -r “旧域名” /www | grep “.php”
大概率是data/inc/***.inc文件,直接vim全局替换,如果系统里用了getCurl等外部请求函数,必须检查/include/functions.php中的URL拼接逻辑——很多人在模板里直接写死了域名,最后在nginx配置中加入:
rewrite ^/旧域名/?(.*) /新域名/$1 permanent;
避免旧链接404。
数据库的“断舍离”
备份要自动化:
mysqldump -u root -p密码 --opt --where=”1=1 limit 1000” dedecmsdb > /backup/db_$(date +%Y%m%d).sql
核心技巧:用--opt加速导出,--where分片备份防止大库卡死,恢复时用mysql -u root -p密码 dedecmsdb < /backup/db_20231101.sql,经常遇到table already exists错误?加--replace参数覆盖,遇到字符集乱码,备份前执行SET NAMES utf8mb4;。
真正的安全运维从不是一次性操作,而是构建可重复的自动化流程,当你把上述步骤写成crontab脚本、把核心文件的Immutable属性写进启动脚本时,才能从挂马后的恐慌中彻底解放,毕竟,一个连运维工程师都记不住步骤的防御体系,本身就留着一扇虚掩的门。



发表评论