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