首页 / 资讯中心 / 文章详情

CVE-2019-2725漏洞深度解析:WebLogic反序列化攻击原理与应急防御

CVE-2019-2725漏洞深度解析:WebLogic反序列化攻击原理与应急防御 ★ FEATURED ARTICLE
2019年4月的一天晚上我的监控群里连续弹了七八台服务器的告警。Java进程CPU直接拉满/tmp目录下多了一堆来路不明的脚本进程列表里冒出不认识的线程名。顺着日志一路排查所有线索都指向一个共同点WebLogic的/_async/路径。没过多久CVE-2019-2725这个编号出现在了安全公告里我才意识到这是一轮针对老版本WebLogic的大规模定点清理行动。这篇文章不打算复述漏洞公告原文我想站在中间件运维和应急响应的角度把CVE-2019-2725的原理、检测、防御以及我在处理过程中踩过的坑完整梳理一遍。适合WebLogic运维、安全工程师、SRE以及还在维护老旧Java系统的开发同学阅读。尤其是那些系统里还跑着10.3.x版本的人看完你会知道该从哪里下手。1. 漏洞背景与影响范围分析1.1 影响版本与公开热度回顾CVE-2019-2725是Oracle WebLogic Server中的反序列化远程代码执行漏洞官方公告明确点名的受影响版本包括10.3.6.0和12.1.3.0。后续的同类问题研究又拉上了12.2.1.2、12.2.1.3等版本所以实际风险面比公告列出的还要宽。这个漏洞真正让人头疼的地方有三点利用门槛极低公开渠道很快流出了可用代码不需要什么高深技巧触发入口是中间件自带的异步Web服务组件默认环境下甚至不需要账号密码漏洞一旦被利用攻击者直接拿到的是运行WebLogic的JVM进程权限在多数生产服务器上这个权限基本等同于系统本地用户权限。做过资产盘点的人都有体会企业内部多的是“跑了十年没人敢动”的中间件。WebLogic 10.3.x又是很多传统企业的存量主力版本老、依赖深、迁移成本高。CVE-2019-2725之所以在当年引发大面积告警不是因为它的技术含量有多顶尖而是因为存量环境实在太多。1.2 攻击入口为何有这么大杀伤力要理解这个漏洞的威力先得搞清楚入口是怎么暴露的。WebLogic Server提供消息中间件、Web Service等企业级能力wls9_async_response.war就是异步Web服务的承载组件。在域的默认部署中这个war经常被自动带上来即使业务团队从没用过异步消息功能它也可能安静地躺在应用列表里。也就是说攻击面并不来自业务自身而是来自中间件产品自带、默认被部署的组件。这给运维带来的麻烦是当你排查漏洞影响时无法通过“我们没开这个功能”来排除风险因为这个组件有没有被部署与你用不用它没有直接关系。更麻烦的是端口暴露。很多网络环境的业务域名解析到Nginx或负载均衡但管理端口7001被直接放开到了公网或者某些特殊路径被透传到后端WebLogic。攻击者从公网就能直接触达/_async/入口等于把反序列化攻击的钥匙挂在了门把手上。所以做漏洞整改时光看WebLogic自身不够还要回答一个核心问题谁把7001暴露出来了2. 漏洞原理深度拆解2.1 Java反序列化到底在玩什么Java的序列化是把内存中的对象转成字节流方便存储或传输反序列化则是把字节流重新还原成对象。正常业务里RMI远程调用、缓存持久化、消息队列传递都会用到这套机制。问题在于反序列化过程中存在“隐式动作”。对象的类定义里可以自定义readObject之类的方法这些方法会在反序列化时被框架自动调用。你可以把Java反序列化想象成快递柜的取件流程系统收到包裹会按包裹上的说明自动开箱。如果包裹里的说明被人换个了内容开箱瞬间就会触发你完全不想看到的动作。攻击者把精心构造的序列化对象发给服务器服务端一旦执行反序列化攻击者就能控制“开箱动作”的内容进而执行任意Java方法最终落地系统命令。CVE-2019-2725的特殊之处在于它走的不是传统Java原生序列化字节流而是XMLDecoder组件。XMLDecoder是Java平台自带的工具作用是把一段XML描述还原成Java对象和属性。正常情况下没人会拿它去处理不可信的输入。但WebLogic的异步Web服务在处理请求时把攻击者可控的XML直接丢给了XMLDecoder等于把一个不可信的内容源接上了能够反向创建对象、调用方法的引擎不炸才怪。2.2 从XML到系统命令执行的路径这里我贴一段原理性示例去掉了完整的网络请求封装只看XMLDecoder的核心处理逻辑java object classjava.lang.ProcessBuilder stringwhoami/string void methodstart/ /object /javaXMLDecoder会把object标签解析为创建一个类实例void methodstart解析为调用这个实例的start方法。上面这段XML执行后就会启动系统进程去运行whoami命令。真实攻击者当然不会只跑whoami他们会构造更复杂的XML下载木马、解码、运行一气呵成。XML标签里头还能嵌套循环、赋值、异常处理基本可以把一个简化版编程语言塞进一段HTTP请求里。完整可打的Payload我就不展开了原因很直接这类利用代码到今天还能打穿大量存量环境写出来没有任何正面意义。原理层面的片段已经足够管理人员理解漏洞的本质了。2.3 补丁为什么会被绕过CVE-2019-2725能成为2019年的“明星漏洞”还有个绕不开的原因是补丁被绕过。2019年4月官方在一块CPU补丁里处理了一批反序列化漏洞包括T3协议下的若干入口。攻击者随后发现XMLDecoder这条路并没有被堵死wls9_async_response.war里的/_async/路径完全可用于是有了CVE-2019-2725这个编号。等官方针对它发布了新补丁又有人换了个上下文继续触发同样的问题最终催生了后续的CVE-2019-2729。绕过的本质是官方在补丁层面做了“删入口”而不是“堵根因”。只要WebLogic内部对XMLDecoder处理不可信XML的问题没有根除换个应用上下文、换条路径就能再次触发。这个特点也提醒了所有做防御的人补丁打完不等于安全结束流量侧的拦截和监控侧的告警必须长期持续。3. 漏洞检测与自查方案3.1 版本与组件自查先确认自己有没有暴露第一步要确认WebLogic的版本和补丁情况。生产环境不方便随便重启可以登录WebLogic控制台在域环境信息里看基础版本。也可以在服务器上用命令行获取cd ${WL_HOME}/server/bin ./setWLSEnv.sh java weblogic.version查看补丁安装情况不同版本用的工具不一样。老版本一般用BSU${WL_HOME}/utils/bsu/bsu.sh -view -statusapplied -prod_dir${WL_HOME}/server/lib新版本可能要用OPatch${WL_HOME}/opatch/opatch lsinventory版本评估记住一个原则低于12.2.1.3、且没有打到2019年4月之后季度补丁的WebLogic大概率在风险范围内。这里要特别强调控制台里显示的版本号只是基础版本补丁信息必须通过命令行工具单独确认两个信息缺一不可。3.2 日志与流量特征还原攻击请求的面貌WebLogic开过访问日志的话日志路径一般在${DOMAIN_HOME}/servers/${SERVER_NAME}/logs/目录下。重点排查POST方法指向/_async/路由的请求grep -i _async ${DOMAIN_HOME}/servers/*/logs/*access*log* grep -i AsyncResponseService ${DOMAIN_HOME}/servers/*/logs/*access*log*攻击请求的Content-Type基本都是text/xmlSOAPAction要么为空、要么是一串随机值。如果做了流量镜像直接抓包过滤关键词会更直观报文里往往能直接看到java.lang.ProcessBuilder、java.lang.Runtime、wls9_async_response这些字符串。3.3 主机痕迹排查判断是否已经沦陷日志里看到可疑请求接下来要立刻判断题主是不是已经被植入后门。常见痕迹包括进程列表中Java进程存在非业务类名的加载/tmp、/var/tmp目录下出现近期创建的.sh、.jar、.py文件crontab里出现“下载执行”类任务服务器向非业务端口发起异常外联流量WebLogic进程异常退出或反复重启。主机痕迹排查这一层应急时往往容易被忽略。运维的注意力都在WebLogic日志上但攻击者拿到权限后会在主机上留一堆东西先查主机再查应用顺序不要搞反。4. 实战防御从临时止血到永久修复4.1 第一时间止血访问控制与流量封堵如果确认环境在攻击面内又没法马上打补丁优先做的是访问控制。老环境最常用的止血方案有这么几条在Nginx或负载均衡层直接屏蔽/_async/和/wls-wsat/开头的请求管理端口独立把7001端口限制到白名单IP段网络架构允许的话把WebLogic管理流量和业务流量彻底分离。Nginx层的拦截配置很简单location ^~ /_async/ { return 403; } location ^~ /wls-wsat/ { return 403; }改成403之后攻击者就触达不了漏洞入口Nginx层直接拦截掉了。这条规则后来我一直在用即使系统迁移到新版本前面的负载均衡上也还挂着它。流量封堵是临时方案但它能为你争取到打补丁和清理后门的时间。4.2 应用卸载与补丁安装的正确姿势流量封堵只是外围止血根除还得从WebLogic内部去掉攻击面。如果业务确实用不到异步Web服务可以在控制台的应用部署列表里查看wls9_async_response.war按标准流程停止并卸载应用。这里必须提醒一句别直接到安装目录把war包文件删掉。我见过不止一个同事这么干结果下次启动AdminServer直接报错因为域的配置里还保留着部署记录找不到对应文件。正确做法是先通过控制台停止并卸载应用再考虑要不要归档或删除war包。如果控制台的应用列表里看不到这个war那就不要硬删规规矩矩用前文的访问控制策略解决。补丁安装方面我的建议是不要只打单一漏洞补丁。WebLogic每个季度会有统一的CPU补丁包把同批次的安全修复全量打上去比只打一个编号更稳妥。打补丁前备份域目录、记录当前版本、写好回滚步骤完成之后至少做一次启停验证和业务接口冒烟测试。还有一个容易被忽略的点补丁和JDK版本强相关升级前一定要确认当前WebLogic使用的JDK版本在补丁兼容矩阵里面。4.3 纵深防御从单点修复到整体加固经历过CVE-2019-2725的应急之后我给客户做的WebLogic加固清单逐渐沉淀成了一套稳定模板大致分四层网络边界层WAF规则和IPS签名库保持更新对反序列化特征保持敏感主机层HIDS监控文件落地、进程异常、外联请求攻击者下载脚本的动作要能及时告警中间件层关闭业务不需要的T3、IIOP协议数据库账号遵循最小权限原则WebLogic进程不要用root账号启动配置基线控制台强密码策略、登录失败锁定、管理端口不对外暴露。这套模板里的每一项单看都不复杂但组合起来效果非常明显。攻击者利用漏洞只是一瞬间的事情但从入口触达、payload执行、文件落地、权限提升到横向移动中间有太多环节可以被监控拦下来。纵深防御的意义不在于让系统“无法攻破”而在于让入侵者每一步都踩到告警上。5. 常见问题与排查技巧实录5.1 典型问题速查表我在多次处置中沉淀了一个速查表遇到类似情况可以照着查现象可能原因排查方向打了补丁仍然被植入后门补丁被绕过或补丁没有完全生效核实补丁安装日志排查其他war入口Java进程CPU飙升攻击Payload包含死循环逻辑抓线程栈定位可疑线程/tmp目录出现不明脚本已经被植入下载器或木马排查定时任务、近期文件、进程外联7001端口被持续扫描公网暴露面过大配置访问控制收敛端口检查上游防火墙访问日志大量500错误攻击请求被应用拒绝但不代表没有执行配合流量镜像确认命令是否真正执行5.2 应急响应中的两个核心建议第一处置这类漏洞时强烈建议先用快照或克隆方式保留现场。我见过不止一次同事为了止损手动kill掉可疑进程后来做溯源取证时啥都没剩下。保留现场是最基本的工作习惯后续做入侵分析会完全依赖现场数据。第二不要只盯着WebLogic日志。攻击者拿到权限后会立刻做内网信息收集检查数据库连接配置、应用配置文件、SSH密钥等。应急排查时要把同网段其他系统的登录记录也纳入范围判断攻击者是否已经横向移动。很多反序列化漏洞的利用最终造成大面积沦陷就是因为只清了一台机器攻击者早从这台机器跳出去了。5.3 几个我踩过的真实坑版本判断上最经典的坑就是把控制台显示的基础版本当成了全部信息。控制台里显示的版本只是最底层版本补丁必须单独确认两者不能混为一谈。应急时如果时间紧至少要用命令行看一眼补丁清单再下结论。还有一次业务方非常确定地说不依赖/_async/结果我在测试环境卸载war包后凌晨的定时任务开始报错。最后排查才发现某个老模块间接调用了异步Web服务平时根本看不出来。所以卸载动作前必须先在测试环境做业务回归不要轻信“这个功能我们没用过”。处理完整个CVE-2019-2725之后我心里一直留着一个准则反序列化漏洞的真正解药不是某个具体补丁而是“不信任外部输入”的设计理念。对中间件来说只要系统暴露在不可信网络中这类漏洞就会以新编号的形式反复出现。每次看到WebLogic新公告我都会先问自己三个问题入口关了吗监控能发现吗日志能溯源吗把这三件事落实到位再遇到类似的漏洞编号好歹能心里有数。
阅读完成 · 觉得有帮助?
咨询建站