[ 
https://issues.apache.org/jira/browse/WW-5184?focusedWorklogId=778707&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-778707
 ]

ASF GitHub Bot logged work on WW-5184:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 06/Jun/22 17:36
            Start Date: 06/Jun/22 17:36
    Worklog Time Spent: 10m 
      Work Description: yasserzamani commented on code in PR #559:
URL: https://github.com/apache/struts/pull/559#discussion_r890375109


##########
core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java:
##########
@@ -354,7 +407,86 @@ protected boolean isExcluded(String paramName) {
         }
         return false;
     }
+    
 
+    public void setAcceptedValuePatterns(String commaDelimitedPatterns) {

Review Comment:
   BTW another methods annotated with `@Inject` as well as some other changes 
are required enabling user to configure these patterns via XML configuration.



##########
core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java:
##########
@@ -354,7 +407,86 @@ protected boolean isExcluded(String paramName) {
         }
         return false;
     }
+    
 
+    public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
+       Set<String> patterns = 
TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
+        if (acceptedValuePatterns == null) {
+            // Limit unwanted log entries (for 1st call, acceptedValuePatterns 
null)
+            LOG.debug("Sets accepted value patterns to [{}], note this may 
impact the safety of your application!", patterns);
+        } else {
+            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware 
that this affects all instances and may impact the safety of your application!",
+                       acceptedValuePatterns, patterns);
+        }
+        acceptedValuePatterns = new HashSet<>(patterns.size());
+        try {
+            for (String pattern : patterns) {
+               acceptedValuePatterns.add(Pattern.compile(pattern, 
Pattern.CASE_INSENSITIVE));
+            }
+        } finally {
+               acceptedValuePatterns = 
Collections.unmodifiableSet(acceptedValuePatterns);
+        }
+    }
+    
+    public void setExcludeValuePatterns(String commaDelimitedPatterns) {
+       Set<String> patterns = 
TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
+        if (excludedValuePatterns == null) {
+            // Limit unwanted log entries (for 1st call, excludedValuePatterns 
null)
+            LOG.debug("Setting excluded value patterns to [{}]", patterns);
+        } else {
+            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware 
that this affects all instances and may impact safety of your application!",
+                       excludedValuePatterns, patterns);
+        }
+        excludedValuePatterns = new HashSet<>(patterns.size());
+        try {
+            for (String pattern : patterns) {
+               excludedValuePatterns.add(Pattern.compile(pattern, 
Pattern.CASE_INSENSITIVE));
+            }
+        } finally {
+               excludedValuePatterns = 
Collections.unmodifiableSet(excludedValuePatterns);
+        }
+    }
+    
+       protected boolean isParamValueExcluded(String value) {
+               if (hasParamValuesToExclude()) {
+                       for (Pattern excludedPattern : excludedValuePatterns) {
+                               if (value != null) {
+                                       if 
(excludedPattern.matcher(value).matches()) {
+                                               LOG.info("Parameter value [{}] 
matches excluded pattern [{}] and will be dropped.", value,

Review Comment:
   same here



##########
core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java:
##########
@@ -311,6 +346,24 @@ private boolean isIgnoredDMI(String name) {
         }
     }
 
+    /**
+     * Validates:
+     * * Value is null/blank
+     * * Value is not excluded
+     * * Value is accepted
+     * 
+     * @param name - Param name (for logging)
+     * @param value - value to check
+     * @return true if accepted
+     */
+    protected boolean acceptableValue(String name, String value) {
+       boolean accepted = (value == null || value.isEmpty() || 
(!isParamValueExcluded(value) && isParamValueAccepted(value)));
+        if (!accepted) {
+            LOG.info("Parameter [{}] was not accepted with value [{}] and will 
be dropped!", name, value);

Review Comment:
   Sorry my failure in previous PR. Could you please log such thing with WARN 
level? as well as other similar places.



##########
core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java:
##########
@@ -354,7 +407,86 @@ protected boolean isExcluded(String paramName) {
         }
         return false;
     }
+    
 
+    public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
+       Set<String> patterns = 
TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
+        if (acceptedValuePatterns == null) {
+            // Limit unwanted log entries (for 1st call, acceptedValuePatterns 
null)
+            LOG.debug("Sets accepted value patterns to [{}], note this may 
impact the safety of your application!", patterns);
+        } else {
+            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware 
that this affects all instances and may impact the safety of your application!",
+                       acceptedValuePatterns, patterns);
+        }
+        acceptedValuePatterns = new HashSet<>(patterns.size());
+        try {
+            for (String pattern : patterns) {
+               acceptedValuePatterns.add(Pattern.compile(pattern, 
Pattern.CASE_INSENSITIVE));
+            }
+        } finally {
+               acceptedValuePatterns = 
Collections.unmodifiableSet(acceptedValuePatterns);
+        }
+    }
+    
+    public void setExcludeValuePatterns(String commaDelimitedPatterns) {
+       Set<String> patterns = 
TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
+        if (excludedValuePatterns == null) {
+            // Limit unwanted log entries (for 1st call, excludedValuePatterns 
null)
+            LOG.debug("Setting excluded value patterns to [{}]", patterns);
+        } else {
+            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware 
that this affects all instances and may impact safety of your application!",
+                       excludedValuePatterns, patterns);
+        }
+        excludedValuePatterns = new HashSet<>(patterns.size());
+        try {
+            for (String pattern : patterns) {
+               excludedValuePatterns.add(Pattern.compile(pattern, 
Pattern.CASE_INSENSITIVE));
+            }
+        } finally {
+               excludedValuePatterns = 
Collections.unmodifiableSet(excludedValuePatterns);
+        }
+    }
+    
+       protected boolean isParamValueExcluded(String value) {
+               if (hasParamValuesToExclude()) {
+                       for (Pattern excludedPattern : excludedValuePatterns) {
+                               if (value != null) {
+                                       if 
(excludedPattern.matcher(value).matches()) {
+                                               LOG.info("Parameter value [{}] 
matches excluded pattern [{}] and will be dropped.", value,
+                                                               
excludedPattern);
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+               return false;
+       }
+
+       protected boolean isParamValueAccepted(String value) {
+               if (hasParamValuesToAccept()) {
+                       for (Pattern excludedPattern : acceptedValuePatterns) {
+                               if (value != null) {
+                                       if 
(excludedPattern.matcher(value).matches()) {
+                                               return true;
+                                       }
+                               }
+                       }
+               } else {
+                       // acceptedValuePatterns not defined so anything is 
allowed
+                       return true;
+               }
+               LOG.info("Parameter value [{}] did not match any 
acceptedValuePattern pattern and will be dropped.", value);

Review Comment:
   and here





Issue Time Tracking
-------------------

    Worklog Id:     (was: 778707)
    Time Spent: 2h 10m  (was: 2h)

> Add optional parameter value check to ParametersInterceptor
> -----------------------------------------------------------
>
>                 Key: WW-5184
>                 URL: https://issues.apache.org/jira/browse/WW-5184
>             Project: Struts 2
>          Issue Type: Improvement
>            Reporter: Brian Andle
>            Priority: Major
>          Time Spent: 2h 10m
>  Remaining Estimate: 0h
>
> It is known that developers utilizing Struts/Freemarker should always  ensure 
> proper sanitization to prevent OGNL/Freemarker evaluation on untrusted user 
> input when %{/$\{ in FTL being passed into Struts tags.
> These patterns aren't always practical to resolve/find especially in legacy 
> code. This isn't a solely a legacy code of course it's just as easy to make a 
> mistake in newer code as well.
> The following would end up rendering 81
> Payload:
> {code:java}
> untrustedInput=%25%7B9%2A9%7D {code}
> FTL:
>  
> {code:java}
> <@s.form theme="simple" action="${untrustedInput}" id="myForm4">
> </@s.form> {code}
>  
> Java:
> {code:java}
>     private String untrustedInput;
>     public String getUntrustedInput() {
>         return untrustedInput;
>     }
>     public void setUntrustedInput(String untrustedInput) {
>         this.untrustedInput = untrustedInput;
>     } {code}
>  
> This ticket is to add an optional `params.excludeValuePatterns` so that 
> ParametersInterceptor can drop incoming parameter itself if the value matches 
> a pattern to be excluded.
>  
> {code:java}
> <param 
> name="params.excludeValuePatterns">.*\$\{.*?\}.*,.*%\{.*?\}.*</param>{code}
>  
> Since this is a pattern and would be executed against the values themselves 
> there is the potential of a performance impact however I since it's optional 
> we shouldn't see any measurable impact when not enabled.
>  
> *NOTE:* I did add a `params.acceptValuePatterns` pattern that is 
> null/disabled by default. This might not ever be used but mimic'd the Pattern 
> matcher the ParametersInterceptor/CookieInterceptor.
>  



--
This message was sent by Atlassian Jira
(v8.20.7#820007)

Reply via email to