凌晨三点,告警短信炸醒你的原因
你刚入职某企业担任网站运维的第二周,凌晨三点被连续12条“网站自动生成异常内容”的告警短信惊醒,打开浏览器,你看到织梦CMS后台“内容自动生成”功能正疯狂生成数万个带有赌博推广链接的HTML页面——服务器CPU飙到95%,数据库表增长了2GB,首页被篡改成黑色背景的“澳门最大赌场”广告页。
“上次运维离职时说这站没问题啊……”你一边骂骂咧咧,一边登录SSH,在50个异常进程中抓到三个可疑的:/tmp/.systemd、/var/tmp/.httpdcron、和一个伪装成mysql.png的实际是ELF二进制文件的恶意程序,更可怕的是,自动生成内容的触发器已经被修改为每60秒执行一次,垃圾页面正以每秒17条的速度产生。
第一步:应急断网与现场保全(挂马后清理恢复)
别急着删文件,先止血。 立即执行以下四步:
-
切断对外服务
执行iptables -A INPUT -p tcp --dport 80 -j DROP,或者直接在云服务商面板关闭80/443端口,同时停止Nginx/Apache:systemctl stop nginx && systemctl stop php-fpm。织梦CMS自动更新触发机制下的安全运维实战手册
-
创建内存快照
ps aux --sort=-%cpu > /tmp/ps_snapshot_$(date +%Y%m%d%H%M).txt netstat -antp > /tmp/netstat_snapshot.txt ls -la /proc/$(pgrep -f "可疑进程名")/exe
用
lsof +L1找出正在被删除但进程仍在使用的文件,这些往往是木马的影子文件。 -
数据库紧急锁定
登录MySQL,执行:FLUSH TABLES WITH READ LOCK; SET GLOBAL general_log = OFF;
备份general_log表内容(可能记录了攻击者操作痕迹),然后直接
mysqldump -u root -p --all-databases > /root/emergency_bak.sql。 -
清除自动生成任务的侵入点
攻击者通常修改了织梦的/plus/task.php、/include/helpers/archive.helper.php或/dede/sys_task.php,对比原始安装包:diff -r /www/dede_original/plus /www/web/plus | grep "<?php"
找到被插入的恶意代码,通常是eval(base64_decode(...))或file_put_contents形式的后门,替换为官方原始文件后,再删除
/data/tplcache/下的所有文件。
第二步:后台路径修改与安全加固(防复发)
攻击者是通过扫后台路径/dede/进入的,现在你必须在搜索引擎疯狂收录垃圾页面前完成改造:
-
修改后台登录目录
mv /www/web/dede /www/web/your_custom_admin_folder_name
然后修改
/www/web/data/common.inc.php:$cfg_admin_dir = '/your_custom_admin_folder_name'; $cfg_cookie_encode = '一个随机32位字符串';
-
禁用自动更新触发器
在/www/web/dede/sys_task.php(注意是旧路径,新路径已改名)中,找到任务循环部分,注释掉:// $dsql->ExecuteNoneQuery("UPDATE #@__sys_task SET exectime='".time()."' WHERE id='$row['id']'");同时删除
/data/task/cron_*.php所有文件。 -
设置路径访问白名单
在Nginx配置中添加:location /your_custom_admin_folder_name { allow 你的公司出口IP段; deny all; auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd; }
第三步:文件权限的铜墙铁壁(最低权限原则)
织梦的“万能目录权限”是灾难根源,现在动手:
-
可写目录最小化
chmod 755 /www/web -R chmod 755 /www/web/uploads chmod 755 /www/web/data chmod 755 /www/web/a chmod 644 /www/web/index.php find /www/web -type f -name "*.php" -exec chmod 444 {} \; -
禁止上传目录执行PHP
在/www/web/uploads/.htaccess中写入:<FilesMatch "\.php$"> Order Deny,Allow Deny from all </FilesMatch>Nginx环境则在配置中加:
location ~* /uploads/.*\.php$ { deny all; } -
data目录单独加固
织梦的/data/目录常被写入缓存后门,最好将其移出Web根目录:mv /www/web/data /www/data_store ln -s /www/data_store /www/web/data
然后修改
/www/web/data/common.inc.php中所有../data/路径为绝对路径。
第四步:整站搬家完整流程(域名更换+数据迁移)
如果你因为被黑了决定换服务器,或者换域名,必须严格按顺序操作:
-
打包前的清理
# 删除织梦缓存、临时文件、日志 rm -rf /www/web/data/tplcache/* rm -rf /www/web/data/rss/* rm -rf /www/web/data/admin_subdomains/*.php rm -f /www/web/a/*.html(或保留你需要的主页)
-
全站打包
tar -czf /backup/dede_site_$(date +%Y%m%d).tar.gz /www/web --exclude=/www/web/uploads/security/*.bak
-
数据库完整导出
mysqldump -u root -p --opt --routines --triggers --events --hex-blob dedecms > /backup/db_full.sql
-
在新服务器恢复
假设新服务器IP是192.168.1.100,数据库密码已改:mkdir /www/web && tar -xzf /backup/dede_site_*.tar.gz -C / mysql -u root -p dedecms < /backup/db_full.sql
-
域名更换后的数据替换
如果旧域名是old.com,新域名是new.com,跑以下三条SQL:UPDATE dede_addonarticle SET body = REPLACE(body,'old.com','new.com'); UPDATE dede_arctype SET typedir = REPLACE(typedir,'old.com','new.com'); UPDATE dede_archives SET redirecturl = REPLACE(redirecturl,'old.com','new.com');
然后修改
/www/web/data/common.inc.php中的$cfg_basehost和$cfg_cmspath。
第五步:数据库备份与恢复的防呆操作
很多新手备份只导结构不导数据,这里教你正确操作:
-
全量备份
mysqldump -u root -p --single-transaction --quick --lock-tables=false --routines --triggers dedecms | gzip > /backup/db_$(date +%Y%m%d).sql.gz
-
增量备份(利用二进制日志)
先开启binlog:[mysqld] log-bin=mysql-bin expire_logs_days=7
恢复时:
mysqlbinlog --start-datetime="2023-03-15 08:00:00" --stop-datetime="2023-03-15 09:00:00" /var/lib/mysql/mysql-bin.000001 | mysql -u root -p dedecms
-
恢复时必做验证
# 恢复前先检查表完整性 mysqlcheck -u root -p --all-databases --auto-repair # 然后导入 gunzip < /backup/db_20250315.sql.gz | mysql -u root -p dedecms # 恢复后重建索引 mysql -u root -p dedecms -e "REPAIR TABLE dede_archives, dede_arctype; OPTIMIZE TABLE dede_addonarticle;"
如果你的织梦站点能熬过今天这波操作,再过24小时你还活着,记得给服务器装个基于文件哈希值的入侵检测系统(比如AIDE或Tripwire),以及把自动更新内容的时间间隔从60秒强制改为动态验证码触发——这是你今晚用命换来的经验。



发表评论