问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Apache OFBiz 最新Grovvy代码执行分析(CVE-2024-36104)
漏洞分析
这个月爆出了CVE-2024-36104这个漏洞,实际上CVE-2024-32113和新爆出的CVE-2024-36104应该都是基于webtools/control/ProgramExport这个接口所产生的漏洞,该接口用于后台执行groovy代码,攻击者可以通过恶意的groovy代码实现任意命令执行
前言 == Apache OFBiz是一个开源的开发框架,它提供了一些预制的逻辑用于开发企业级的业务流程。 在今年5、6月份分别爆出了两个目录遍历导致命令执行的漏洞**CVE-2024-32113**和**CVE-2024-36104**   当我在寻找漏洞相关poc的时候,发现很多公众号都放出了关于CVE-2024-32113这个漏洞的相关poc,但是接口都是webtools/control/xmlrpc,实际上这个接口是CVE-2020-9496反序列化漏洞的接口,而且在18.12.10版本之后,OFBiz官方对于这个接口的漏洞修复方法是直接移除了XML-RPC相关的逻辑了,所以部分公众号发布的关于CVE-20240-32113这个漏洞的poc都是不对的  紧着在这个月爆出了CVE-2024-36104这个漏洞,实际上CVE-2024-32113和新爆出的CVE-2024-36104都是基于webtools/control/ProgramExport这个接口所产生的漏洞,该接口用于后台执行groovy代码,攻击者可以通过恶意的groovy代码实现任意命令执行 环境搭建 ==== 这里下载的ofbiz版本为**18.12.14** 安装gradle后,将项目导入到IDEA,执行build后会在build/libs下生成一个ofbiz.jar 然后添加JAR Application,设置JAR的路径后启动就可以开始调试项目了  访问https://127.0.0.1:8443/accounting 能看到登录界面说明搭建成功 CVE-2023-51467分析 ================ 我们先看看CVE-2023-51467这个漏洞,这个漏洞是一个鉴权绕过漏洞,可以实现绕过身份验证机制从而直接调用后台的一些接口,实际上应该也是webtools/control/ProgramExport这个接口漏洞最早的利用方式,这里可以使用**vulhub/ofbiz/CVE-2023-51467**的环境 启动环境后直接发送poc执行id命令,可以看到成功执行命令  现在通过代码来分析一下,Apache OFBiz中,对于登录的验证在org.apache.ofbiz.webapp.control.LoginWorker#checkLogin()下,根据poc详情,只要在登录时提交参数**USERNAME=&PASSWORD=&requirePasswordChange=Y**就能绕过登录 在未登录的情况下,userLogin==null,程序会进入到if语句下,这里的验证逻辑是当返回内容不是error时则为认证成功  这里会判断username和password是否为null,还判断login(request, response)的返回值是否为error  在login()方法下首先会判断username和password是否为空,如果为空的话就给unpwErrMsgList添加一个值,接着会判断requirePasswordChange是否等于Y,当requirePasswordChange=Y成立时,就会将requirePasswordChange的值赋为true 程序执行到return语句时,由于requirePasswordChange为true,所以login()返回的内容为requirePasswordChange ```java return requirePasswordChange ? "requirePasswordChange" : "error"; ```  返回到checkLogin()中,由于if条件不成立,继续向下执行到最后直接返回success,所以就能绕过checkLogin()的身份认证  官方为了修复这个漏洞,发布了18.12.11版本,现在来看看官方是如何修复的,修复版本改用UtilValidate.isEmpty()来判断参数的值是否为空  新漏洞分析 ===== 没有找到有关CVE-2024-32113这个漏洞的相关文章,但是找到了CVE-2024-36104的相关poc,关于漏洞的描述是由于在controlfilter类中对路径限制不当导致攻击者能够绕过后台功能点的身份验证 **下面是找到的在网上公开的poc:** [https://mp.weixin.qq.com/s/tsG1wbKqGs\_yyzQhJr6ZLw](https://mp.weixin.qq.com/s/tsG1wbKqGs_yyzQhJr6ZLw) groovyProgram的内容是unicode加密后的 ```java POST /webtools/control/forgotPassword/%2e/%2e/ProgramExport HTTP/1.1 Host: x.x.x.x User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35 Connection: close Content-Length: 262 Content-Type: application/x-www-form-urlencoded user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_14\_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15 Accept-Encoding: gzip groovyProgram=\\u0074\\u0068\\u0072\\u006f\\u0077\\u0020\\u006e\\u0065\\u0077\\u0020\\u0045\\u0078\\u0063\\u0065\\u0070\\u0074\\u0069\\u006f\\u006e\\u0028\\u0027\\u0069\\u0064\\u0027\\u002e\\u0065\\u0078\\u0065\\u0063\\u0075\\u0074\\u0065\\u0028\\u0029\\u002e\\u0074\\u0065\\u0078\\u0074\\u0029\\u003b ``` 在最新发布的18.12.14版本中官方也是在controlfilter中添加了对;和%2e的过滤 <https://github.com/apache/ofbiz-framework/commit/d33ce31012>  **但是发现其中也存在一些问题,接下来使用最新版本18.12.14来进行调试** 当利用上面的poc发送请求的时候,发现是能够成功执行命令的 尝试在不使用%2e特殊字符,直接请求/webtools/control/forgotPassword/ProgramExport接口的情况下发现也可以绕过身份验证调用后台接口  将断点下在ProgramExport.gvooy下 然后向webtools/control/forgotPassword/ProgramExport接口发送请求,可以获取到调用栈  从调用栈中可以看到请求首先经过一系列的filter,先跟进到ControlFilter#dofilter()下 红框里的代码是官方在18.14.13版本之后新增加的,在这里对我们的请求没有限制,程序继续向下执行  在这里主要关注的点是为什么请求的是/webtools/control/forgotPassword/ProgramExport接口时,但是实际调用的是ProgramExport接口,而且能利用forgotPassword来绕过身份验证 具体的处理逻辑从webapp.control.ControlServlet#doGet()开始,该方法主要是做请求预处理,包括获取用户session信息、设置响应头,接着就会进入到RequestHandler.doRequest() 程序首先会解析WEB-INF/common-controller.xml配置文件,获取request-map标签的相关信息,在security标签中保存了接口是否需要鉴权的信息,当该接口无需身份验证就能访问时auth的值就为false,从下图中我们可以看到forgotPassword是无需鉴权的  首先跟进到RequestHandler.doRequest()第286行下面,系统会通过所请求接口requestUri去生成一个requestMap对象,该对象有一个属性为securityAuth,该属性的值是从commom-controller.xml中获取的,保存的是security标签里auth的值  向上看看requestUri的值是如何得到的,往上在第274行可以看到path经过getRequestUri()之后得到requestUri,在getRequestUri中将path以/为分隔符分开,接着返回list\[0\]也就是forgotPassword   得到了requestUri之后,接着看后面一行调用getOverrideViewUri(),这个方法返回了ProgranExport保存在overrideViewUri变量中,这个在后面会用到   接着继续向下执行到第480行,如果requestMap.security的值为true的话,就会进入到if语句,调用到下面的this.runEvent(request,response,checkLoginEvent,null,”security-auth”),这行代码实际上会调webapp.control.LoginWorker#checkLogin()进行用户身份验证  由于我们的requestUri是forgotPassword,所以得到的requestMap.securityAuth为False,所以这里不会进入到if语句里,也就绕过了身份验证 继续向下执行到第717行,首先对nextRequestResponse.type的值进行判断,当type的值为view时进入到renderView(),通过调试可以看到nextRequestResponse.type=view,程序是会执行到739行的   这里就用到了上面提到的overrideViewUri变量,最后得到viewName的值是ProgramExport,进入renderView()之后就开始处理业务逻辑了  **以上就是关于Apache OFBiz漏洞的分析,看到有错误的地方,麻烦师傅们指出来下!!**
发表于 2024-06-14 10:51:16
阅读 ( 32219 )
分类:
漏洞分析
1 推荐
收藏
0 条评论
请先
登录
后评论
kakakakaxi
4 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!