This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.xss-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-xss.git
commit 675462e985395be0d8789eef1366883f6bdc1a9e Author: Felix Meschberger <[email protected]> AuthorDate: Wed Nov 19 09:01:54 2014 +0000 SLING-4176 - Added validation/filtering for StyleToken context * Adding a new method for checking CSS tokens to the XSSAPI * Incl. implementation and unit tests This closes #38 (Applying patch by Vlad Bailescue; Thanks alot) git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/xss@1640505 13f79535-47bb-0310-9956-ffa450edef68 --- src/main/java/org/apache/sling/xss/XSSAPI.java | 10 +++ .../java/org/apache/sling/xss/impl/XSSAPIImpl.java | 40 ++++++++++ .../org/apache/sling/xss/impl/XSSAPIImplTest.java | 88 +++++++++++++++++++--- 3 files changed, 128 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/sling/xss/XSSAPI.java b/src/main/java/org/apache/sling/xss/XSSAPI.java index b447324..09801a6 100644 --- a/src/main/java/org/apache/sling/xss/XSSAPI.java +++ b/src/main/java/org/apache/sling/xss/XSSAPI.java @@ -86,6 +86,16 @@ public interface XSSAPI { public String getValidJSToken(String token, String defaultValue); /** + * Validate a style/CSS token. Valid CSS tokens are specified at http://www.w3.org/TR/css3-syntax/ + * + * @param token the source token + * @param defaultValue a default value to use if the source doesn't meet validity constraints. + * + * @return a string containing sanitized style token + */ + public String getValidStyleToken(String token, String defaultValue); + + /** * Validate a CSS color value. Color values as specified at http://www.w3.org/TR/css3-color/#colorunits * are safe and definitively allowed. Vulnerable constructs will be disallowed. Currently known * vulnerable constructs include url(...), expression(...), and anything with a semicolon. diff --git a/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java b/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java index 034a38d..4306d99 100644 --- a/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java +++ b/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java @@ -190,6 +190,46 @@ public class XSSAPIImpl implements XSSAPI { } } + private static final String NON_ASCII = "\\x00\\x08\\x0B\\x0C\\x0E-\\x1F"; + /** http://www.w3.org/TR/css-syntax-3/#number-token-diagram */ + private static final String NUMBER = "[+-]?[\\d]*[\\.]?[\\d]*(?:[e][+-]?\\d+)?"; + /** http://www.w3.org/TR/css-syntax-3/#hex-digit-diagram */ + private static final String HEX_DIGITS = "#[0-9a-f]*"; + /** http://www.w3.org/TR/css-syntax-3/#ident-token-diagram */ + private static final String IDENTIFIER = "-?[a-z_" + NON_ASCII + "][\\w_\\-" + NON_ASCII + "]*"; + /** http://www.w3.org/TR/css-syntax-3/#string-token-diagram */ + private static final String STRING = "\"(?:[^\"^\\\\^\\n]|(?:\\\\\"))*\"|'(?:[^'^\\\\^\\n]|(?:\\\\'))*'"; + /** http://www.w3.org/TR/css-syntax-3/#dimension-token-diagram */ + private static final String DIMENSION = NUMBER + IDENTIFIER; + /** http://www.w3.org/TR/css-syntax-3/#percentage-token-diagram */ + private static final String PERCENT = NUMBER + "%"; + /** http://www.w3.org/TR/css-syntax-3/#function-token-diagram */ + private static final String FUNCTION = IDENTIFIER + "\\((?:(?:" + NUMBER + ")|(?:" + IDENTIFIER + ")|(?:[\\s]*)|(?:,))*\\)"; + /** http://www.w3.org/TR/css-syntax-3/#url-unquoted-diagram */ + private static final String URL_UNQUOTED = "[^\"^'^\\(^\\)^[" + NON_ASCII + "]]*"; + /** http://www.w3.org/TR/css-syntax-3/#url-token-diagram */ + private static final String URL = "url\\((?:(?:" + URL_UNQUOTED + ")|(?:" + STRING + "))\\)"; + /** composite regular expression for style token validation */ + private static final String CSS_TOKEN = "(?i)" // case insensitive + + "(?:" + NUMBER + ")" + + "|(?:" + DIMENSION + ")" + + "|(?:" + PERCENT + ")" + + "|(?:" + HEX_DIGITS + ")" + + "|(?:" + IDENTIFIER + ")" + + "|(?:" + STRING + ")" + + "|(?:" + FUNCTION + ")" + + "|(?:" + URL + ")"; + + /** + * @see org.apache.sling.xss.XSSAPI#getValidStyleToken(String, String) + */ + public String getValidStyleToken(String token, String defaultValue) { + if (token.matches(CSS_TOKEN)) { + return token; + } + return defaultValue; + } + /** * @see org.apache.sling.xss.XSSAPI#getValidCSSColor(String, String) */ diff --git a/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java b/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java index 9637da6..3f7108c 100644 --- a/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java +++ b/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java @@ -39,6 +39,8 @@ import org.owasp.validator.html.Policy; public class XSSAPIImplTest { + public static final String RUBBISH = "rubbish"; + private XSSAPI xssAPI; @Before @@ -310,25 +312,25 @@ public class XSSAPIImplTest { {"simple", "simple"}, {"clickstreamcloud.thingy", "clickstreamcloud.thingy"}, - {"break out", "rubbish"}, - {"break,out", "rubbish"}, + {"break out", RUBBISH}, + {"break,out", RUBBISH}, {"\"literal string\"", "\"literal string\""}, {"'literal string'", "'literal string'"}, - {"\"bad literal'", "rubbish"}, + {"\"bad literal'", RUBBISH}, {"'literal'); junk'", "'literal\\x27); junk'"}, {"1200", "1200"}, {"3.14", "3.14"}, - {"1,200", "rubbish"}, - {"1200 + 1", "rubbish"} + {"1,200", RUBBISH}, + {"1200 + 1", RUBBISH} }; for (String[] aTestData : testData) { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.getValidJSToken(source, "rubbish"); + String result = xssAPI.getValidJSToken(source, RUBBISH); if (!result.equals(expected)) { fail("Validating Javascript token '" + source + "', expecting '" + expected + "', but got '" + result + "'"); } @@ -336,6 +338,72 @@ public class XSSAPIImplTest { } @Test + public void TestGetValidStyleToken() { + String[][] testData = { + // Source Expected result + + // CSS close + {"}" , RUBBISH}, + + // line break + {"br\neak" , RUBBISH}, + + // no javascript: + {"javascript:alert(1)" , RUBBISH}, + {"url(javascript:alert(1))" , RUBBISH}, + + // no expression + {"expression(alert(1))" , RUBBISH}, + {"expression (alert(1))" , RUBBISH}, + {"expression(this.location='a.co')" , RUBBISH}, + + // html tags + {"</style><script>alert(1)</script>", RUBBISH}, + + // usual CSS stuff + {"background-color" , "background-color"}, + {"-moz-box-sizing" , "-moz-box-sizing"}, + {".42%" , ".42%"}, + {"#fff" , "#fff"}, + + // valid strings + {"'literal string'" , "'literal string'"}, + {"\"literal string\"" , "\"literal string\""}, + {"'it\\'s here'" , "'it\\'s here'"}, + {"\"it\\\"s here\"" , "\"it\\\"s here\""}, + + // invalid strings + {"\"bad string" , RUBBISH}, + {"'it's here'" , RUBBISH}, + {"\"it\"s here\"" , RUBBISH}, + + // valid parenthesis + {"rgb(255, 255, 255)" , "rgb(255, 255, 255)"}, + + // invalid parenthesis + {"rgb(255, 255, 255" , RUBBISH}, + {"255, 255, 255)" , RUBBISH}, + + // valid tokens + {"url(http://example.com/test.png)", "url(http://example.com/test.png)"}, + {"url('image/test.png')" , "url('image/test.png')"}, + + // invalid tokens + {"color: red" , RUBBISH} + }; + + for (String[] aTestData : testData) { + String source = aTestData[0]; + String expected = aTestData[1]; + + String result = xssAPI.getValidStyleToken(source, RUBBISH); + if (!result.equals(expected)) { + fail("Validating style token '" + source + "', expecting '" + expected + "', but got '" + result + "'"); + } + } + } + + @Test public void TestGetValidCSSColor() { String[][] testData = { // Source Expected Result @@ -352,16 +420,16 @@ public class XSSAPIImplTest { {"transparent", "transparent"}, {"\f\r\n\t MenuText\f\r\n\t ", "MenuText"}, - {"expression(99,99,99)", "rubbish"}, - {"blue;", "rubbish"}, - {"url(99,99,99)", "rubbish"} + {"expression(99,99,99)", RUBBISH}, + {"blue;", RUBBISH}, + {"url(99,99,99)", RUBBISH} }; for (String[] aTestData : testData) { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.getValidCSSColor(source, "rubbish"); + String result = xssAPI.getValidCSSColor(source, RUBBISH); if (!result.equals(expected)) { fail("Validating CSS Color '" + source + "', expecting '" + expected + "', but got '" + result + "'"); } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
