Apache OFBiz XML-RPC反序列化漏洞分析
Apache XML-RPC
是一个Java实现的XML-RPC库,基于HTTP传输的XML实现RPC,最后一个版本为2020年2月6日发布的3.1.3。
Apache OFBiz
是一个企业自动化流程开源框架,提供ERP、CRM、电商应用程序。
漏洞分析
CVE-2016-5003
- 影响 Apache XML-RPC <= 3.1.3
根据Data Types官方文档,设置了enabledForExtensions
属性时,支持以http://ws.apache.org/xmlrpc/namespaces/extensions
作为命名空间的serializable
标签,用于传输以Base64编码的序列化字节数组。
0ang3el在博客中给出了POC截图,看到以rO0AB
开头的Base64编码序列化数据,对应十六进制Java原生序列化数据的aced0005
魔数头。
全局搜索readObject
,看到SerializableParser#getResult
调用super.getResult()
获取字节数组后反序列化。SerializableParser
继承自ByteArrayParser
。
ByteArrayParser
在startElement
方法中解码Base64编码的字节数组,在endElement
方法中调用了setResult
方法。ByteArrayParser
继承自TypeParserImpl
。
TypeParserImpl
中实现了getResult
、setResult
方法。查找对ByteArrayParser#startElement
的调用,这里的接口会出现很多干扰结果。世上无难事只要肯放弃,反向跟进因为动态实现而路径爆炸后,试试正向跟进。
定位到XmlRpcRequestParser
,类注释表示它是对XmlRpcClient
请求的解析器。从startElement
方法的判断逻辑可以猜测,各级XML标签分别为methodCall
、methodName
、params
、param
、value
,与POC截图吻合。
endElement
方法同理,两个方法分别调用了从父类RecursiveTypeParserImpl
继承而来的startValueTag
、endValueTag
方法。代表Map对象的struct
标签则会进入default
分支调用startElement
、endElement
方法(SerializerTest#testMapParam
测试用例可以看到相应XML)。
在RecursiveTypeParserImpl#startElement
中看到了对TypeParser
接口实例的调用。
跟进getParser
方法可知pLocalName
为serializable
时调用SerializableParser
。
查找对RecursiveTypeParserImpl#startElement
的调用并筛选后,看到SerializableSerializer#write
在序列化时写入了相应的pLocalName
。
CVE-2019-17570
- 影响 3.1 <= Apache XML-RPC <= 3.1.3
客户端解析响应数据时的反序列化,逻辑类似。
CVE-2020-9496
- 影响 Apache OFBiz < 17.12.04
全局搜索org.apache.xmlrpc
,定位到XmlRpcEventHandler#getRequest
,一路反向跟进得到调用链。
1 | org.apache.ofbiz.webapp.event.XmlRpcEventHandler#execute |
OFBiz根据framework/component-load.xml
创建Context,并在相应的WEB-INF/web.xml
中指定url-pattern
。
ControlServlet#doGet
中this.getRequestHandler
方法实际调用了RequestHandler#getRequestHandler
方法。
一直跟到RequestHandler
构造方法,由ConfigXMLReader#getControllerConfigURL
获取配置文件路径后,经EventFactory
构造方法创建对应的handler。
webtools
的配置文件/WEB-INF/controller.xml
中存在<request-map uri="xmlrpc"
,并且include了common-controller.xml
,再进一步include了handlers-controller.xml
。
定义了xmlrpc
对应XmlRpcEventHandler
,即sink所在类。
OFBIZ-11716增加了鉴权配置。
OFBIZ-12332增加了过滤关键字的Filter
CVE-2023-49070
- 影响 Apache OFBiz < 18.12.10
RequestHandler#doRequest
判断securityAuth
后,执行checkLoginEvent
。
进入if分支的条件是security
标签auth
属性的值为true
,对应上文OFBIZ-11716
增加的鉴权。
根据webcommon/WEB-INF/common-controller.xml
找到LoginWorker#extensionCheckLogin
,其进一步调用了LoginWorker#checkLogin
。
进入343行的if分支则会返回error
,否则会顺序执行并返回success
。判断条件是逻辑或,跟进login
方法。
requirePasswordChange
参数为Y
且unpwErrMsgList
不为空时,会进入三目运算符分支返回非error
字符串。
看到438行/441行,只要用户名/密码为空就存在add,满足if条件绕过身份认证。
至于OFBIZ-12332
增加的路径判断,RequestHandler#doRequest
业务功能中用了HttpServletRequest#getPathInfo
获取路径,而Filter
用的HttpServletRequest#getRequestURI
,是经典的路径绕过。
另外对</serializable
的检查,改改设置XML命名空间的位置,给标签加个前缀即可绕过。
1 | POST /webtools/control/xmlrpc?USERNAME=&PASSWORD=&requirePasswordChange=Y HTTP/1.1 |
OFBIZ-12812删除了Apache XML-RPC
相关库和代码
参考链接
Beware of ws-xmlrpc library in your Java App
Apache - Deserialization of Untrusted Data in XML-RPC (CVE-2019-17570)
GHSL-2020-069: Unsafe deserialization of XMLRPC arguments in ApacheOfBiz - CVE-2020-9496