☰
Webshell流量分析实战:从可疑HTTP请求还原完整攻击链
2026/10/19 8:02:49 网站建设 项目流程

webshell流量分析这个系列,我一直认为是安全运营人员最值得反复磨的基本功之一。Practice2这道题拿到手之后,我第一反应是"又来"——毕竟第一道题已经让我在密密麻麻的数据包里翻了半天。但真正做下来才发现,这一道比上一道的乐趣要足得多,因为它不再是单纯地"找一个可疑请求"那么简单,而是要把攻击者的整个行为链从流量里完整还原出来。这篇文章就按我实际的分析过程,一步步和你拆开讲清楚。

这道题非常适合刚接触Web安全流量分析的人来练手,尤其是已经掌握Wireshark基本操作、但不太清楚"恶意流量到底长什么样"的读者。如果你做过第一道Practice题,你会发现这道的难度曲线是往上走的,但它又不至于让你无从下手——只要思路对,答案就藏在那些看似普通的HTTP请求里面。

1. 先说清楚:Practice2到底想考你什么

1.1 从题目设计反推考点

做过安全类实操题的人都知道,题目不会平白无故给你一个流量包。Practice2之所以被放在"练习二"的位置,说明出题人默认你已经具备了一些基础能力:会用Wireshark、看得懂HTTP协议的基本结构、知道什么是请求行、请求头和请求体。在这个基础上,这道题主要想考察三个方面。

第一是对Webshell通信特征的敏感度。Webshell说白了就是攻击者上传到服务器上的一个恶意脚本,服务器执行它之后,攻击者通过HTTP请求来操控这台服务器。这个"操控"的过程必然会在流量里留下痕迹,关键是你能不能从一票正常的请求里把它挑出来。

第二是对编码和加密数据的处理能力。实战中的Webshell通信几乎不会明文传输命令,有的用Base64,有的用十六进制,再进阶一点的直接上AES加密。这道练习里出现的编码方式不算复杂,但如果你平时没练过解码,很容易卡在"找到了可疑请求但不知道它在干嘛"这一步。

第三是多维度信息串联的能力。单看一条请求,你可能只看到一个奇怪的文件名和一堆乱码参数;但把时间线、IP会话、请求频率、响应长度摆在一起,整个攻击路径就清晰了。这也是蓝队分析流量和CTF解题最大的区别——前者需要还原事件全貌,后者往往只需要定位一个flag点。

1.2 和上一道练习的衔接

如果做过Practice1,你会发现那道题更偏向"基础定位",比如找到扫描器IP、识别一次暴力破解尝试。而Practice2直接把场景拉到了"服务器已经被攻破,攻击者正在通过Webshell做后续操作"这个阶段。这两道题拼起来,其实是一条完整的攻击链:侦察 → 漏洞利用 → 权限维持 → 内网行动。

这种设计思路我很喜欢,它逼着你用"事件调查"的眼光去看流量包,而不是单纯地在一个个数据包里翻flag。所以你在分析Practice2的时候,脑子里要始终带着一个疑问:如果这是真实环境中的一起安全事件,攻击者用Webshell做了什么?带着这个问题去分析,比漫无目的地翻包高效得多。

2. 流量包到手,先别急着翻:全局摸底才是第一步

2.1 用统计视图快速建立整体认知

不少新手拿到pcap文件之后,第一件事就是噼里啪啦输入一堆过滤表达式,结果看到满屏的数据包瞬间懵了。我的习惯恰恰相反——先打开Wireshark的统计功能,花两分钟搞清楚"这包流量是什么时间段内的、涉及哪些主机、跑的是什么协议"。

Wireshark菜单栏里的Statistics是一套非常实用的组合拳。先看一眼Protocol Hierarchy,了解流量包里的协议分布。正常情况下的HTTP、TCP、DNS占比是一目了然的,如果出现大量你预期之外的协议类型,比如某种很少见的应用层协议,那本身就值得警惕。

接着看Conversations和Endpoints,分别按对话和端点统计流量。这两个表会给你一个非常直观的印象:谁和谁在通信,通信了多久,交换了多少字节。在Webshell分析这个场景里,你通常会在Endpoint表里看到一个不太正常的组合——比如一个内网IP和一个外网IP之间有持续的小流量交互,单次请求不大,但频率很稳定,时间跨度从流量包的前段一直延续到后段。这种"小流量+长周期+固定对端"的模式,天然就是Webshell控制通信的典型画像。

2.2 按照先听后看的原则过滤HTTP

