最新的Apache OFBiz XML-RPC 反序列化漏洞,讲讲它的前世今生。
Apache OFBiz是一个开源的开发框架,它提供了一些预置的逻辑用于开发企业级的业务流程。早在2020年,Apache OFBiz就曾出现过一个反序列化漏洞(CVE-2020-9496),问题出现在XML-RPC这个组件中。
XML-RPC也是Apache基金会旗下的一个项目,但基本上在2010年前后就不更新了,历史上出现过多个反序列化漏洞(如CVE-2016-5003、CVE-2019-17570),但都没有被修复。Apache OFBiz由于使用了XML-RPC组件所以受到了影响。
CVE-2020-9496这个漏洞在Vulhub中也有环境:https://github.com/vulhub/vulhub/tree/master/ofbiz/CVE-2020-9496。利用方式很简单,向/webtools/control/xmlrpc
接口发送POST包,包含XML格式的RPC请求体。其中,<serializable>
这个对象中包含了base64格式的Payload:
2020年5月,漏洞出现后,OFBiz官方在 https://github.com/apache/ofbiz-framework/commit/d955b03fdc226d600d81d19d273e773f84b5c000 这个提交中提交了第一次补丁,这个补丁的作用是为XML-RPC的接口增加鉴权:
很显然这个补丁并不能完全解决问题,但至少提高了漏洞利用门槛,不再是“Pre-Auth RCE”漏洞。
在2021年10月,一个叫Jie Zhu的人向官方反应了这个“Post-Auth RCE漏洞”,可以在当时最新的17.12.08版本上复现。官方也很无奈呀:这个漏洞本不是OFBiz导致,但因为XML-RPC不再维护,无法从根本上修复这个漏洞。
官方只能退而求其次,使用filter的方式对请求做了一次检测,只要发现Body中存在</serializable>
这个关键字就报错:
这个修复方法很快被Jie Zhu绕过,因为攻击者可以增加一个空格,使用</serializable >
的方式绕过检测。
于是,官方在 https://github.com/apache/ofbiz-framework/commit/25293e4cf6f334a2ae33b3041acba45113dddce9 这个提交中再次进行加固,将检测关键词更改为</serializable
:
那么,最新的CVE-2023-49070又是怎么回事呢?其实,CVE-2023-49070就是对上述官方提供的两个加固方式进行了绕过:
</serializable
这个关键词的检测有了这两个绕过,最新的漏洞重新变回一个Pre-Auth RCE漏洞。
那么,来看看这两个补丁都是怎么被绕过的。
使用Vulhub启动CVE-2023-49070的环境,然后下载Apache OFBiz源码,切换到7935a14627a86325440516ac6b892a5f9d635e4d
这个commit。在IDEA中打开,并增加远程调试的配置,端口是Vulhub的5005端口。
由于前面已经分析出补丁的位置,我们直接在org.apache.ofbiz.base.util.CacheFilter#doFilter
这个函数中下断点。
然后,先发送老的CVE-2020-9496的POC,已经断下:
这个函数里有两个关键的if语句,第一个if语句判断当前的path是不是等于/control/xmlrpc
,第二个if语句判断body中是否包含</serializable
,如果两个if语句都满足,则filter退出,不执行后续逻辑。
在Java中,我们多次提到,部分中间件如Tomcat可以通过;
的方式可以在路径中增加Matrix Parameters:https://www.baeldung.com/cs/url-matrix-vs-query-parameters。
所以,我们也可以尝试在XML-RPC请求的路径中增加分号:/webtools/control/xmlrpc;/
。
断点再次断下,此时uri.toLowerCase()
已经变成/control/xmlrpc;/
,再不等于/control/xmlrpc
,绕过了这里的限制:
第一个限制绕过,服务器返回了登录页面:
接着,我们还需要绕过认证的限制,否则漏洞还是一个Post-Auth RCE。
我们在org.apache.ofbiz.webapp.control.LoginWorker#checkLogin
下断点,这个函数用于检查用户是否登录:
第343行有一个很关键的判断"error".equals(login(request, response))
,当login()
函数的返回值等于error
时进入if语句。
那么,单步进入login()
函数看看逻辑。这个函数中有这样几行:
requirePasswordChange
这个参数的值如果等于Y
,则返回requirePasswordChange
,否则返回error
。
而前面的逻辑,只要login(request, response)
返回的不是error,则认为认证成功。很显然,这里存在一个逻辑Bug。
所以,只要我们在发送XML-RPC请求的时候,将requirePasswordChange
设置成Y
,即可绕过权限检测,最后的POC就呼之欲出了:
抛开XML-RPC这个组件的漏洞来看,requirePasswordChange
这个逻辑Bug本来就是Apache OFBiz的一个认证绕过的漏洞,只是这个漏洞被用于访问XML-RPC了。
在最新发行版18.12.10中,对于CVE-2023-49070的修复方式是直接移除了XML-RPC相关的逻辑:https://github.com/apache/ofbiz-framework/commit/c59336f604f503df5b2f7c424fd5e392d5923a27。
但是认证绕过的问题其实并没有处理,虽然程序后续逻辑中仍然有垂直权限相关的检查,但这一步的权限绕过,仍然导致可以看到一些非预期的页面,比如
这个权限绕过的问题,仍然有待深入研究。
喜欢这篇文章,点个在看再走吧~
加入「代码审计」,学习更多安全知识。一次付费,终身学习免续费。