Skip to content

Improper Neutralization of Alternate XSS Syntax in KnowageLabs / Knowage-Server

Moderate
kerny3d published GHSA-f2gr-6h9j-rwcw Oct 11, 2022

Package

KnowageLabs / Knowage-Server (Knowage)

Affected versions

6.x.x, <7.4.22, <8.0.9, <8.1.0

Patched versions

7.4.22, 8.0.9, 8.1.0

Description

Impact

Cross Site Scripting in KnowageLabs / Knowage-Server

Root Cause

The XSSRequestWrapper::stripXSS method can be bypassed.

public static String stripXSS(String value) {
logger.debug("IN");
String initialValue = value;
if (value != null) {
// NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
// avoid encoded attacks.
// value = ESAPI.encoder().canonicalize(value);
// Avoid null characters
value = value.replaceAll("", "");
// Avoid anything between script tags
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("&lt;script&gt;(.*?)&lt;/script&gt;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid anything in a src='...' type of expression
// Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
// value = scriptPattern.matcher(value).replaceAll("");
//
// scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
// value = scriptPattern.matcher(value).replaceAll("");
value = checkImgTags(value);
value = checkIframeTags(value);
value = checkAnchorTags(value);
value = checkVideoTags(value);
value = checkCSS(value);
// Remove any lonesome </script> tag
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("&lt;/script&gt;", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome <script ...> tag
scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("&lt;script(.*?)&gt;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid eval(...) expressions
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid expression(...) expressions
scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid javascript:... expressions
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid vbscript:... expressions
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid onload= expressions
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid onClick= expressions
scriptPattern = Pattern.compile("onClick(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid anything between form tags
Pattern formPattern = Pattern.compile("<form(.*?)</form>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = formPattern.matcher(value).replaceAll("");
// Avoid anything between a tags
// Pattern aPattern = Pattern.compile("<a(.*?)</a>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
// value = aPattern.matcher(value).replaceAll("");
// aPattern = Pattern.compile("<a(.*?/)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
// value = aPattern.matcher(value).replaceAll("");
Pattern aPattern = Pattern.compile("&lt;a(.*?)&lt;/a&gt;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = aPattern.matcher(value).replaceAll("");
// Avoid anything between button tags
Pattern buttonPattern = Pattern.compile("<button(.*?)</button>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = buttonPattern.matcher(value).replaceAll("");
buttonPattern = Pattern.compile("<button(.*?/)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = buttonPattern.matcher(value).replaceAll("");
buttonPattern = Pattern.compile("&lt;button(.*?)&lt;/button&gt;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = buttonPattern.matcher(value).replaceAll("");
// Example value ="<object data=\"javascript:alert('XSS')\"></object>"
// Avoid anything between script tags
Pattern objectPattern = Pattern.compile("<object(.*?)</object>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = objectPattern.matcher(value).replaceAll("");
objectPattern = Pattern.compile("&lt;object(.*?)&lt;/object&gt;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = objectPattern.matcher(value).replaceAll("");
// Remove any lonesome </object> tag
objectPattern = Pattern.compile("</object>", Pattern.CASE_INSENSITIVE);
value = objectPattern.matcher(value).replaceAll("");
objectPattern = Pattern.compile("&lt;/object&gt;", Pattern.CASE_INSENSITIVE);
value = objectPattern.matcher(value).replaceAll("");
// Remove any lonesome <object ...> tag
objectPattern = Pattern.compile("<object(.*?/)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = objectPattern.matcher(value).replaceAll("");
objectPattern = Pattern.compile("&lt;object(.*?/)&gt;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = objectPattern.matcher(value).replaceAll("");
if (!value.equalsIgnoreCase(initialValue)) {
logger.warn("Message: detected a web attack through injection");
}
}
logger.debug("OUT");
return value;
}

The following payloads can bypass this filter:

  • <scrivbscript:pt>alert(1)</scrivbscript:pt> -> <script>alert(1)</script>
  • javavbscript:script: -> javascript:
  • ect...

Fundamentally, attempting to filter for XSS payloads uniformly, as this logic attempts to do is, a fundamentally flawed protection strategy. The way that user-input strings need to be used (for example HTML escaped, or URL encoded) is context dependent and varies heavily depending upon where they are being rendered/used. This issue needs to be fixed closer to where the content is being rendered, instead of attempting to prevent XXS in the manner this method attempts.

Patches

Has the problem been patched? What versions should users upgrade to?

Workarounds

Is there a way for users to fix or remediate the vulnerability without upgrading?

References

Are there any links users can visit to find out more?

For more information

If you have any questions or comments about this advisory:

Severity

Moderate

CVE ID

CVE-2022-39295

Weaknesses

Credits