流量包如果是用tcpdump或者类似工具抓的,通常会有不少TCP协商包、重传包,甚至可能混着DNS和ARP请求。在正式开始分析之前,先把视角收敛到HTTP层。我最常用的两个过滤表达式是http和http.request,前者展示所有HTTP相关包,后者只看HTTP请求包,过滤掉响应包,让视图更干净。

有人可能会问:为什么不直接看tcp.port == 80?这个过滤条件当然也行,但不够精确——HTTP完全可以跑在非80端口上,尤其是这类练习流量包里,经常故意把Web服务放在8080或者某个随机高位端口上,就为了考验你有没有死盯着80端口。用http.request的好处是,它关注的是协议本身而非端口,只要流量里存在HTTP请求,不管端口多少都会被过滤出来。

我第一次做这道题的时候就是吃了端口思维的亏,傻乎乎地在80端口翻了十分钟没找到东西,后来切到http.request才恍然大悟。所以这里给新手一个建议:先按协议维度过滤,再按端口维度过滤,顺序反了很容易把自己绕进去。

3. 锁定可疑请求:Webshell流量的三个典型特征

3.1 从URI结构判断文件类型

全局摸底完成之后,接下来才是重头戏——把可疑的HTTP请求从正常流量里摘出来。在http.request过滤条件下,你会看到一串请求列表。正常的业务请求长什么样?无非是/index.php、/api/login、/assets/js/main.js这种,路径语义清晰,文件名和功能一一对应。

而Webshell请求的URI,怎么看怎么别扭。这道题里最显眼的一个畸形URI出现在某条POST请求上,路径指向一个后台目录下的PHP文件,文件名是由几个随机字母和数字拼接而成的,完全不具备可读性。比如正常的后台文件可能叫config.php、upload.php,它偏要叫x9k2.php。这种命名规律,说明文件不是业务代码里原生存在的,极有可能是攻击者通过文件上传漏洞传上去的脚本。

另一个观察点是请求方法分布。Webshell的交互操作大多数是POST请求,因为攻击者要把命令参数塞进请求体里,GET请求的长度限制摆在那儿,塞不了太多内容。你可以用http.request.method == "POST"过滤出所有POST请求,数量通常不会太多,再逐一排查。正常业务里POST请求也有不少,但它们的URI往往集中在固定的几个业务路径上,像x9k2.php这种孤立无援的POST目标,基本可以判定为"非正常人类行为"。

3.2 请求参数里的工具指纹

看到可疑的URI之后,接下来的操作非常关键:点开这一条POST请求,仔细看请求体里的参数内容。Webshell类恶意流量的精髓就在请求参数里,因为攻击者的命令、服务器回显的数据,全都编码藏在这里。

这道题里,请求体是一串param1=xxx&param2=yyy格式的键值对,但xxx和yyy的值都是Base64编码的字符串。Base64编码的典型特征是字符串只包含大小写字母、数字以及+、/、=这几个字符。你在Wireshark的报文详情面板里看到这种结构时,基本可以判定这条请求有猫腻。

更进一步的判断是编码内容解码之后的格式。如果你在本地用Python或者命令行的base64 -d解码,看到的内容是以@开头的字符串,那么恭喜你,这就是一个非常经典的Webshell连接特征。@加一串字符在PHP语境里是assert加参数的变体写法,这类模式常出现在用中国蚁剑生成的连接流量中。蚁剑在向Webshell发送命令时,会把要执行的PHP代码片段整体编码后塞进参数,而编码解出来之后必然带着可执行的代码痕迹,这是工具本身的设计逻辑,藏不住的。

3.3 响应包体积与状态码的双重印证

判断一条请求是否可疑,光看请求端还不够,响应端同样是重要线索。你在Wireshark里选中那条POST请求,右键追踪HTTP流,就能把这条交互的请求和响应拼在一起看。

正常的一个静态资源请求,响应体可能是几百字节到几十KB不等;正常的业务接口请求,响应体通常是JSON结构或者一段HTML。而Webshell的响应体,体量上往往与其"请求体"有奇怪的不匹配。比如这里,请求体只有一两百字节,响应体却是一大段Base64编码的数据。这段数据解码之后,实际上是服务器上某个目录的文件列表,或者是某个命令的执行结果。

再看状态码,Webshell通信的响应大多数是200 OK,因为脚本正常执行了,服务器确实是"正常"地给出了结果。如果你看到一个可疑请求的响应是404或者500,反而要思考一下是不是Webshell文件已经被清理掉、或者执行出了错误。

