WebLogic反序列化漏洞CVE-2019-2725解析与加固

📅 发布时间:2026/10/21 16:01:02
WebLogic反序列化漏洞CVE-2019-2725解析与加固
1. 漏洞背景与影响范围1.1 这个漏洞为什么值得拿出来单讲先说一个判断CVE-2019-2725 是整个 WebLogic 反序列化漏洞家族里非常特殊的一个它不是简单的补丁漏了而是 Oracle 在修复上一个漏洞时留下的绕过产物。很多人只知道它是一个 RCE远程命令执行但没搞明白它跟前代漏洞比如 CVE-2017-10271、CVE-2018-2628的关系导致修复时总是修了又破、破了又修非常典型的打地鼠场景。这个漏洞影响的是 Oracle WebLogic Server 的wls9-async 组件涉及的版本主要是10.3.6.0和12.1.3.0。漏洞的本质是WebLogic 在解析通过 HTTP 协议进来的 SOAP 请求时会调用一个名为AsyncResponseService的异步服务而该服务在反序列化 XML 中嵌入的 Java 对象时没有做足够的黑名单校验攻击者可以构造一份畸形的 SOAP 报文让服务器反序列化恶意对象从而实现远程代码执行。2019 年 4 月 Oracle 发布季度补丁时官方只修补了 wls-wsat 组件的反序列化绕过问题却漏掉了 wls9-async 这个入口于是这个漏洞在补丁发布后没多久就被人在野利用。我印象里国内最早的一批利用是针对中间件服务器的挖矿程序攻击者拿到权限后迅速下载木马、植入后门整个过程只需要一个 HTTP POST 请求快得让人反应不过来。这篇文章适合三类人看一是中间件管理员需要确认自己的 WebLogic 是否受影响、怎么修二是安全运维需要写检测规则和加固清单三是刚接触 Java 反序列化漏洞的初学者想搞明白 WebLogic 这类反序列化漏洞到底是怎么一步步被利用的。1.2 追溯根因从 wls-wsat 到 wls9-async要理解 CVE-2019-2725得先从它的前辈说起。2017 年底曝光的 CVE-2017-10271 影响的是 wls-wsat 组件Oracle 在 2018 年的补丁里给 wls-wsat 加了一个黑名单。这个黑名单的思路很直接反序列化的时候如果碰到黑名单里的类就直接抛异常拒绝执行。思路本身没问题问题出在覆盖面上——补丁只补了 wls-wsatwls9-async 这个同样存在反序列化逻辑的接口没有被覆盖到。wls9-async 是 WebLogic 用来处理异步消息通知的组件通过/_async/AsyncResponseService这个路径对外提供服务它同样基于 XML 解析 SOAP 消息同样调用了 XMLDecoder 进行对象反序列化只是入口不一样。这就好比一栋楼有两个门保安只守住了前门后门不仅没锁门上还贴着贵重物品请放此处的告示。攻击者只是把原本打在 wls-wsat 上的攻击载荷原封不动地转移到了/_async/AsyncResponseService上发现居然还能打通。CVE-2019-2725 的官方描述里也明确写了攻击者可以通过精心构造的 SOAP 请求在未授权的情况下实现远程代码执行。 所谓未授权就是不需要任何账号密码直接往 7001 端口发一个 POST 请求就行。这里要特别提一下 XMLDecoder。这个类是 Java 自带的 XML 反序列化工具它能把 XML 描述的对象图转换成 Java 对象。在设计之初它就不是给不可信输入用的因为 XML 里可以声明任意类的实例化、字段赋值、方法调用这等于给了攻击者一个拿着 XML 就能写代码的能力。CVE-2019-2725 的核心问题就在这里WebLogic 把来自网络的不可信 XML 直接交给了 XMLDecoder而且没有做严格的类过滤。2. 漏洞原理剖析2.1 反序列化攻击的基本逻辑用生活化的方式讲Java 反序列化攻击听起来玄乎拆开看其实就是三步。第一步攻击者在提交的数据里嵌入一个 Java 对象的序列化表示。序列化就是把对象变成字节流反序列化就是把字节流变回对象。问题在于反序列化的过程中对象的readObject方法会被调用而某些类的readObject方法里藏着危险的后续动作。第二步攻击者会去找一条gadget chain利用链。这条链子的意思是从入口类出发通过一层层的 getter、setter、方法调用最终抵达一个能执行系统命令的终点类。举个不太严谨但容易理解的类比你往一台自动售货机里投入一枚特制的假硬币恶意数据这枚硬币看起来正常但在验币器里被弹来弹去的的时候会恰好连续触发几个开关最后激活了掉饮料的机械臂只是掉出来的不是饮料而是一台命令执行器。第三步把恶意数据塞到服务端会反序列化的位置等服务器处理请求时自动触发。攻击者不需要交互不需要提前知道服务器密码只需要服务器存在这个漏洞接口就能拿到执行权限。CVE-2019-2725 利用的链子在当时的公开分析中被认为是基于oracle.toplink.internal.sessions.UnitOfWorkChangeSet等类构造的。这些类在反序列化时会触发对Method的调用最终可以调用Runtime.exec这类执行命令的方法。我不在这里展开完整利用链的每一个类和方法因为那是另一个大话题而且网上已经有很多分析文章我只想让你记住一个结论这条链子是真实存在且可稳定触发的从请求报文到命令执行中间没有任何身份验证环节。2.2 CVE-2019-2725 的触发链路拆解这个漏洞的 HTTP 请求报文长什么样大体上是这样一条链路POST /_async/AsyncResponseService HTTP/1.1 Host: target:7001 Content-Type: text/xml SOAPAction: (空) soapenv:Envelope soapenv:Body ...反序列化触发载荷... /soapenv:Body /soapenv:EnvelopeWebLogic 收到这个请求后会交给 wls9-async 的AsyncResponseService处理。这个服务接收 SOAP 消息后把 body 里的 XML 交给XMLDecoder完成反序列化。XMLDecoder 不像ObjectInputStream那样要求必须是严格序列化的字节流它宽容得多几乎整个 XML 都能变成它的操作指令。这就是 2725 跟纯 JNDI 注入比如 CVE-2021-2109 那类不一样的地方——它走的是完全的 XMLDecoder 指令路线。攻击者在 XML 里声明一个object classjava.lang.Runtime methodgetRuntime然后在这个对象上继续声明调用exec方法就可以执行任意系统命令。当然实际利用的时候不会这么直白因为 WebLogic 内部还有一些过滤逻辑但总体思路如此。值得注意的一个细节是这个接口对 HTTP 方法并不挑剔GET、POST 都能到处理逻辑只是 POST 方便携带 XML body。我在复现环境里测试过即使SOAPAction为空或者 Content-Type 写不规范服务也能正常触发。这意味着基于请求头是否规整来做拦截的思路基本是白费功夫。3. 自查与验证怎么判断环境是否受影响3.1 不依赖扫描器的快速排查三件套很多人拿到这台 WebLogic 服务器的第一反应是上去执行一个 POC但我不建议在线上环境直接打恶意载荷。正确做法是先做静态排查确认环境到底存不存在漏洞接口。第一步看版本。SSH 登录到 WebLogic 服务器找到安装目录下的registry.xml或version.xml查看版本号。如果版本在10.3.6.0或12.1.3.0范围内且没有打上 2019 年 4 月之后的补丁基本可以判定为高风险。注意WebLogic 的补丁是累计型的不是说我 12.1.3.0 的补丁级别比较新就没事要看具体的 PSUPatch Set Update版本号以 Oracle CPU Quarterly 为准。第二步看部署的 war 包。wls9-async 是内置组件对应的 web 应用路径是/_async。你可以在 WebLogic 控制台里看已部署的应用列表也可以直接看domains/基础域名/servers/AdminServer/tmp/下的部署缓存或者用下面的命令直接请求一下curl -i http://127.0.0.1:7001/_async/AsyncResponseService -X POST如果返回的状态码是 404 或 405说明这个路径可能不存在或者已被禁用如果返回 500 或者直接进入某些异常处理流程说明这个组件是启用的需要重点盯防。也可以检查_async目录下是否有AsyncResponseService对应的部署包wls9_async_response.war。第三步看网络层访问控制。用netstat -antp看一下 7001 端口监听在什么地址上。如果 WebLogic 直接暴露在公网或者对办公网大范围开放那么漏洞的可达性就从理论可利用升级为很容易被打。我在真实处置中遇到的情况是很多企业把 WebLogic 放在内网但内网也是大互通状态任何一台办公终端都能直接访问中间件的管理端口这种边界形同虚设。3.2 最小化验证思路既不触发警报又能确认风险如果你需要做一次验证但又不希望真的让目标机器执行命令、留下痕迹我的建议是用无害探测 响应差异匹配的方式。具体来说就是构造一个不含恶意代码的 XML 报文但它的结构刚好能触发服务端解析逻辑。如果服务端进入反序列化的处理流程在开启了 WebLogic Access Log 的条件下请求日志里会出现/_async/AsyncResponseService的记录并且请求可能返回500或者带异常堆栈信息如果服务端在入口处就拦截了返回的可能是404或者纯静态的 HTTP 错误页。比如可以构造这样的请求注意不含攻击载荷只探测接口可达性POST /_async/AsyncResponseService HTTP/1.1 Host: 127.0.0.1:7001 Content-Type: text/xml Content-Length: 120 soapenv:Envelope xmlns:soapenvhttp://schemas.xmlsoap.org/soap/envelope/ soapenv:Body test/test /soapenv:Body /soapenv:Envelope然后对比/wls-wsat/CoordinatorPortType这个同样容易出问题的路径的返回情况。如果_async返回了明显的 WebLogic 异常页面或 500 状态而wls-wsat返回 404说明你至少有一个入口是活着的。我没有在这里给出完整的命令执行载荷原因很简单你不需要靠打一遍完整的攻击链来确认漏洞存在探测接口可达性已经足够决策。线上滥用完整利用代码很容易触发安全设备的告警还会给攻击溯源留下自己的 IP属于出力不讨好。4. 修复与加固实操4.1 官方补丁怎么打以及打补丁的注意事项CVE-2019-2725 的官方修复方案是 Oracle 2019 年 4 月 CPU 补丁编号上对应的补丁集是28969423。如果你的 WebLogic 版本是 10.3.6.0需要先升级到 10.3.6.0.190416 这个 PSU 级别12.1.3.0 版本同理需要 12.1.3.0.190416 及以上的补丁级别。打补丁的标准流程不复杂但有几个坑必须提醒第一个坑补丁安装前置条件不满足。打补丁之前必须先确认操作系统的依赖库完整特别是执行opatch时需要用到libclntsh.so这类共享库同时确保ORACLE_HOME环境变量指向正确的 WebLogic 安装目录。我见过有人把环境变量指到数据库的 ORACLE_HOME结果 opatch 直接把整个 WebLogic 目录搞乱的案例。第二个坑补丁后没有清理 tmp 缓存。WebLogic 会把部署的应用解压缓存到 domains 的servers/AdminServer/tmp/.internal/目录下补丁更新了 jar 包但缓存没刷新重启后可能仍然调用旧的 class。正确做法是打补丁后先停掉 AdminServer 和 ManagedServer清空每个 Server 的 tmp 和 cache 目录再启动服务。第三个坑补丁版本跟集群版本不一致。如果你的环境是 WebLogic 集群建议所有节点一次性全部打上补丁保持 patch level 一致。混跑的高低版本节点在启用集群内部通信时可能出现不兼容的通告严重的时候会导致会话复制异常。打补丁期间必须申请停机窗口。WebLogic 的补丁理论上支持滚动重启但在 10.3.6 这种老版本上我实测滚动重启的风险远高于一次性全部重启除非是核心业务要求 7x24 小时不能间断否则我不建议图省事搞滚动。4.2 临时缓解措施不重启也能降低风险如果业务不允许马上打补丁Oracle 官方和业界都有临时缓解方案。最有效的一条是禁用 wls9-async 组件的对外访问。具体操作是在 WebLogic 控制台或者直接编辑web.xml把AsyncResponseService对应的 servlet 映射注释掉。但控制台操作对权限有要求而且动态生效需要重载应用更干脆的办法是直接用防火墙或安全组规则把/_async/和/wls-wsat/这两个路径的访问限定到可信来源。如果你的 WebLogic 前面有 Nginx 或 Apache可以做一层 URI 级别的过滤location ~ ^/_async/ { deny all; return 403; } location ~ ^/wls-wsat/ { deny all; return 403; }实测下来这个配置对阻断外部扫描是很有效的。但要注意如果攻击者走的是 WebLogic 自身的 T3 协议或者内部转发Nginx 这层就看不到了。所以这只是临时缓解不是根治。另一种缓解方案是删除部署目录下的wls9_async_response.war和wls-wsat.war的部署注册信息。但直接删 war 包可能导致 WebLogic 控制台出现部署错误而且下次重启时如果Config.xml里还有部署项可能报应用找不到的错。我建议删除之前先备份并同步修改config.xml里的相关app-deployment条目。4.3 深层加固不只是补洞还要防横向修完漏洞不等于安全了因为攻击者可能已经利用漏洞留下过后门。处置完补丁之后下一步应该做工作组层面的排查。第一件事检查 WebLogic 进程是否被注入了恶意 jar。用jps或jstack看一下 JVM 进程确认是否有异常的线程名。也可以去临时目录看看有没有可疑的.jar或.jsp文件特别是名字跟正常业务完全不搭边的那种。第二件事检查系统层有没有反弹 shell 的痕迹。看看/tmp、/var/tmp下有没有可疑的脚本和二进制文件crontab -l检查定时任务/etc/ld.so.preload检查库劫持。第三件事保留 WebLogic access log。我见过不少企业默认把访问日志级别开得极低出了问题连攻击者从哪里来都查不到。建议把访问日志打开至少记录 POST body 的大小和来源 IP。日志的保存周期不要低于 6 个月这是溯源的重要依据。5. 常见问题排查实录5.1 排查中的典型误区为什么你测不到漏洞我在帮助企业处置 2725 相关的安全事件时经常遇到几种测不到漏洞的困惑。整理成速查表方便你按图索骥。现象可能原因进一步排查方式请求/_async/AsyncResponseService返回 404该路径被前置防火墙/Nginx 拦截或应用未部署直接在内网一台机器上用 IP端口访问绕过七层代理试试返回 500 但日志里看不到异常堆栈日志级别设置为 ERROR 以下或者异常被统一处理到servers/AdminServer/logs/下看*.log和*.out文件探测 wls-wsat 正常但 _async 无响应wls-wsat 和 wls9-async 是不同组件可能分别打了不同补丁分别测试两个路径不能只测一个入口就判定安全打了 4 月补丁后仍可访问 _async 路径补丁只是加了类过滤没有禁用接口用包含恶意类的载荷测试是否被拦截如果仍可执行说明补丁未生效WebLogic 是新装的 12.2.x仍然中招12.2.x 也受部分反序列化漏洞影响且组件默认开启不能只关注 2725 对应的旧版本其他反序列化入口同样要排查其中返回 500 但日志无异常这个现象最坑。因为 WebLogic 的高版本默认开启了一个安全异常抑制机制部分反序列化异常被吞掉只在更底层的日志里打印。你要看日志目录/diagnostic_images/下的*_DiagnosticImage.log那里往往记录着被压制的异常详情。5.2 补丁打不上典型的 3 个卡点与解法卡点一opatch 报 Oracle Home not known at /...这个错误八成是环境变量没配对。确认一下ORACLE_HOME和MIDDLEWARE_HOME是否指向 WebLogic 的wlserver_10.3或wlserver目录不要指向整个Oracle/Middleware根目录。另外 opatch 工具的路径应该在$ORACLE_HOME/OPatch/opatch不同版本之间不要混用。卡点二补丁应用到一半报某个 jar 包 checksum 不匹配典型的组件文件被动过可能是之前打过别的补丁、也可能有人手工替换过 jar 包。这个没有捷径需要对照官方补丁说明里的文件清单用cksum检查每个 jar 包。如果实在找不到被改的文件最稳妥的办法是把 WebLogic 停掉备份原目录后重新解压一个干净的安装目录再打补丁。卡点三10.3.6 打 4 月 CPU 补丁前必须先打 1 月的补丁Oracle 的季度补丁是叠加式的如果你直接跳到 190416opatch 会报requires earlier PSU这是正常的不是失败了。你需要找到 1901151 月 CPU先装上再上 190416。这一点官方文档里写得不太显眼但实操中非常常见。5.3 做完加固后怎么验证确实安全了打完补丁、配完过滤规则之后最好做一轮验收测试确认修复确实生效。我的习惯是准备一份不包含真实攻击载荷的探针脚本用 Python 的requests或curl发送特制报文到_async接口观察响应变化。具体来说补丁生效后当报文里包含明显反序列化特征类名的 XML 结构时服务端应返回异常或拒绝处理而正常业务报文则不受影响。另外别忘了做正向验证——用正常业务调用走一遍_async接口如果你还需要这个接口的话确认没有因为加固导致业务功能挂掉。有几次我只注意拦截忘了业务方还在用这个接口做异步通知加固一上业务直接报错运维半夜打电话找我很尴尬。注意所有验证请求必须在企业授权的测试环境或系统管理员明确同意的环境下进行避免在未授权系统上做任何探测。安全测试不是攻击授权不是所有试一下都是合规的。6. 最后再分享几个实操心得CVE-2019-2725 这类 WebLogic 反序列化漏洞给我最大的警醒不是某个组件写得不安全而是补丁管理在真实运维里的滞后程度。我处理过不止一个案例客户在漏洞曝光半年之后才知道自己中了招期间整整半年服务器都在公网裸奔。问他们为什么没打补丁答案几乎都是担心影响业务不敢动。这里我想说一个朴素的建议对中间件类的漏洞不要抱着不被打就不修的心态尤其是 WebLogic、JBoss 这类常年在 RCE 漏洞榜单前排的软件上线之初就应该把补丁更新列入例行运维计划而不是等 Red Hat 的告警邮件堆了一堆才着急。回到 CVE-2019-2725 本身如果你今天看完这篇文章能记住三件事就够了第一它的根因是 wls9-async 组件把不可信 XML 直接交给 XMLDecoder 处理入口路径是/_async/AsyncResponseService第二修复的核心不是删接口而是打上正确的补丁并确认补丁确实生效第三修复只是起点攻击者可能早就在你还没打补丁的时候进来逛了一圈所以事后检查系统后门跟打补丁同等重要。我一直觉得安全工作的本质是把边界看住把变更做稳把痕迹留全。这三个词听起来简单但每一条背后都是无数个踩坑换来的。希望这篇文章能让你少踩几个坑。