Apache OFBiz 命令执行漏洞分析(CVE-2024-32113、CVE-2024-36104)
原创 元亨-blckder02 2024-06-21 17:33 浙江
通过目录遍历可以绕过授权验证实现命令执行。
1.前言
https://issues.apache.org/jira/browse/OFBIZ-13006
https://lists.apache.org/thread/w6s60okgkxp2th1sr8vx0ndmgk68fqrd
https://issues.apache.org/jira/browse/OFBIZ-13092
https://lists.apache.org/thread/sv0xr8b1j7mmh5p37yldy9vmnzbodz2o
CVE-2024-32113:
Apache OfBiz < 18.12.13
CVE-2024-36104:
Apache OfBiz < 18.12.14
2. 环境搭建
新增JAR Application,添加指定ofbiz.jar路径。


3. 漏洞复现
(详情可回顾:Apache OFBiz 命令执行漏洞分析)
直接构造 18.12.14 及之前版本通杀的路径 payload,不需要进行目录遍历。
/webtools/control/ListTimezones/ProgramExport?groovyProgram='calc.exe'.execute() 


所以 18.12.13 和 18.12.14 版本的 payload 需要对 groovyProgram 参数内容进行编码传入来绕过黑名单校验。
/webtools/control/ListSetCompanies/ProgramExportgroovyProgram=\u0027\u0063\u0061\u006c\u0063\u002e\u0065\u0078\u0065\u0027\u002e\u0065\u0078\u0065\u0063\u0075\u0074\u0065\u0028\u0029

uri ListTimezones的 auth 改为了 true,不能进行利用了,不过其他的 uri 仍然可以利用。

4. 漏洞分析
接下来以 18.12.12 版本为例分析看看,如果请求的路径为/webtools/control/ListTimezones/./ProgramExport,在 ControlFilter.doFilter() 中,getRequestURI() 首先获取到的是/control/ListTimezones/./ProgramExport,经过规范化后去除了其中的.,变成了/control/ListTimezones/ProgramExport。
所以特殊符号在这一步都会被过滤掉,18.12.13 以及 18.12.14 版本的补丁都在围绕这一块代码进行修改补充,不过这并不是关键所在。

rmaps 为ListSetCompanies对应的 requestMap,其中 securityAuth 属性为 false。

此时 eventReturn 的值是 null,740 行的逻辑表达式为 true,视图名称得到 overrideViewUri 的值ProgramExport,关键就在这里,将路径的第二部分作为视图名称赋值,后面就是进行视图渲染。

获取传入的 groovyProgram 参数值,从 \framework\webtools\webapp\webtools\WEB-INF\controller.xml 中找到 ProgramExport 的视图信息定义在 component://webtools/widget/EntityScreens.xml#ProgramExport 文件中。

获取到 screen 类型的视图处理器。
一直跟进,从 EntityScreens.xml 中获取到了ProgramExport对应的脚本文件位置 component://webtools/groovyScripts/entity/ProgramExport.groovy ,当遍历到此文件时跟进。

检测到.groovy后缀,进入 ProgramExport.groovy 文件,执行 groovyProgram 参数的命令。

5. 补丁分析
主要体现在将ListTimezones的 auth 改为 true,黑名单里增加execute关键字,ControlFilter.doFilter() 中校验了规范化前后的 url 是否一致,以此来判断 url 是否含有特殊字符。
18.12.14版本:
网上使用的 payload 是将.换为%2e或;来绕过 18.12.13 版本的修复代码,于是官方在 18.12.14 版本的 ControlFilter.doFilter() 中添加过滤了%2e和;,不过仍然没有修复到问题关键。