|
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("<script>(.*?)</script>", 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("</script>", 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("<script(.*?)>", 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("<a(.*?)</a>", 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("<button(.*?)</button>", 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("<object(.*?)</object>", 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("</object>", 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("<object(.*?/)>", 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; |
|
} |
Impact
Cross Site Scripting in KnowageLabs / Knowage-Server
Root Cause
The
XSSRequestWrapper::stripXSS
method can be bypassed.Knowage-Server/knowageutils/src/main/java/it/eng/spagobi/utilities/filters/XSSRequestWrapper.java
Lines 82 to 206 in b079a65
The following payloads can bypass this filter:
<scrivbscript:pt>alert(1)</scrivbscript:pt>
-><script>alert(1)</script>
javavbscript:script:
->javascript:
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: