引言
CVE-2024-25065 是一个存在于 Apache OFBiz 18.12.12 之前版本的漏洞。这是一个路径遍历漏洞,它通过 hasBasePermission()
方法中的 contextPath
变量允许身份验证绕过。
什么是 Apache OFBiz?
Apache OFBiz(Open For Business)是一个开源企业资源规划(ERP)和电子商务系统,提供一整套业务应用程序以自动化和集成各种商业流程。OFBiz 使用 Java 和 XML 构建,具有高度的可定制性和可扩展性,适用于中小型企业(SME)以及具有复杂流程的公司。其模块化设计包括用于会计、库存管理、生产、订单管理和采购的 ERP 模块,以及电子商务、客户关系管理(CRM)和人力资源功能。OFBiz 支持强大的数据模型和面向服务的架构(SOA),使得业务逻辑和流程的管理无缝进行。作为 Apache 软件基金会的项目,OFBiz 受益于一个庞大的开发者社区和丰富的文档,确保持续的支持和协作。OFBiz 采用 Apache Tomcat、Apache Derby、Freemarker 和 Groovy 等关键技术,为希望简化操作的企业提供集成解决方案,无需支付昂贵的许可费用。
补丁差异
修复此漏洞的提交位于以下文件中
framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
以下代码块被添加:
该代码旨在确保 contextPath
变量是一个有效的、标准化的 URI 字符串。标准化 UR 过程包括去除冗余部分(例如 .
和 ..
)、解析相对路径,以及将 URI 转换为标准格式。显然,这涉及到 contextPath
中的路径遍历漏洞,如 CVE 描述中所述。
测试实验室
由于在 18.12.12 之前的版本存在漏洞,因此大多数先前版本在构建时可能会出现问题。其中问题最少的版本是 18.12.05,可以从此处下载。
首先,需要 OpenJDK-8:
# 下载 OpenJDK 8
wget https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz
# 解压缩
tar -xvf openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz
# 移动到 JVM 文件夹
sudo mv java-se-8u41-ri /usr/lib/jvm/openjdk-8
# 添加到 PATH
export JAVA_HOME=/usr/lib/jvm/openjdk-8
export PATH=$JAVA_HOME/bin:$PATH
# 设置更新替代方案系统为 OpenJDK 8
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/openjdk-8/bin/java 1
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/openjdk-8/bin/javac 1
# 选择 OpenJDK 8 版本
sudo update-alternatives --config java
sudo update-alternatives --config javac
# 验证安装
java -version
现在是构建我们的 OFBiz 版本的时候了:
# 使用以下命令
./gradlew cleanAll loadAll
修复问题
在构建过程中,可能会遇到一些问题,例如缺少gradle-wrapper.jar
文件。
- 可以通过以下命令解决此问题:
gradle wrapper
- 或者手动下载:
# 手动下载
wget https://services.gradle.org/distributions/gradle-6.8.3-all.zip
- 另一个问题可能与 ca-certificates 有关,可以通过更新或重新安装来轻松修复它:
sudo apt install --reinstall ca-certificates
运行 OFBiz
以调试模式运行 OFBiz:
./gradlew ofbiz --debug-jvm
注:在调试模式下运行时,可能会遇到与_JAVA_OPTIONS
相关的问题:
- 如果遇到此问题,可以简单地取消设置它:
unset _JAVA_OPTIONS
- 或者将其设置为默认设置:
export _JAVA_OPTIONS="-Dawt.useSystemAAFontSettings=on -Dswing.aatext=true"
分析
根据补丁差异,我们了解到问题存在于LoginWorker.java
,特别是在hasBasePermission()
方法下。下面我们将详细分析该方法的代码。
静态分析
首先,我们来看一下该方法的定义:
public static boolean hasBasePermission(GenericValue userLogin, HttpServletRequest request)
该方法接受两个参数:GenericValue userLogin
(表示用户的登录信息)和HttpServletRequest request
(表示HTTP请求对象,提供对请求参数、属性和其他数据的访问)。
Security security = (Security) request.getAttribute("security");
该方法从HttpServletRequest
中检索Security
对象,以用于权限检查。
if (security != null) {
接下来,检查Security
对象是否为null。如果不为null,将执行以下操作:
ServletContext context = request.getServletContext();
String serverId = (String) context.getAttribute("_serverId");
String contextPath = request.getContextPath();
这里,它从Servlet上下文中检索serverId
和contextPath
。serverId
唯一标识服务器实例,而contextPath
对于识别Web应用程序的配置和要处理的端点是必要的。
if (UtilValidate.is