This is an automated email from the ASF dual-hosted git repository.

jleroux pushed a commit to branch release18.12
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/release18.12 by this push:
     new 50fc66c  Fixed: Secure the uploads (OFBIZ-12080)
50fc66c is described below

commit 50fc66c8e051947ae7f664a68c344e7b41930722
Author: Jacques Le Roux <jacques.le.r...@les7arts.com>
AuthorDate: Sun Feb 20 15:39:11 2022 +0100

    Fixed: Secure the uploads (OFBIZ-12080)
    
    Last commits put in an issue in DataServices.java and 
GroovyBaseScript.groovy.
    I should have used SecuredUpload::isValidFileName with dataResourceName and
    SecuredUpload::isValidFile  with objectInfo. This fixes that.
    
    Also fixes formatting checkstyle issues in SecuredUpload class and move 
allow
    all and check line length in right places (it's about content)
---
 .../apache/ofbiz/content/data/DataServices.java    | 21 +++++++++++++++---
 .../org/apache/ofbiz/security/SecuredUpload.java   | 25 +++++++++++-----------
 .../ofbiz/service/engine/GroovyBaseScript.groovy   | 20 ++++++++++++-----
 3 files changed, 46 insertions(+), 20 deletions(-)

diff --git 
a/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
 
b/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
index 2bd71c1..cec71ac 100644
--- 
a/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
+++ 
b/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
@@ -199,12 +199,27 @@ public class DataServices {
     public static Map<String, Object> createFileNoPerm(DispatchContext dctx, 
Map<String, ? extends Object> rcontext) throws IOException,
             ImageReadException {
         String originalFileName = (String) rcontext.get("dataResourceName");
+        String fileNameAndPath = (String) rcontext.get("objectInfo");
         Delegator delegator = dctx.getDelegator();
         Locale locale = (Locale) rcontext.get("locale");
-        if (!SecuredUpload.isValidFile(originalFileName, "All", delegator)) {
-            String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", "SupportedTextFileFormats", 
locale);
-            return ServiceUtil.returnError(errorMessage);
+        File file = new File(fileNameAndPath);
+        if (!originalFileName.isEmpty()) {
+            // Check the file name
+            if 
(!org.apache.ofbiz.security.SecuredUpload.isValidFileName(originalFileName, 
delegator)) {
+                String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", 
"SupportedFileFormatsIncludingSvg", locale);
+                return ServiceUtil.returnError(errorMessage);
+            }
+            // TODO we could verify the file type (here "All") with 
dataResourceTypeId. Anyway it's done with isValidFile()
+            // We would just have a better error message
+            if (file.exists()) {
+                // Check if a webshell is not uploaded
+                if 
(!org.apache.ofbiz.security.SecuredUpload.isValidFile(fileNameAndPath, "All", 
delegator)) {
+                    String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", 
"SupportedFileFormatsIncludingSvg", locale);
+                    return ServiceUtil.returnError(errorMessage);
+                }
+            }
         }
+
         Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
         context.put("skipPermissionCheck", "true");
         return createFileMethod(dctx, context);
diff --git 
a/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java 
b/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java
index 364c066..bbace32 100644
--- 
a/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java
+++ 
b/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java
@@ -108,23 +108,12 @@ public class SecuredUpload {
     }
 
     public static boolean isValidFileName(String fileToCheck, Delegator 
delegator) throws IOException {
-        // Allow all
-        if 
(("true".equalsIgnoreCase(EntityUtilProperties.getPropertyValue("security", 
"allowAllUploads", delegator)))) {
-            return true;
-        }
-
         // Prevents double extensions
         if (StringUtils.countMatches(fileToCheck, ".") > 1) {
             Debug.logError("Double extensions are not allowed for security 
reason", MODULE);
             return false;
         }
 
-        // Check max line length, default 10000
-        if (!checkMaxLinesLength(fileToCheck)) {
-            Debug.logError("For security reason lines over " + 
MAXLINELENGTH.toString() + " are not allowed", MODULE);
-            return false;
-        }
-
         String imageServerUrl = 
EntityUtilProperties.getPropertyValue("catalog", "image.management.url", 
delegator);
         Path p = Paths.get(fileToCheck);
         boolean wrongFile = true;
@@ -197,12 +186,24 @@ public class SecuredUpload {
      * @throws ImageReadException
      */
     public static boolean isValidFile(String fileToCheck, String fileType, 
Delegator delegator) throws IOException, ImageReadException {
+        // Allow all
+        if 
(("true".equalsIgnoreCase(EntityUtilProperties.getPropertyValue("security", 
"allowAllUploads", delegator)))) {
+            return true;
+        }
 
+        // Check the file name
         if (!isValidFileName(fileToCheck, delegator)) {
             return false;
         }
 
-        // Check the the file content
+        // Check the file content
+
+        // Check max line length, default 10000
+        if (!checkMaxLinesLength(fileToCheck)) {
+            Debug.logError("For security reason lines over " + 
MAXLINELENGTH.toString() + " are not allowed", MODULE);
+            return false;
+        }
+
         if (isExecutable(fileToCheck)) {
             deleteBadFile(fileToCheck);
             return false;
diff --git 
a/framework/service/src/main/groovy/org/apache/ofbiz/service/engine/GroovyBaseScript.groovy
 
b/framework/service/src/main/groovy/org/apache/ofbiz/service/engine/GroovyBaseScript.groovy
index 41be1a9..672fa43 100644
--- 
a/framework/service/src/main/groovy/org/apache/ofbiz/service/engine/GroovyBaseScript.groovy
+++ 
b/framework/service/src/main/groovy/org/apache/ofbiz/service/engine/GroovyBaseScript.groovy
@@ -55,14 +55,24 @@ abstract class GroovyBaseScript extends Script {
                     : this.binding.getVariable('parameters').locale
         }
         if (serviceName.equals("createAnonFile")) {
-            String dataResourceName = inputMap.get("dataResourceName")
-            File file = new File(dataResourceName)
-            if (file.exists()) {
-                // Check if a webshell is not uploaded
-                if 
(!org.apache.ofbiz.security.SecuredUpload.isValidFile(dataResourceName, "All", 
delegator)) {
+            String fileName = inputMap.get("dataResourceName")
+            String fileNameAndPath = inputMap.get("objectInfo")
+            File file = new File(fileNameAndPath)
+            if (!fileName.isEmpty()) {
+                // Check the file name
+                if 
(!org.apache.ofbiz.security.SecuredUpload.isValidFileName(fileName, delegator)) 
{
                     String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", 
"SupportedFileFormatsIncludingSvg", inputMap.locale)
                     throw new ExecutionServiceException(errorMessage)
                 }
+                // TODO we could verify the file type (here "All") with 
dataResourceTypeId. Anyway it's done with isValidFile()
+                // We would just have a better error message
+                if (file.exists()) {
+                    // Check if a webshell is not uploaded
+                    if 
(!org.apache.ofbiz.security.SecuredUpload.isValidFile(fileNameAndPath, "All", 
delegator)) {
+                        String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", 
"SupportedFileFormatsIncludingSvg", inputMap.locale)
+                        throw new ExecutionServiceException(errorMessage)
+                    }
+                }
             }
         }
         Map serviceContext = dctx.makeValidContext(serviceName, 
ModelService.IN_PARAM, inputMap)

Reply via email to