java 漏洞挖掘_Java XXE漏洞典型场景分析

本文首发于oppo安全应急响应中心:

0x01 前言:

XML 的解析过程中若存在外部实体,若不添加安全的XML解析配置,则XML文档将包含来自外部 URI 的数据。这一行为将导致XML External Entity (XXE) 攻击,从而用于拒绝服务攻击,任意文件读取,扫内网扫描。以前对xxe的认识多停留在php中,从代码层面而言,其形成原因及防护措施较为单一,而java中依赖于其丰富的库,导致解析xml数据的方式有多种,其防御手段也有着种种联系,本文主要从几个cve的分析,了解java中xxe的常用xml解析库、xxe的形成原因、java中xxe的防护手段以及如何挖掘java中的xxe。

0x02 XXE相关分析:

1.JavaMelody组件XXE

JavaMelody是一个用来对Java应用进行监控的组件。通过该组件,用户可以对内存、CPU、用户session甚至SQL请求等进行监控,并且该组件提供了一个可视化界面给用户使用。

默认情况下只要将其添加pom依赖中,其将随web服务一起启动,所以不需要什么权限即可访问此路由,若路径泄露如下图所示本来就会泄露一些敏感信息

8711de7deaa6afed48b46306cb26c719.png

1.1 漏洞点分析

在monitor的filter匹配之后将会对请求的http请求内容做处理获取请求类型,在net/bull/javamelody/PayloadNameRequestWrapper中在处理当content-type为以下两种情况:

1.contentType.startsWith("application/soap+xml")2.contentType.startsWith("text/xml") || requests.getheader("SOAPAction")

部分函数调用栈如下图所示:

f4717044d61345c537393ac2bf738015.png

在content type满足xml数据请求规则后调用parseSoapMethodName来对http请求内容做解析,这个函数就是漏洞所在处

cf77cdbb4ac7aeb15d4426ffea1997bf.png

这里使用xmlInputFactor工厂类,该类与DocmentBuilderFactory一样都可以设置一些feature来规范化xml处理过程,那么问题就是默认情况下dtd解析和外部实体都是可以使用的,如下两条配置即为导致xxe的默认配置

javax.xml.stream.isSupportingExternalEntitiesResolve external parsed entitiesBooleanUnspecifiedYesjavax.xml.stream.supportDTDUse this property to request processors that do not support DTDsBooleanTrueYes

在xmlInputFactor类的文件中就可以找到默认的一些feature,我们可以将feature理解为为了解析xml而提供的配置选项

8c680ed2b488accfd18a0ba4eab91791.png

pom依赖:

net.bull.javamelody

javamelody-spring-boot-starter

1.73.1

4ced16c2d587151e21baba69b8ccf6e2.png

1.2 代码层面修复

那么在该组件的新版本中对应的修复如下图所示,默认情况下在创建xml解析对象之前设置工厂的feature禁用掉dtd和外部实体,从而防御xxe

34e7e843a08238d8355aad1deea18e25.png

1.3 如何避免xxe

在实际的开发中,对于xml数据解析流程不需要外部实体参与的情况,设置feature将其禁用。在确定组件版本对xml的解析已经禁用掉外部实体后,也要设计filter来对该功能的访问进行鉴权操作,防止敏感功能被越权访问。

2.weblogic中的xxe

这节主要分析weblogic中的几个xxe,包括CVE-2019-2647-CVE2019-2650以及CVE2019-2888,那么这几个洞的原因都是weblogic依赖的jar包中涉及xml数据处理时默认情况下没有做好外部实体限制措施,导致可以通过T3协议进行序列化payload发送,从而利用外部实体进行xxe

2.1 漏洞点分析

第一处是是Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar下的weblogic/wsee/reliability/WsrmServerPayloadContext,从weblogic输入流处理到xml数据解析入口的部分调用栈如下图所示:

9f2d8ad64066e445b3d979115c6cd7dd.png

在WsrmServerPayloadContext的readEndpt方法中直接就能发现存在xml解析,其中使用DocumentBuilderFactory类作为解析工厂类,这里并没有添加任何feature限制外部实体的加载,所以只需要关心var14是否可控

1a5de1df86fb5d3045add638bcb75761.png

那么在WsrmServerPayloadContext的readExternal方法调用了readEndpt方法,该方法将在反序列化时自动调用,与通常的readObject相类似,而readEndpt中的var14又来自此时的var1(payload 输入流),所以满足可控条件

d60702389a229c20f47649596a3c5127.png

那么从反序列化到xxe的入口点就是如此,接下来只需要构造满足条件的反序列化数据流通过t3协议发送到weblogic的7001端口即可,找到该类的序列化时调用的函数然后跟踪其输出流就行

a4d09848da1f521f1417bc7200c9a557.png

在writeExternal中判断this.fromEndpt不为null时,调用writeEndpt传入输出流, 可以看到this.fromEndpt实际上是EndpointReference的实例,根据方法名以及入口参数盲猜要将该类的实例写进输出流

6b95cac5a1f0c0cdeae4a1695a4a7bb8.png

那么实际上该函数的功能也主要是通过XMLSerializer的serlialize处理EndpointReference的返回值(Element类的实例)后最终存储为字节数组,并在输出流中写入字节数组和其长度,那么XMLSerializer的serialize方法的实现了3种重载,分别可以传入Element,DocumentFragment,Document,那么实际上构造xml的payload时如果使用Element型的重载,那么实际上写入的序列化数据中包含的xml数据外部实体将被解析最终只留下节点元素,所以为了在payload中保留完整的xml的payload,需要使用Document型的重载,因此这里需要重写WsrmServerPayloadContext的writeEndpt方法即可,我们只需删除jar包中对应的class字节码文件重新打包引入,然后本地新建与其包名类名一致的该类即可,从而定制如我们目标相符合的序列化数据(接下来几个weblogic的xxe payload本地构造方法均与此一样)

124aa019995a4ef2023769933a588bc9.png

构造结构如上图所示,我们知道DocumentBuilder的parse处理xml文件后将返回Document,因此我们只需要将处理结果再传入seriali

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值