冰蝎 4.0 流量检测实战:从密钥协商到 10 个可落地特征
原创
炫彩之星
炫彩之星
菜鸟学安全
2026年11月2日 08:30
广东
去阅读
前年做应急响应的时候,碰到过一台失陷主机,告警里没有一条能直接定位后门——因为通信全走加密。翻流量的时候想起冰蝎:这款 Java 写的加密 Webshell 客户端,这几年在红队工具箱里几乎人手一个。它把交互流量做对称加密,密钥由随机数动态生成,WAF 和 IDS 拆开包看到的确实只有密文。
但换个角度想:内容加密了,行为是加密不掉的。一个工具要干活,就得握手、就得发请求、就得维持连接,这些都写在 HTTP 层和 TCP 层,藏不住。
于是我拿冰蝎 4.0 连着 shell 抓了一轮包,逐条对比正常业务流量,整理出下面 10 个能落地的检测点。每条都交代\"包里长什么样\"和\"规则怎么写\",照着做就能上设备。
一、先交代背景
冰蝎(Behinder)是动态二进制加密网站管理客户端,定位和当年的中国菜刀一样,但走的是全加密路线:payload 加密传输、密钥会话级随机生成,传统基于特征串的检测手段基本失效。也正因为\"加密万能\"的惯性,它的一些实现细节反而没怎么变过——这就是本文的切入点。
4.0 版相对 3.x 有两个对检测影响很大的变化:通信协议不再硬编码、可以完全自定义;支持 Java Agent 无文件落地注入内存马。检测门槛确实更高了,但默认配置下它依旧会露出下面这些马脚。
二、通信过程:两个阶段
冰蝎的会话分两步走。第一步协商密钥:客户端先发一个普通 HTTP 请求要密钥,服务端拿随机数的 MD5 取高 16 位当密钥,写进 SESSION 存起来,再原样返回给客户端。
第二步加密传输:客户端把要执行的命令用 AES(或 XOR)加密后 POST 过去,服务端解密、执行、把结果再加密回传。从第二步开始,包体里就全是密文了——所以检测的主战场不在包体,而在握手残留和外围行为上。
三、10 个检测点
1. Accept 头:伪装成 AJAX 请求
实测包里固定带:
Accept: application/json, text/javascript, */*; q=0.01
这是冰蝎在模仿前端 AJAX 调用,但绝大多数真实业务的 Accept 组合和它并不一致,可以做成中等强度的匹配条件。
写 snort/ids 规则时注意用 file_data:它的作用类似 http_server_body,区别是 file_data 之后的所有 content 都必须在响应体里匹配,适合校验\"密文形态\"的 body。
2. Content-Type:一个弱信号
请求头里是:
Content-type: Application/x-www-form-urlencoded
注意这里有个细节:实测抓到的是大写 A 开头,正常浏览器和主流框架发出的是全小写,这个大小写差异本身就可以作为加分项。单独拿它告警误报太多,只适合做组合条件。
3. User-Agent:十选一的假身份
冰蝎内置了 10 个浏览器 UA,每次连 shell 随机抽一个用,想靠 UA 黑名单直接打死它不现实。
但它的 UA 池是固定的。规则上可以反向操作:正常流量千变万化,而这 10 个 UA 如果配合其他可疑特征同时出现,命中率就上来了。写法上记得给这组 content 加 fast_pattern,让引擎优先匹配短串,别把性能浪费在长 UA 上。
4. 本地端口:javaw 的小习惯
抓包时注意到一个 TCP 层的行为:冰蝎建立连接时,客户端侧的 javaw 进程发起的连接,本地端口集中在 49700 附近,每新建一条连接端口号依次递增。
这个特征发生在攻击者机器上,对防守方价值有限,但做溯源反查时很有用——流量回溯时看到这个端口段的 javaw 连接,基本可以断定对面挂着冰蝎。
5. PHP 服务端的固定代码
PHP webshell 解密后执行的代码是死的:
$post=Decrypt(file_get_contents(\"php://input\"));
eval($post);
如果目标做过主机侧检测,eval($post) 这个组合可以直接进静态特征库;流量侧虽然看不到明文,解密后的报文比对时也用得上。
6. 长连接:省出来的特征
冰蝎为了避免反复握手的开销,默认全程走长连接,请求和响应头里都会带:
Connection: Keep-Alive
Keep-Alive 本身太常见,单拎出来毫无意义,但\"POST 密文体 + Keep-Alive + 上面的 Accept 组合\"同时命中,可疑度就很高了。
7. 最硬的特征:固定的请求/响应字节头
这是整篇文章里含金量最高的一条。默认密钥下,冰蝎的密文有固定前缀——
请求字节头:
dFAXQV1LORcHRQtLRlwMAhwFTAg/M
响应字节头:
TxcWR1NNExZAD0ZaAWMIPAZjH1BFBFtHThcJSlUXWEd
拿这两个前缀直接做流量匹配即可。我们验证过解密流程:把密文按 webshell 里的加解密逻辑逆向处理,再 base64 解码,就能还原出列目录这样的操作指令——
8. 默认密钥:没改密码就等于明牌
所有冰蝎 4.0 默认 webshell 里都带着同一串密钥:e45e329feb5d925b。它是默认连接密码 rebeyond 的 32 位 MD5 前 16 位。
检测这串值出现在流量或文件里基本就是实锤。反过来这也是运营建议:真要用工具做授权测试,记得改默认密码。
9. webshell 文件本身的样子
JSP 和 PHP 的 shell 各有固定代码骨架,主机侧查文件时直接对特征:
10. 请求时序:固定的一来一回
还有一个容易被忽略的行为:每次发起连接,冰蝎会连发两个 HTTP 请求。默认密钥下,所有响应头一模一样,第二次的请求头有点特殊,其余请求头全部相同。
另外冰蝎可以自定义连接密码(本地和远程加解密函数里都保存 $key 即可)。改了密码之后,初始字符串被新密钥加密,请求/响应头都会变,上面第 7 条的固定字节头就失效了——除非针对 shell 里的 $key 动态改写解密函数,才能还原出不变的报文头。
两次请求解出来分别是:
dFAXQV1LORcHRQtLRlwMAhwFTAg/M
@error_reporting(0);\\r
OT8AQUBWFDoQUBRWQEELC1MdVRoJNGwDF1sHTVtaDEVZVAxdGh0RDQNBAU9X
error_reporting(0);\\r
写在最后
把 10 条收拢成一句话:弱信号打组合,强信号打单发。Accept、Content-Type、Keep-Alive、端口段这类弱特征单独看都是噪音,串起来才有意义;固定字节头、默认密钥、eval($post) 这三条命中即可高置信告警。
还要留个心眼:4.0 支持自定义协议,攻击者一旦换掉默认报文,第 7 条就哑火。所以特征库不是写完就完,每次工具更新都值得重新抓包核对一遍。你有什么实测中发现的其他冰蝎特征,欢迎留言补充。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。







评论