这里特别提醒一点:不要只凭单一字段判断。有些新手看到响应体是Base64就急着下结论,实际上正常的业务也可能用Base64传数据。真正的判断依据,是"请求参数编码 + 响应内容编码 + URI命名异常 + 对端IP可疑"这几个条件叠加之后形成的组合证据。流量分析这件事,单点证据会误判,多点交叉才靠谱。

4. 还原行为链:从一条Webshell请求到一次完整攻击事件

4.1 解码请求,还原攻击者的操作意图

找到Webshell连接请求只是第一步,这道练习的真正难度在于:攻击者通过Webshell做了什么?要回答这个问题,必须把请求里的编码内容全部解出来,逐条还原成可读的命令。

以这个流量包里的一组典型请求为例。某条POST请求的参数经过Base64解码之后,内容是类似system("whoami");的PHP代码片段,说明攻击者在执行系统命令探测当前用户权限。下一条请求的解码结果变成了system("ls -la /var/www/html");,这是在列目录,侦察Web根目录下有哪些文件。再往下翻,还能看到file_put_contents之类的函数出现在解码结果里,这是在尝试往服务器上写文件。

你把这几条请求摆在时间轴上顺序一看,整个行为链就清清楚楚了:攻击者先确认自己拿到的是哪个用户的权限,再查看Web目录里的文件结构,接着可能尝试写入一个额外的文件作为备用后门。这在真实的应急响应里是一个极其常见的Webshell后利用序列——拿到脚本执行权限之后,第一件事永远是"确认身份+查看环境+寻找持久化机会"。

4.2 时间维度上的串联分析

逐条解码是有价值的,但如果你只看单条请求,很容易漏掉攻击者的整体意图。这时候需要把分析视角从"单条报文"拉高到"整段时间线"。

Wireshark的Telephony -> VoIP Calls(或者直接按时间排序)能帮你按时间顺序把所有的HTTP交互列出来。你会发现,这个流量包里,攻击者与Webshell的交互并不是均匀分布的,而是有明显的节奏感:先是一阵密集的请求——每三五秒就有一条,这是攻击者正在执行命令收集信息;然后是一个较长的静默期,期间没有任何交互;接着又是几条密集请求,再静默。这种"爆发-静默-再爆发"的模式,恰恰对应了真实攻击场景里"自动化脚本批量采集"和"人工分析结果后下一步操作"交替进行的特点。

还原时间线还有一个好处:它能帮你排除干扰项。流量包里可能还有其他扫描器产生的噪声,比如大范围的端口扫描请求,这些请求在时间线和行为模式上跟Webshell交互有明显差异——扫描请求通常是少量、高频、机械重复的,而Webshell交互是逐条、有目的、有逻辑递进的。把时间线拉出来,谁是主角谁是噪声,一眼就能分辨。

5. 流量分析工具箱:那些让效率翻倍的实操技巧

5.1 Wireshark里几个高频实用的过滤表达式

在分析完这道练习之后,我把整个过程中最常用的几个过滤表达式整理了出来。这些不是网上抄来的命令,是我在自己的分析流程里真正反复用到的。

首先是按IP过滤:ip.addr == 192.168.1.10,用来锁定某台主机的全部流量,不管是发出去的还是接收的。接着是HTTP方法过滤:http.request.method == "POST",这个前面说过,用来快速筛选出所有POST请求。如果你想看某个IP的所有POST请求,就把这两个拼起来:ip.src == 攻击者IP && http.request.method == "POST"。

还有一个很容易被忽略但非常实用的表达式是http.response.code == 200,配合http.request一起用,可以只看那些成功交互的请求。Webshell连接失败时会产生大量404或500响应,把失败响应过滤掉之后,剩下的就是有效交互,分析起来干净得多。

如果你想把可疑的请求内容原样保存下来,Wireshark的File -> Export Objects -> HTTP是一个好用的功能。它会把流量包里所有HTTP传输的文件对象提取出来,按MIME类型分类。对Webshell分析来说,你可以在提取出的文件里找PHP可执行文件,直接保存到本地看原始内容,比自己对着Hex面板找解码容易太多。

5.2 常见Webshell工具的流量特征速查

练完这道题,我把主流Webshell管理工具的流量特征做了个小小的汇总,方便你在实战中快速对照。这个表只列最关键的特征,因为不同版本的工具可能存在差异,但核心的设计逻辑是稳定的。

