From 3c44a547d0f35dca96cad3fe1fe01d68b26f13c9 Mon Sep 17 00:00:00 2001 From: Jacopo Cappellato Date: Mon, 20 Apr 2026 12:18:32 +0200 Subject: [PATCH 1/4] Fixed: Escape username in DN template --- .../apache/ofbiz/common/login/LdapAuthenticationServices.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/common/src/main/java/org/apache/ofbiz/common/login/LdapAuthenticationServices.java b/framework/common/src/main/java/org/apache/ofbiz/common/login/LdapAuthenticationServices.java index 14c01a1ce50..f2cef68a8ee 100644 --- a/framework/common/src/main/java/org/apache/ofbiz/common/login/LdapAuthenticationServices.java +++ b/framework/common/src/main/java/org/apache/ofbiz/common/login/LdapAuthenticationServices.java @@ -26,6 +26,7 @@ import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; +import javax.naming.ldap.Rdn; import javax.transaction.Transaction; import org.apache.ofbiz.base.crypto.HashCrypt; @@ -75,7 +76,7 @@ public static boolean userLogin(DispatchContext ctx, Map context) { if (UtilValidate.isEmpty(dn)) { String dnTemplate = (String) env.get("ldap.dn.template"); if (dnTemplate != null) { - dn = dnTemplate.replace("%u", username); + dn = dnTemplate.replace("%u", Rdn.escapeValue(username)); } if (Debug.verboseOn()) { Debug.logVerbose("Using DN template: " + dn, MODULE); From 13f317556b387210c89c5569ccabc8955b0b518f Mon Sep 17 00:00:00 2001 From: Jacopo Cappellato Date: Mon, 20 Apr 2026 12:58:54 +0200 Subject: [PATCH 2/4] Fixed: Replace ObjectInputStream with SafeObjectInputStream for safer JDBC object deserialization --- .../java/org/apache/ofbiz/entity/jdbc/JdbcValueHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/entity/src/main/java/org/apache/ofbiz/entity/jdbc/JdbcValueHandler.java b/framework/entity/src/main/java/org/apache/ofbiz/entity/jdbc/JdbcValueHandler.java index 114edcff1de..972146aaccb 100644 --- a/framework/entity/src/main/java/org/apache/ofbiz/entity/jdbc/JdbcValueHandler.java +++ b/framework/entity/src/main/java/org/apache/ofbiz/entity/jdbc/JdbcValueHandler.java @@ -37,6 +37,7 @@ import javax.sql.rowset.serial.SerialBlob; import org.apache.ofbiz.base.util.Debug; +import org.apache.ofbiz.base.util.SafeObjectInputStream; /** * An object that handles getting/setting column values in JDBC @@ -617,7 +618,7 @@ public Object getValue(ResultSet rs, int columnIndex) throws SQLException { if (bis == null) { return null; } - in = new ObjectInputStream(bis); + in = new SafeObjectInputStream(bis); return in.readObject(); } catch (Exception e) { throw new SQLException(e); From 32037a6aa12b8c2e853f29712446521725d6ad8e Mon Sep 17 00:00:00 2001 From: Jacopo Cappellato Date: Mon, 20 Apr 2026 16:48:41 +0200 Subject: [PATCH 3/4] Fixed: Enhance parsing security by disabling external entity resolution --- .../java/org/apache/ofbiz/base/util/string/UelFunctions.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/base/src/main/java/org/apache/ofbiz/base/util/string/UelFunctions.java b/framework/base/src/main/java/org/apache/ofbiz/base/util/string/UelFunctions.java index 33730cfedbe..9c9a8b18040 100644 --- a/framework/base/src/main/java/org/apache/ofbiz/base/util/string/UelFunctions.java +++ b/framework/base/src/main/java/org/apache/ofbiz/base/util/string/UelFunctions.java @@ -368,6 +368,11 @@ public static Document readHtmlDocument(String str) { URL url = FlexibleLocation.resolveLocation(str); if (url != null) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + factory.setXIncludeAware(false); + factory.setExpandEntityReferences(false); DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.parse(url.openStream()); document.getDocumentElement().normalize(); From b53f5c64f39a95807b941e7b83db3eb5ee5fa5ef Mon Sep 17 00:00:00 2001 From: Jacopo Cappellato Date: Mon, 20 Apr 2026 17:48:48 +0200 Subject: [PATCH 4/4] Fixed: Implement path traversal protection in OutputServices --- applications/content/config/ContentUiLabels.xml | 3 +++ .../org/apache/ofbiz/content/output/OutputServices.java | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/applications/content/config/ContentUiLabels.xml b/applications/content/config/ContentUiLabels.xml index d161e2db79f..c3e02181e67 100644 --- a/applications/content/config/ContentUiLabels.xml +++ b/applications/content/config/ContentUiLabels.xml @@ -2089,6 +2089,9 @@ 生成${contentType}是出错:${errorString} 產生${contentType}時出錯:${errorString} + + Rejected output path: "${fileName}" resolves outside the allowed directory "${filePath}" + Required field ${requiredField} is missing in simple method call ${resourceDescription} Le champ requis ${requiredField} est manquant dans l'appel d'une méthode simple : ${resourceDescription} diff --git a/applications/content/src/main/java/org/apache/ofbiz/content/output/OutputServices.java b/applications/content/src/main/java/org/apache/ofbiz/content/output/OutputServices.java index 5cf2e8b5c8b..202ec736e10 100644 --- a/applications/content/src/main/java/org/apache/ofbiz/content/output/OutputServices.java +++ b/applications/content/src/main/java/org/apache/ofbiz/content/output/OutputServices.java @@ -218,7 +218,7 @@ public static Map createFileFromScreen(DispatchContext dctx, Map Map screenContext = UtilGenerics.cast(serviceContext.remove("screenContext")); String contentType = (String) serviceContext.remove("contentType"); String filePath = (String) serviceContext.remove("filePath"); - String fileName = (String) serviceContext.remove("fileName"); + String fileName = new File((String) serviceContext.remove("fileName")).getName(); if (UtilValidate.isEmpty(screenContext)) { screenContext = new HashMap<>(); @@ -265,7 +265,12 @@ public static Map createFileFromScreen(DispatchContext dctx, Map if (UtilValidate.isEmpty(filePath)) { filePath = EntityUtilProperties.getPropertyValue("content", "content.output.path", "/output", delegator); } - File file = new File(filePath, fileName); + File baseDir = new File(filePath).getCanonicalFile(); + File file = new File(baseDir, fileName).getCanonicalFile(); + if (!file.toPath().startsWith(baseDir.toPath())) { + return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ContentRenderingPathTraversalError", + UtilMisc.toMap("fileName", fileName, "filePath", filePath), locale)); + } FileOutputStream fos = new FileOutputStream(file); fos.write(baos.toByteArray());