1. 项目概述:一次典型的企业安全实战
最近在内部安全巡检和响应外部威胁情报时,我们团队处理了好几起围绕致远M3 Server的Fastjson反序列化漏洞的应急事件。这个组合在近期的企业安全攻防演练和真实攻击中,曝光率相当高。对于企业安全运维团队来说,这已经不是一个陌生的名词,而是一个必须掌握处置流程的“必修课”。简单来说,这个漏洞的核心在于,攻击者可以通过构造特定的恶意JSON数据,发送给使用了存在漏洞的Fastjson版本进行数据解析的致远M3 Server应用,从而触发反序列化过程,最终在服务器上执行任意代码,实现远程控制。
这听起来很技术化,但我们可以把它想象成一个“特洛伊木马”。你的应用(致远M3 Server)有一个信任的“城门守卫”(Fastjson库),负责检查进城的“货物”(JSON数据)。但这个守卫(特定版本的Fastjson)存在一个致命的识别漏洞,它无法分辨伪装成普通货物的“木马”(恶意构造的JSON)。一旦木马进城,它就能在城内(服务器上)为所欲为。对于企业而言,这意味着核心的业务系统、敏感的客户数据、内部通讯信息都可能面临被窃取、篡改甚至服务中断的风险。
因此,快速、准确地检测环境中是否存在此漏洞,并采取有效的修复措施,是每一位安全运维工程师必须具备的实战能力。本文将基于我们团队多次实战处置的经验,拆解从漏洞原理理解、自动化与手动检测方法,到临时缓解与彻底修复的完整闭环。无论你是刚接触安全运维的新手,还是希望优化现有流程的老兵,都能从中找到可直接落地的参考方案。
2. 漏洞原理与影响范围深度解析
2.1 Fastjson反序列化漏洞的“罪魁祸首”
要有效检测和修复,必须先理解漏洞的根源。Fastjson是阿里巴巴开源的一个高性能JSON处理库,在Java开发者中应用极其广泛。它的一个强大特性是能够自动将JSON字符串“反序列化”为复杂的Java对象。为了方便这一过程,Fastjson设计了一个“自动类型”(AutoType)机制。
问题就出在这个AutoType上。在反序列化时,为了能实例化出JSON中指定类型的对象,Fastjson需要根据一个@type这样的字段来查找并加载对应的Java类。攻击者正是利用这一点,精心构造一个JSON字符串,其中的@type指向一个存在于Java类路径中、且其构造函数或setter方法中存在危险操作的类(例如com.sun.rowset.JdbcRowSetImpl)。当Fastjson(在特定漏洞版本下)解析这个JSON时,会按照@type的指示去实例化这个危险类,进而触发其中的恶意代码,比如发起一个JNDI查询。如果这个JNDI查询指向一个由攻击者控制的恶意RMI/LDAP服务,服务器就会从该服务加载并执行攻击者准备好的恶意类,从而完成远程代码执行。
从Fastjson 1.2.25版本开始,官方引入了黑白名单机制来限制AutoType,但后续版本中又陆续爆出多个绕过黑名单的漏洞(如1.2.47, 1.2.68, 1.2.80等),使得该问题反复出现,成为安全领域的“常青树”漏洞。
2.2 致远M3 Server为何成为重灾区?
理解了Fastjson的漏洞原理,我们再来看致远M3 Server。致远互联的M3系列产品是一款面向中小企业的移动协同管理平台,其后台服务通常由Java开发,并且很大概率会引入Fastjson库来处理前端传递的JSON数据(例如API接口、表单提交等)。
当一个广泛使用的、存在历史漏洞的组件(Fastjson)被集成到一个广泛部署的企业应用(致远M3 Server)中时,它就构成了一个极具吸引力的攻击面。攻击者无需了解M3业务逻辑的细节,只需要探测到其Web接口,并发送针对Fastjson漏洞的通用攻击载荷,就有可能拿下服务器权限。这使得致远M3 Server成为了僵尸网络、勒索软件攻击者重点扫描和攻击的目标之一。
影响范围可以概括为:所有部署了致远M3 Server,且其依赖的Fastjson库版本在受影响范围内(通常是<=1.2.80的多个特定版本)的系统,无论其运行在物理机、虚拟机还是容器环境中,均存在被远程代码执行的高风险。
3. 快速检测方案:自动化扫描与手动验证
发现漏洞是修复的第一步。我们推荐“工具扫描初步发现 + 手工验证确认”的组合拳,确保检测结果的准确性。
3.1 自动化资产扫描与漏洞发现
对于拥有成百上千台服务器的企业,人工排查是不现实的。我们需要借助自动化工具。
1. 网络空间测绘引擎(如 FOFA、Shodan、ZoomEye):这是最快速的初步排查方式。你可以使用特定的搜索语法来定位互联网上暴露的致远M3 Server。例如,在FOFA中,可以尝试搜索title=“致远M3”或body=“M3-server”等关键词。结合port=“8080”或其他Web端口,可以快速列出可能的目标列表。但这只能发现暴露在公网的系统,内网系统还需内部扫描。
2. 漏洞扫描器集成:商业或开源的漏洞扫描器(如Nessus, OpenVAS, Goby)的漏洞库通常已经收录了致远M3 Server Fastjson漏洞的检测插件。你可以定期对全网的IP段进行漏洞扫描。配置扫描策略时,需确保启用了对应的Web应用漏洞检测项。
注意:在生产环境进行主动漏洞扫描前,务必获得授权,并在业务低峰期进行,因为扫描行为可能对应用性能造成短暂影响,甚至触发安全设备的告警。
3. 专项检测脚本:安全团队通常会编写或使用现成的Python脚本进行批量检测。这类脚本的原理是向目标URL(如/api/v1/data,/m3/service等常见接口)发送一个无害的、但能触发特定响应的探测Payload(例如利用DNSLog回传的Payload),通过检查是否有DNS解析记录或HTTP回调来判断是否存在漏洞。
# 示例:一个简单的检测思路(伪代码,实际需根据情况调整) import requests targets = [‘http://192.168.1.100:8080‘, ‘http://10.0.0.5:8080‘] dnslog_subdomain = ‘your-unique-subdomain.dnslog.cn‘ probe_payload = { “@type”: “java.net.Inet4Address”, “val”: dnslog_subdomain } for target in targets: try: resp = requests.post(target + ‘/some-api-endpoint‘, json=probe_payload, timeout=5) # 随后去DNSLog平台检查是否有该子域名的解析记录 except Exception as e: print(f“{target} 请求失败: {e}”)3.2 手工验证与深度排查
自动化工具可能会误报或漏报,因此关键系统需要手工验证。
1. 版本信息收集:
- 前端探查:访问致远M3 Server的登录页面或任意静态资源,查看HTML源码、JS文件注释或HTTP响应头,有时会包含版本信息。
- 文件系统检查(需有服务器权限):登录到部署M3 Server的服务器,找到其Web应用目录(如Tomcat的
webapps/m3或WEB-INF/lib)。在lib目录下,查找名为fastjson-*.jar的文件。通过文件名即可确定版本,例如fastjson-1.2.68.jar。find /path/to/tomcat/webapps -name “fastjson*.jar” -type f - 进程与依赖分析:使用
ps命令找到Java进程,通过jps -l和jcmd <PID> VM.command_line查看启动参数和类路径,间接定位JAR包位置。
2. 漏洞验证(谨慎操作!):强烈建议在隔离的测试环境中进行。可以使用公开的验证工具,如fastjson_tool或集成在Burp Suite中的插件。向疑似存在漏洞的接口发送一个无害的、带有延迟的探测Payload。例如,构造一个触发Thread.sleep()的Payload,如果服务器响应时间明显延长,则高度怀疑漏洞存在。
{ “@type”: “java.lang.Thread”, “target”: { “@type”: “java.lang.Runnable”, “instance”: { “@type”: “com.sun.xml.internal.ws.api.message.Packet”, “message”: { “@type”: “java.lang.Thread”, “sleep”: 10000 } } } }重要警告:切勿在生产环境使用任何可能执行命令或造成破坏的Payload进行验证。仅使用无害的探测技术(如DNS外带、时间延迟)。
4. 漏洞修复的完整实战流程
检测确认后,必须立即启动修复流程。修复不仅仅是升级一个JAR包,而是一个系统的工程。
4.1 紧急临时缓解措施
在无法立即升级或重启服务的极端情况下,可以采取以下临时措施“止血”:
网络层访问控制:
- 在防火墙或WAF(Web应用防火墙)上,对致远M3 Server的业务端口设置严格的访问策略。仅允许可信的IP地址段(如办公网IP、运维跳板机IP)访问,阻断所有非必要的公网访问。
- 在WAF上部署针对“Fastjson反序列化漏洞”的虚拟补丁规则。规则核心是检测HTTP请求体(特别是POST的JSON数据)中是否包含特征字符串,如
@type、autoType、$ref等,以及其后是否跟有疑似恶意类的类名(如com.sun.、org.apache.下的一些危险类)。这可以有效拦截大部分自动化攻击。
应用层参数过滤:
- 如果具备二次开发能力,可以在请求进入业务逻辑之前,增加一个全局过滤器或拦截器,对请求内容进行清洗。例如,严格校验JSON结构,拒绝包含
@type字段的请求,或者对@type的值进行严格的白名单校验。 - 缺点:这可能影响应用正常功能,如果M3 Server内部通信也使用了
@type,则会导致服务异常。因此这只能作为非常临时的应急手段。
- 如果具备二次开发能力,可以在请求进入业务逻辑之前,增加一个全局过滤器或拦截器,对请求内容进行清洗。例如,严格校验JSON结构,拒绝包含
4.2 根本解决方案:升级与加固
临时措施治标不治本,彻底修复需要升级Fastjson库。
1. 获取安全版本:访问Fastjson的官方GitHub仓库,获取最新的安全版本。目前,1.2.83及以上版本是相对安全的。务必从官方渠道下载,避免引入被篡改的恶意版本。
2. 升级操作步骤:
停机升级(推荐用于可接受中断的业务):a.备份:停止M3 Server服务,完整备份整个应用目录及原
fastjson-*.jar文件。 b.替换:删除旧版本的fastjson-*.jar文件,将新版本的JAR包放入WEB-INF/lib/目录。 c.验证依赖:检查是否有其他JAR包对特定版本的Fastjson有强依赖(可通过查看其他JAR包的MANIFEST.MF或使用mvn dependency:tree如果项目是Maven构建)。通常直接替换主JAR包即可。 d.启动测试:启动服务,全面测试核心业务功能,确保升级未引入兼容性问题。热更新/动态加载(适用于高可用环境,技术要求高):对于不能停机的核心系统,可以考虑使用Java Agent技术或某些中间件/容器的热部署功能来动态替换类加载器中的Fastjson类。此操作风险极高,必须由经验丰富的开发人员在预发布环境中充分测试后才能在生产环境尝试,否则极易导致内存泄漏或应用崩溃。
3. 安全加固配置:仅仅升级版本可能还不够,需要配置Fastjson的安全模式以彻底关闭风险最高的AutoType功能。
- 在应用启动参数或初始化代码中,添加以下配置:
// 在初始化Fastjson的ParserConfig或全局设置中 ParserConfig.getGlobalInstance().setAutoTypeSupport(false); // 关闭AutoType ParserConfig.getGlobalInstance().addDeny(“*”); // 显式拒绝所有,黑名单思维 // 或者,更安全的是使用白名单 ParserConfig.getGlobalInstance().addAccept(“com.yourcompany.”); // 只允许自己公司的包 - 对于致远M3 Server,你需要找到其初始化代码的位置,或者通过JVM参数
-Dfastjson.parser.autoTypeSupport=false来尝试全局关闭。注意:修改前务必在测试环境验证此配置是否会导致M3应用功能异常。
4. 容器与镜像修复:如果致远M3 Server部署在Docker容器中,你需要: a. 基于原有Dockerfile,修改其中下载或复制Fastjson JAR包的步骤,指向新版本。 b. 重新构建Docker镜像,生成新的镜像标签(如m3-server:v1.2-fixed)。 c. 在测试环境部署新镜像,完成验证。 d. 在生产环境通过滚动更新或蓝绿发布的方式,将旧容器替换为新容器。
5. 修复后的验证与监控
修复完成不代表万事大吉,必须进行严格的验证和持续的监控。
5.1 修复有效性验证
- 漏洞复测:使用之前验证漏洞的相同方法(如无害的DNSLog探测Payload)再次对修复后的系统进行测试。预期结果应为:请求正常响应,且DNSLog平台没有收到任何解析记录,时间延迟Payload不会造成响应延迟。
- 功能回归测试:组织测试团队或业务人员,对致远M3 Server的所有核心功能模块进行一轮完整的测试,确保升级和配置修改没有破坏原有的业务流程。重点测试与JSON数据交互的API、表单提交、数据导入导出等功能。
- 版本确认:再次通过文件检查或应用内接口(如果M3提供了版本查询接口)确认Fastjson的版本号已更新至目标安全版本。
5.2 建立长效监控机制
一次修复不能防范未来的新漏洞。必须建立持续的安全监控体系。
- 资产与依赖清单管理:使用CMDB(配置管理数据库)或专门的软件成分分析(SCA)工具,对所有业务系统的第三方依赖(包括Fastjson)进行清点和管理。当有新的漏洞爆发时,能快速定位受影响系统。
- 威胁情报订阅:关注国家漏洞库(CNVD、CNNVD)、开源社区(GitHub Security Advisories)、安全厂商(如奇安信、绿盟、深信服)发布的漏洞通告。针对Fastjson、致远等关键组件设置关键词告警。
- 入侵检测与日志审计:
- 在服务器层面部署HIDS(主机入侵检测系统),监控异常进程启动、敏感命令执行、网络外连等行为,这些可能是漏洞被利用后的后续攻击迹象。
- 集中收集并分析致远M3 Server的应用日志、Web访问日志。设置告警规则,例如:短时间内大量包含
@type、JdbcRowSetImpl等关键词的POST请求;来自异常地理位置的访问;响应状态码为500但伴有特定异常栈(如JSONException相关)的请求。
- 定期漏洞扫描与渗透测试:将修复后的系统重新纳入定期的漏洞扫描范围。每年至少进行一次深度的渗透测试,模拟攻击者的手法检验系统的整体安全性。
6. 实战中遇到的典型问题与排查记录
在多次处置过程中,我们踩过不少坑,这里分享几个典型案例和解决思路。
问题1:升级Fastjson后,应用启动报ClassNotFoundException或NoSuchMethodError。
- 排查思路:这通常是依赖冲突或兼容性问题。
- 依赖冲突:使用
mvn dependency:tree命令(如果是Maven项目)或类似工具,检查是否有其他传递依赖引入了不同版本的Fastjson。旧版本的JAR可能没有被完全清除,或者被其他依赖强制指定。解决方法是使用<exclusions>标签排除旧版本,确保只有一个新版本在类路径中。 - API不兼容:Fastjson在部分大版本间(如1.1到1.2)可能存在API变更。检查应用代码中是否使用了在新版本中被废弃或删除的方法。需要根据Fastjson的官方升级指南修改代码。
- 依赖冲突:使用
- 我们的经验:在升级前,先在测试环境用
java -verbose:class启动应用,观察加载的Fastjson类具体来自哪个JAR文件,能清晰定位冲突源。
问题2:关闭AutoType后,应用内部某些功能报错“autoType not support”。
- 排查思路:这说明M3 Server自身的某些功能(或它依赖的某个模块)确实需要使用AutoType特性。
- 解决方案:不能一刀切地关闭。需要采取更精细化的白名单策略。
- 通过日志分析,找到报错时尝试反序列化的具体类名(例如
com.seeyon.xxx.XXXModel)。 - 将这些确系业务需要的、安全的类名,逐个添加到Fastjson的白名单中。
ParserConfig.getGlobalInstance().addAccept(“com.seeyon.v3x.”); ParserConfig.getGlobalInstance().addAccept(“com.yourcompany.safe.package.”);- 这是一个迭代过程,需要在测试环境充分测试,逐步添加白名单直至所有业务功能正常。
- 通过日志分析,找到报错时尝试反序列化的具体类名(例如
问题3:WAF虚拟补丁规则导致正常业务请求被误拦截。
- 排查思路:WAF规则通常基于正则表达式匹配请求体中的关键词,过于严格的规则可能会误伤合法的、恰好包含类似字符串的请求(例如,一段包含“@type”英文单词的普通文本内容)。
- 解决方案:
- 优化规则:与安全设备管理员协作,分析误拦截的请求日志,优化规则逻辑。例如,将规则从简单的字符串匹配,改为更精确的“检查JSON结构中的
@type键名”。 - 设置例外:对于确认为安全的、固定的业务接口或来源IP,可以在WAF上设置例外策略,绕过对该部分流量的检测。
- 记录与审计:即使有误报,在应急期间也建议保持WAF拦截模式为“记录”而非“阻断”,待分析所有日志、确认无误后再切换为“阻断”,并在业务低峰期进行。
- 优化规则:与安全设备管理员协作,分析误拦截的请求日志,优化规则逻辑。例如,将规则从简单的字符串匹配,改为更精确的“检查JSON结构中的
问题4:在分布式集群中,修复进度不一致,导致漏洞被利用。
- 场景:一个M3 Server集群有10个节点,修复时先升级了5个,另外5个因故延迟。攻击者可能通过负载均衡器,将恶意请求打到未修复的节点上。
- 解决方案:
- 标准化修复流程:制定包含“拉出负载均衡 -> 升级 -> 验证 -> 重新加入”的标准节点修复SOP(标准作业程序)。
- 利用编排工具:如果使用Kubernetes等容器编排平台,利用其滚动更新机制,可以控制一次只更新一个或少量Pod,并在新Pod健康检查通过后再替换旧的,实现无缝修复。
- 前置流量清洗:在集群入口处(如API网关、全局WAF)部署统一的防护规则,为整个集群提供一层额外的保护,即使个别节点未修复,也能在入口层拦截大部分攻击。