常见的几类工具特征如下:最老牌的"菜刀"系列流量特征最明显,请求头中带有固定的User-Agent标识,请求体是Base64编码的PHP代码,且特征字符串非常固定;"蚁剑"的请求体里通常藏着@开头的assert调用模式,参数名以字典顺序排列,响应体往往也是Base64数据;"冰蝎"的特征是通信内容经过AES加密,加密后的数据以Base64形式嵌入POST请求体,单看请求体全是乱码,这是它和明文工具最明显的区别;"哥斯拉"也采用加密通信,但它的请求中会带着固定的Cookie字段,响应内容的加密形式也有特殊标志。

工具通信加密方式最明显的可观察特征
菜刀家族弱编码(Base64)固定UA字符串,编码结构单一
蚁剑编码器体系(Base64/十六进制等)@开头的assert调用模式,多参数名固定
冰蝎AES对称加密POST体为高熵乱码,单次请求体量偏大
哥斯拉自定义加密Cookie字段格式固定,响应数据带特征标记

当然,这个表只能帮你快速建立初步判断,真正要确定工具类型,还需要结合具体的交互流程和编码格式做确认。流量分析里最忌讳的就是"看一眼就下结论",多收集几条证据再判断,误报率会低很多。

6. 常见问题与排查陷阱实录

6.1 加密流量怎么破局

练习做到后半段,有一个情况值得单独拿出来讲:如果流量里的Webshell通信不是简单的Base64编码,而是走了强加密,你该怎么往下走?我在做练习的过程中,故意试了试不依赖服务器密钥的纯流量侧分析方法,过程很痛苦,但结论很值得分享。

面对加密流量,第一选择是看密钥是否在流量里泄露——有些实现会把密钥或者密钥生成因子直接放在某个请求参数里,这时候你只需按图索骥,把密钥捞出来,就能解密后续流量。第二选择是找请求和响应之间的规律,比如有些工具虽然加密了请求体,但响应的某些字段是没有加密的,比如HTTP状态码、内容长度、响应时间,这些metadata在加密流量的加持下依然暴露大量信息。比如攻击者执行ls命令时目录项很多,响应体就长;执行whoami时结果很短,响应体就短。通过这些外部特征,哪怕是加密流量,也能大致猜出攻击者的操作节奏。

6.2 误判与边界情况

Webshell流量分析有一个天然的难点:恶意流量和正常流量的边界在某些场景下非常模糊。比如有的业务系统本身就使用Base64编码传输数据,有的Web应用为了安全会故意对请求参数做二次编码。你在分析时,要把这些因素都考虑进去。

最容易踩的坑是看到Base64就兴奋。BASE64本身是"传输编码"而不是"加密",它解决的只是"把二进制数据变文本"的问题,不是安全问题。所以判断一条请求是不是Webshell交互,必须回到三个核心问题上:这个URI是业务定义的还是凭空出现的?这个请求的触发方式是否符合正常用户的行为逻辑?请求和响应的内容组合是否指向"服务器执行了代码并把结果回传"?三个问题里有至少两个答案是肯定的,才值得把你宝贵的时间花在深挖上。

6.3 我自己踩过的一个坑

最后说一个我在排查中实实在在踩过的坑。有一段时间我分析这种题总是找不到最后一个关键请求,后来发现原因是我一直盯着http.request.method == "POST"过滤,把GET请求完全排除了。但实际上,有的Webshell工具为了让某些操作更隐蔽,会把信息采集类的"轻量"请求伪装成GET,把参数塞在URL的Query String里。

那次之后我调整了自己的分析策略:先按来源IP圈定可疑主机的全部流量,再在这个范围内看请求方法的分布,而不是一开始就用方法过滤把流量给框死。做流量分析一定不能把预设条件卡得太死,要多给自己留一点重新审视的空间。

回到Practice2这道题本身,它最打动我的地方在于,它没有为了出题而出题,而是用一个相对简单的流量包,把Webshell分析的核心方法论完整地过了一遍。做完之后,你再回头去看真实的恶意流量,脑子里就不只是"这包有问题"的模糊感觉,而是"这里编码异常、那里响应不匹配、再加上时间线行为可疑、综合判断是XX工具"的清晰逻辑链。这种分析思维的建立,比多解出几道题重要得多。多练几次你会发现,Webshell流量其实是藏不住的——它要么在URI上露馅,要么在参数里漏形,要么在交互模式上露出马脚。关键是你愿不愿意沉下心来,一条一条把证据链串起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询