This is an automated email from the ASF dual-hosted git repository.
jleroux pushed a change to branch release18.12 in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git. from bbb25da Fixed: Show WorkEffort names in FindWorkEffort page (OFBIZ-12253) new 0c5fc36 Fixed: XSS vulnerability for ListWorkEfforts form (OFBIZ-12254) If `sanitizer.enable` is turned off, `ListWorkEfforts` form will be vulnerable to XSS attack, because of incomplete escaping. new bb254ca Fixed: Unexpected decoding of url encoded textarea data after submission (OFBIZ-12249) The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: .../java/org/apache/ofbiz/base/util/UtilHttp.java | 130 +++++++++++---------- .../org/apache/ofbiz/base/util/UtilValidate.java | 15 ++- .../template/macro/HtmlFormMacroLibrary.ftl | 4 +- 3 files changed, 84 insertions(+), 65 deletions(-) |
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 commit 0c5fc36b594fe99a82a8236b06bdda9883367606 Author: Jacques Le Roux <[hidden email]> AuthorDate: Wed Jun 9 10:51:34 2021 +0200 Fixed: XSS vulnerability for ListWorkEfforts form (OFBIZ-12254) If `sanitizer.enable` is turned off, `ListWorkEfforts` form will be vulnerable to XSS attack, because of incomplete escaping. Steps to reproduce: 1. Turn off `sanitizer.enable` in owasp.properties 2. Create a WorkEffort entity with name as `<script>alert(1)</script>` 3. Go to page: http://localhost:8080/workeffort/control/FindWorkEffort 4. Search for "Work Effort Name" which contains "script" Thanks: Xin Wang --- themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl index 0923033..b391727 100644 --- a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl +++ b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl @@ -710,7 +710,7 @@ Parameter: delegatorName, String, optional - name of the delegator in context. data-dialog-url="${linkUrl}" <#if text?has_content>data-dialog-title="${text}"</#if> <#if linkStyle?has_content>class="${linkStyle}"</#if>> - <#if description?has_content>${description}</#if></a> + <#if description?has_content>${description?html}</#if></a> <#else> <a <#if linkStyle?has_content && (description?has_content || imgSrc?has_content)>class="${linkStyle}"</#if> href="${linkUrl}"<#if targetWindow?has_content> target="${targetWindow}"</#if> @@ -718,6 +718,6 @@ Parameter: delegatorName, String, optional - name of the delegator in context. <#if confirmation?has_content> data-confirm-message="${confirmation}"</#if> <#if id?has_content> id="${id}"</#if> <#if imgSrc?length == 0 && title?has_content> title="${title}"</#if>> - <#if imgSrc?has_content><img src="${imgSrc}" alt="${alternate}" title="${title}"/></#if>${description}</a> + <#if imgSrc?has_content><img src="${imgSrc}" alt="${alternate}" title="${title}"/></#if>${description?html}</a> </#if> </#macro> |
In reply to this post by jleroux@apache.org
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 commit bb254caddd08846e0c4e3bf6341a1e10d2321178 Author: Jacques Le Roux <[hidden email]> AuthorDate: Wed Jun 9 10:57:51 2021 +0200 Fixed: Unexpected decoding of url encoded textarea data after submission (OFBIZ-12249) When trying to add a note to WorkEffort entity, I found that URL encoded characters are unescaped, which is not expected. e.g.: 1. Go to page: https://demo-trunk.ofbiz.apache.org/workeffort/control/EditWorkEffortNotes?workEffortId=TASK01 2. Add a note with content: https://example.com/a%20link 3. After submission, it will turned to be: https://example.com/a link Thanks: Xin Wang for report and exchanges until solution I provided Conflicts: UtilHttp.java: removes unused OOTB checkURLforSpiders for simplification UtilValidate.java: replaces DEFAULT_EMPTY_OK simply by true --- .../java/org/apache/ofbiz/base/util/UtilHttp.java | 130 +++++++++++---------- .../org/apache/ofbiz/base/util/UtilValidate.java | 15 ++- 2 files changed, 82 insertions(+), 63 deletions(-) diff --git a/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java b/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java index 666316a..56c4e35 100644 --- a/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java +++ b/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java @@ -62,7 +62,6 @@ import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.fileupload.servlet.ServletRequestContext; import org.apache.commons.lang.RandomStringUtils; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; @@ -78,10 +77,6 @@ import org.apache.ofbiz.webapp.control.ConfigXMLReader; import org.apache.ofbiz.webapp.control.SameSiteFilter; import org.apache.ofbiz.webapp.event.FileUploadProgressListener; import org.apache.ofbiz.widget.renderer.VisualTheme; -import org.apache.oro.text.regex.MalformedPatternException; -import org.apache.oro.text.regex.Pattern; -import org.apache.oro.text.regex.PatternMatcher; -import org.apache.oro.text.regex.Perl5Matcher; import com.ibm.icu.util.Calendar; @@ -405,7 +400,30 @@ public final class UtilHttp { public static Map<String, Object> canonicalizeParameterMap(Map<String, Object> paramMap) { for (Map.Entry<String, Object> paramEntry: paramMap.entrySet()) { if (paramEntry.getValue() instanceof String) { - paramEntry.setValue(canonicalizeParameter((String) paramEntry.getValue())); + String paramEntries = (String) paramEntry.getValue(); + String[] stringValues = paramEntries.split(" "); + String params = ""; + // Handles textareas, see OFBIZ-12249 + if (stringValues.length > 0) { + for (String s : stringValues) { + // if the string contains only an URL beginning by http or ftp => no change to keep special chars + if (UtilValidate.isValidUrl(s) && (s.indexOf("://") == 4 || s.indexOf("://") == 3)) { + params = params + s + " " ; + } else if (UtilValidate.isUrl(s) && !s.isEmpty()) { + // if the string contains not only an URL => concatenate possible canonicalized before and after, w/o changing the URL + String url = extractUrls(s).get(0); // THere should be only 1 URL in a block, makes no sense else + int start = s.indexOf(url); + String after = (String) s.subSequence(start + url.length(), s.length()); + params = params + canonicalizeParameter((String) s.subSequence(0, start)) + url + canonicalizeParameter(after) + " "; + } else { + // Simple string to canonicalize + params = params + canonicalizeParameter(s) + " "; + } + } + paramEntry.setValue(params.trim()); + } else { + paramEntry.setValue(canonicalizeParameter(paramEntries)); + } } else if (paramEntry.getValue() instanceof Collection<?>) { List<String> newList = new LinkedList<>(); for (String listEntry: UtilGenerics.<String>checkCollection(paramEntry.getValue())) { @@ -1147,7 +1165,7 @@ public final class UtilHttp { response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, private"); // HTTP/1.1 response.setHeader("Pragma", "no-cache"); // HTTP/1.0 } - + public static void setResponseBrowserDefaultSecurityHeaders(HttpServletResponse resp, ConfigXMLReader.ViewMap viewMap) { // See https://cwiki.apache.org/confluence/display/OFBIZ/How+to+Secure+HTTP+Headers for details and how to test String xFrameOption = null; @@ -1176,29 +1194,31 @@ public final class UtilHttp { resp.addHeader("strict-transport-security", "max-age=31536000; includeSubDomains"); } } - - /** The only x-content-type-options defined value, "nosniff", prevents Internet Explorer from MIME-sniffing a response away from the declared content-type. - This also applies to Google Chrome, when downloading extensions. */ + + /** + * The only x-content-type-options defined value, "nosniff", prevents Internet Explorer from MIME-sniffing a response away from the declared + * content-type. This also applies to Google Chrome, when downloading extensions. + */ resp.addHeader("x-content-type-options", "nosniff"); - - /** This header enables the Cross-site scripting (XSS) filter built into most recent web browsers. - It's usually enabled by default anyway, so the role of this header is to re-enable the filter for this particular website if it was disabled by the user. - This header is supported in IE 8+, and in Chrome (not sure which versions). The anti-XSS filter was added in Chrome 4. Its unknown if that version honored this header. - FireFox has still an open bug entry and "offers" only the noscript plugin - https://wiki.mozilla.org/Security/Features/XSS_Filter - https://bugzilla.mozilla.org/show_bug.cgi?id=528661 + + /** + * This header enables the Cross-site scripting (XSS) filter built into most recent web browsers. It's usually enabled by default anyway, so + * the role of this header is to re-enable the filter for this particular website if it was disabled by the user. This header is supported in + * IE 8+, and in Chrome (not sure which versions). The anti-XSS filter was added in Chrome 4. Its unknown if that version honored this header. + * FireFox has still an open bug entry and "offers" only the noscript plugin https://wiki.mozilla.org/Security/Features/XSS_Filter + * https://bugzilla.mozilla.org/show_bug.cgi?id=528661 **/ - resp.addHeader("X-XSS-Protection","1; mode=block"); - + resp.addHeader("X-XSS-Protection", "1; mode=block"); + resp.setHeader("Referrer-Policy", "no-referrer-when-downgrade"); // This is the default (in Firefox at least) - + resp.setHeader("Content-Security-Policy-Report-Only", "default-src 'self'"); - + SameSiteFilter.addSameSiteCookieAttribute(resp); - + // TODO in custom project. Public-Key-Pins-Report-Only is interesting but can't be used OOTB because of demos (the letsencrypt certificate is renewed every 3 months) } - + public static String getContentTypeByFileName(String fileName) { FileNameMap mime = URLConnection.getFileNameMap(); @@ -1557,45 +1577,6 @@ public final class UtilHttp { HttpSession session = request.getSession(); return (session == null ? "unknown" : session.getId()); } - /** - * checks, if the current request comes from a searchbot - * - * @param request - * @return whether the request is from a web searchbot - */ - public static boolean checkURLforSpiders(HttpServletRequest request) { - boolean result = false; - - String spiderRequest = (String) request.getAttribute("_REQUEST_FROM_SPIDER_"); - if (UtilValidate.isNotEmpty(spiderRequest)) { - return "Y".equals(spiderRequest); - } - String initialUserAgent = request.getHeader("User-Agent") != null ? request.getHeader("User-Agent") : ""; - List<String> spiderList = StringUtil.split(UtilProperties.getPropertyValue("url", "link.remove_lsessionid.user_agent_list"), ","); - - if (UtilValidate.isNotEmpty(spiderList)) { - for (String spiderNameElement : spiderList) { - Pattern pattern = null; - try { - pattern = PatternFactory.createOrGetPerl5CompiledPattern(spiderNameElement, false); - } catch (MalformedPatternException e) { - Debug.logError(e, module); - } - PatternMatcher matcher = new Perl5Matcher(); - if (matcher.contains(initialUserAgent, pattern)) { - request.setAttribute("_REQUEST_FROM_SPIDER_", "Y"); - result = true; - break; - } - } - } - - if (!result) { - request.setAttribute("_REQUEST_FROM_SPIDER_", "N"); - } - - return result; - } /** Returns true if the user has JavaScript enabled. * @param request @@ -1728,4 +1709,29 @@ public final class UtilHttp { public static String getRowSubmitPrefix() { return ROW_SUBMIT_PREFIX; } + + // From https://stackoverflow.com/questions/1806017/extracting-urls-from-a-text-document-using-java-regular-expressions/1806161#answer-1806161 + // If you need more Internet top-level domains: https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains + public static List<String> extractUrls(String input) { + List<String> result = new ArrayList<String>(); + + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile( + "\\b(((ht|f)tp(s?)\\:\\/\\/|~\\/|\\/)|www.)" + + "(\\w+:\\w+@)?(([-\\w]+\\.)+(com|org|net|gov" + + "|mil|biz|info|mobi|name|aero|jobs|museum" + + "|travel|[a-z]{2}))(:[\\d]{1,5})?" + + "(((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?" + + "((\\?([-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" + + "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)" + + "(&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" + + "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*" + + "(#([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?\\b"); + + java.util.regex.Matcher matcher = pattern.matcher(input); + while (matcher.find()) { + result.add(matcher.group()); + } + + return result; + } } diff --git a/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilValidate.java b/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilValidate.java index 2a476e5..8e6f002 100644 --- a/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilValidate.java +++ b/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilValidate.java @@ -24,6 +24,7 @@ import java.util.Locale; import java.util.Map; import org.apache.commons.validator.routines.EmailValidator; +import org.apache.commons.validator.routines.UrlValidator; import org.apache.ofbiz.base.lang.IsEmpty; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.GenericEntityException; @@ -754,6 +755,18 @@ public final class UtilValidate { return false; } + /** + * isValidUrl returns true if the string is a valid URL (using Commons UrlValidator) + * @param s String to validate + * @return true if s contains if the string is a valid URL (using Commons UrlValidator) + */ + public static boolean isValidUrl(String s) { + if (isEmpty(s)) { + return true; + } + return UrlValidator.getInstance().isValid(s); + } + /** isYear returns true if string s is a valid * Year number. Must be 2 or 4 digits only. * @@ -1594,4 +1607,4 @@ public final class UtilValidate { } return isValid; } -} \ No newline at end of file +} |
Free forum by Nabble | Edit this page |