diff options
Diffstat (limited to 'tests/src/com/android/mail/utils/AdvancedHtmlSanitizerTest.java')
-rw-r--r-- | tests/src/com/android/mail/utils/AdvancedHtmlSanitizerTest.java | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/tests/src/com/android/mail/utils/AdvancedHtmlSanitizerTest.java b/tests/src/com/android/mail/utils/AdvancedHtmlSanitizerTest.java new file mode 100644 index 000000000..578ce4ae8 --- /dev/null +++ b/tests/src/com/android/mail/utils/AdvancedHtmlSanitizerTest.java @@ -0,0 +1,537 @@ +package com.android.mail.utils; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +/** + * These test cases verify the handling of more advanced cross-site scripting attacks. + */ +@SmallTest +public class AdvancedHtmlSanitizerTest extends AndroidTestCase { + public void testSampleEmail() { + sanitize("<html>\n" + + "<head>\n" + + "<title>HTML E-mail</title>\n" + + "<script>\n" + + "alert(\"I am an alert box!\");\n" + + "</script>\n" + + "</head>\n" + + "<body>\n" + + "Body here\n" + + "<br />\n" + + "<a href=\"http://www.google.com\">Link to Google Search!</a>\n" + + "<br />\n" + + "<br />\n" + + "<a onclick=\"alert('surprise!')\" href=\"#\">I am a link!</a>\n" + + "<br />\n" + + "Moar body here\n" + + "</body>\n" + + "</html>" + , + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "<div>\n" + + "Body here\n" + + "<br />\n" + + "<a href=\"http://www.google.com\">Link to Google Search!</a>\n" + + "<br />\n" + + "<br />\n" + + "<a href=\"#\">I am a link!</a>\n" + + "<br />\n" + + "Moar body here\n" + + "</div>\n"); + } + + public void testXSS() { + sanitize("'';!--\"<XSS>=&{()}", "'';!--"=&{()}"); + sanitize("<img src=javascript:alert(String.fromCharCode(88,83,83))>", ""); + sanitize("\\\";alert('XSS');//", "\\";alert('XSS');//"); + sanitize("<br size=\"&{alert('XSS')}\">", "<br />"); + sanitize("<xss style=\"xss:expression(alert('XSS'))\">", ""); + sanitize("<xss style=\"behavior: url(xss.htc);\">", ""); + sanitize("¼script¾alert(¢XSS¢)¼/script¾", "¼script¾alert(¢XSS¢)¼/script¾"); + sanitize("<xml><i><b><img src=\"javas<!-- -->cript:alert('XSS')\"></b></i></xml>", + "<i><b></b></i>"); + sanitize("<xml src=\"xsstest.xml\" id=I></xml>", ""); + sanitize("<!--[if gte IE 4]>\n" + + " <SCRIPT>alert('XSS');</SCRIPT>\n" + + " <![endif]-->", ""); + sanitize("<body>\n" + + "<?xml:namespace prefix=\"t\" ns=\"urn:schemas-microsoft-com:time\">\n" + + "<?import namespace=\"t\" implementation=\"#default#time2\">\n" + + "<t:set attributeName=\"innerHTML\" to=\"XSS<script defer>alert(\"XSS\")" + + "</script>\">\n" + + "</body></html>", + "<div>\n" + + "\n" + + "\n" + + "">\n" + + "</div>"); + } + + /** + * Technically, RFC 2392 doesn't limit where CID urls may appear; they are accepted everywhere. + */ + public void testCIDurls() { + sanitize("<img src=\"http://www.here.com/awesome.png\"/>", + "<img src=\"http://www.here.com/awesome.png\" />"); + sanitize("<img src=\"https://www.here.com/awesome.png\"/>", + "<img src=\"https://www.here.com/awesome.png\" />"); + sanitize("<img src=\"cid:ii_145bda161daf6f9c\"/>", + "<img src=\"cid:ii_145bda161daf6f9c\" />"); + + sanitize("<a href=\"http://www.here.com/awesome.png\"/>", + "<a href=\"http://www.here.com/awesome.png\"></a>"); + sanitize("<a href=\"https://www.here.com/awesome.png\"/>", + "<a href=\"https://www.here.com/awesome.png\"></a>"); + sanitize("<a href=\"cid:ii_145bda161daf6f9c\"/>", + "<a href=\"cid:ii_145bda161daf6f9c\"></a>"); + } + + // todo the stock CssSchema in OWASP does NOT allow the float property; I experiment with adding + // todo it to see how much it beautifies HTML display (the risk seems to be that you can display + // todo content outside the bounds of your div and mislead the user with this technique) + public void testCSS_float() { + sanitize("<div style=\"float:none\"></div>", "<div style=\"float:none\"></div>"); + sanitize("<div style=\"float:left\"></div>", "<div style=\"float:left\"></div>"); + sanitize("<div style=\"float:right\"></div>", "<div style=\"float:right\"></div>"); + sanitize("<div style=\"float:inherit\"></div>", "<div style=\"float:inherit\"></div>"); + sanitize("<div style=\"float:initial\"></div>", "<div></div>"); + sanitize("<div style=\"float:garbage\"></div>", "<div></div>"); + } + + // todo the stock CssSchema in OWASP does NOT allow the display property; I experiment with + // todo adding it to see how much it beautifies HTML display (the risk seems to be that you can + // todo display content outside the bounds of your div and mislead the user with this technique) + public void testCSS_display() { + sanitize("<div style=\"display:inline\"></div>", "<div style=\"display:inline\"></div>"); + sanitize("<div style=\"display:block\"></div>", "<div style=\"display:block\"></div>"); + sanitize("<div style=\"display:flex\"></div>", "<div></div>"); + sanitize("<div style=\"display:inline-block\"></div>", + "<div style=\"display:inline-block\"></div>"); + sanitize("<div style=\"display:inline-flex\"></div>", "<div></div>"); + sanitize("<div style=\"display:inline-table\"></div>", + "<div style=\"display:inline-table\"></div>"); + sanitize("<div style=\"display:list-item\"></div>", + "<div style=\"display:list-item\"></div>"); + sanitize("<div style=\"display:run-in\"></div>", "<div style=\"display:run-in\"></div>"); + sanitize("<div style=\"display:table\"></div>", "<div style=\"display:table\"></div>"); + sanitize("<div style=\"display:table-caption\"></div>", + "<div style=\"display:table-caption\"></div>"); + sanitize("<div style=\"display:table-column-group\"></div>", + "<div style=\"display:table-column-group\"></div>"); + sanitize("<div style=\"display:table-header-group\"></div>", + "<div style=\"display:table-header-group\"></div>"); + sanitize("<div style=\"display:table-footer-group\"></div>", + "<div style=\"display:table-footer-group\"></div>"); + sanitize("<div style=\"display:table-row-group\"></div>", + "<div style=\"display:table-row-group\"></div>"); + sanitize("<div style=\"display:table-cell\"></div>", + "<div style=\"display:table-cell\"></div>"); + sanitize("<div style=\"display:table-column\"></div>", + "<div style=\"display:table-column\"></div>"); + sanitize("<div style=\"display:table-row\"></div>", + "<div style=\"display:table-row\"></div>"); + sanitize("<div style=\"display:none\"></div>", "<div style=\"display:none\"></div>"); + sanitize("<div style=\"display:initial\"></div>", "<div></div>"); + sanitize("<div style=\"display:inherit\"></div>", "<div style=\"display:inherit\"></div>"); + } + + public void testTrimmingUrls() { + // todo Gmail strips the leading space on this href +// sanitize("<a href=\"http://www.google.com \">Send mail</a>", +// "<a href=\"http://www.google.com\">Send mail</a>"); + sanitize("<a href=\" http://www.google.com\">Send mail</a>", "Send mail"); + // todo Gmail strips the trailing space on this href +// sanitize("<a href=\"http://www.google.com \">Send mail</a> ", +// "<a href=\"http://www.google.com\">Send mail</a>"); + sanitize("<a href=\"http://www.google.com \">Send mail</a>", + "<a href=\"http://www.google.com \">Send mail</a>"); + // todo Gmail strips the leading and trailing spaces on this href +// sanitize("<a href=\" http://www.google.com \">Send mail</a> ", +// "<a href=\"http://www.google.com\">Send mail</a>"); + sanitize("<a href=\" http://www.google.com \">Send mail</a>", "Send mail"); + } + + public void testDangerousHtml() { + // body tag is translated to div tag + sanitize("<body dir=\"rtl\" onMouseOVer=\"alert(document.cookie)\">arr</body>", + "<div dir=\"rtl\">arr</div>"); + sanitize("<DIV ONCLICK=alert(document.cookie) style=color:red>arr</DIV>", + "<div style=\"color:red\">arr</div>"); + sanitize("<b style=position:absolute;left:0;top:0>arr</b>", "<b>arr</b>"); + + // mailto: URLs on images are too easy to turn into DOS attacks + sanitize("<img src=\"mailto:\">", ""); + sanitize("<img src=\"mailto:hcnidumolu@google.com\">", ""); + sanitize("<img src=\"mailto:hcnidumolu@google.com\">", ""); + sanitize("<img src=\" mailto:hcnidumolu@google.com\">", ""); + sanitize("<img src=\"mailto:hcnidumolu@google.com\">", ""); + sanitize("<img src=\"m
ailto:hcnidumolu@google.com\">", ""); + // todo Gmail doesn't escape the @ sign; OWASP does by default +// sanitize("<a href=\"mailto:hcnidumolu@google.com\">Send mail </a>", +// "<a href=\"mailto:hcnidumolu@google.com\">Send mail </a>"); + sanitize("<a href=\"mailto:hcnidumolu@google.com\">Send mail </a>", + "<a href=\"mailto:hcnidumolu@google.com\">Send mail </a>"); + } + + public void testSanitizingImgsWithoutSchemes() { + sanitize("<img src=\"//images1-gm-opensocial.googleusercontent.com/gadgets/proxy?" + + "url=http://foo.bar/baz.png&container=gm&gadget=a&rewriteMime=image/*\">", +// "<img src=\"//images1-gm-opensocial.googleusercontent.com/gadgets/proxy?" + +// "url=http://foo.bar/baz.png&container=gm&gadget=" + +// "a&rewriteMime=image/*\">"); // todo Gmail doesn't escape the = signs + "<img src=\"//images1-gm-opensocial.googleusercontent.com/gadgets/proxy?" + + "url=http://foo.bar/baz.png&container=gm&gadget=" + + "a&rewriteMime=image/*\" />"); + } + + public void testAdditionalURISchemes() { + // todo Gmail keeps a destinationless link; OWASP strips the a link completely +// sanitize("<a href=\"foo:bar\" target=\"_blank\">link1</a>", "<a>link1</a>"); + sanitize("<a href=\"foo:bar\" target=\"_blank\">link1</a>", "link1"); + // todo Gmail keeps a destinationless a link; OWASP strips the a link completely +// sanitize("<a href=\"baz:alanbs@google.com\">link2</a>", "<a>link2</a>"); + sanitize("<a href=\"baz:alanbs@google.com\">link2</a>", "link2"); + } + + public void testBackgroundAttribute() { + sanitize("<div background=\"http://www.random.org/png\">stuff</div><div>more stuff</div>", + "<div background=\"http://www.random.org/png\">stuff</div><div>more stuff</div>"); + } + + public void testInputImage() { + sanitize("<input type=\"image\" src=\"http://random.org/png\">", + "<input type=\"image\" src=\"http://random.org/png\" />"); + } + + public void testImplicitInputImage() { + // In HTML 4.01, src attribute has meaning only when type="image" (which + // is not the default), but this happens in real life. + sanitize("<input src=\"http://random.org/png\">", + "<input src=\"http://random.org/png\" />"); + } + + public void testSerialization() { + // N.B. (literal) newlines must not occur in CSS strings. + // todo Gmail leaves this CSS style in place and escapes it; OWASP removes it all +// sanitize("<a href=\"http://www.google.com\" style=\"font-family: 'expression; " + +// "\\a color:red;\\a font-family: completely unsanitized =(;' ;\">asdf</a>", +// "<a href=\"http://www.google.com\" style=\"font-family:'expression; " + +// "\\00000acolor:red;\\00000afont-family: completely unsanitized " + +// "=(;'\">asdf</a>"); + sanitize("<a href=\"http://www.google.com\" style=\"font-family: 'expression; " + + "\\a color:red;\\a font-family: completely unsanitized =(;' ;\">asdf</a>", + "<a href=\"http://www.google.com\">asdf</a>"); + } + + public void testNoJS() { + // todo Gmail leaves this CSS in place and escapes it; OWASP removes it all +// sanitize("<a href=\"http://www.google.com\" style=\"background-image: " + +// "url('javascript:alert(1)')\"></a>", +// "<a href=\"http://www.google.com\" style=\"background-image:" + +// "url('')\"></a>"); + sanitize("<a href=\"http://www.google.com\" style=\"background-image: " + + "url('javascript:alert(1)')\"></a>", + "<a href=\"http://www.google.com\"></a>"); + } + + public void testNoStyleElementByDefault() { + sanitize("<head><style type='text/css'>verboten { color: red; }</style></head>" + + "<body><p>test</p>", + "<div><p>test</p></div>"); + } + + public void testMessageFormation() { + sanitize("<table><tr><td><b>This is a simple message</b></td></tr></table>", + "<table><tr><td><b>This is a simple message</b></td></tr></table>"); + sanitize("<table><tr><td><b>This is a simple message", + "<table><tr><td><b>This is a simple message</b></td></tr></table>"); + sanitize("<table><tr>This is a simple message</b></td></tr></table>", + "<table><tr><td>This is a simple message</td></tr></table>"); + sanitize("This is a simple message</b></td></tr></table>", "This is a simple message"); + } + + public void testViolatingTags() { + sanitize("<html><head><title>html to ruin your site</title>" + + "<meta http-equiv=\"refresh\" content=\"5\" />" + + "<link rel=\"stylesheet\" type=\"text/css\" href=\"some site\"/>" + + "<style type=\"text/css\"> h1 {color: red}</style>" + + "</head><body><script>some script to run</script>" + + "<noscript>Please enable Javascript and reload this page." + + "Good things abound!</noscript>" + + "<noframes>This page requires frames!</noframes>" + + "<frameset cols = \"25%, 25%,*\">" + + "<frame src=\"site1.htm\" />" + + "<frame src=\"site2.htm\" />" + + "<frame src=\"site3.htm\" /> " + + "</frameset>" + + "<table><tr><td>" + + "Execute this <applet code=\"some evil site\"></td>" + + "</tr></table></body></html>" + , + "<div>" + + "<table><tr><td>" + + "Execute this </td>" + + "</tr></table></div>" + ); + + sanitize("Include this:<br/>" + + "<object classid=\"clsid:FOOBAR\" id=\"Slider1\"" + + "declare=\"declare\">" + + "<param name=\"some param\" value=\"1\" />" + + "</object><br/>" + + "<form method=\"POST\" action=\"http://www.somesite.com\"" + + "onsubmit=\"run some script\">" + + "<input type=\"text\" onclick=\"run some script\" id=\"input\"/>" + + "<input type=\"submit\" onfocus=\"run some script\" value=\"submit\"/>" + + "</form>" + , + "Include this:<br />" + + "<br />" + + "<form method=\"POST\" action=\"http://www.somesite.com\">" + + "<input type=\"text\" />" + + "<input type=\"submit\" value=\"submit\" />" + + "</form>" + ); + } + + public void testLinks() { + sanitize("<a href=\"http://www.somesite.com\" target=\"_self\" " + + "onclick=\"run some script\" onmouseover=\"run some script\">" + + "click here</a>" + + "<a href=\"javascript:run some script\">here</a>" + + "<a href=\"someinternalpage.htm\">or here</a>" + , + "<a href=\"http://www.somesite.com\">" + + "click here</a>" + + "here" + + "<a href=\"someinternalpage.htm\">or here</a>" + ); + } + + public void testExternalLinks() { + sanitize("This is a test <a href=http://google.com>here</a> " + + "<img src=\"http://google.com/bogus.jpg\">" + + "<img src=\"//google.com/bogus2.jpg\">" + + "<img src=\"google.com/bogus3.jpg\">" + + "<script>Hello</script> " + + "<frameset><frame src=foo name=onlyFrame>hey</frame></frameset>" + , + "This is a test <a href=\"http://google.com\">here</a> " + + "<img src=\"http://google.com/bogus.jpg\" />" + + "<img src=\"//google.com/bogus2.jpg\" />" + + "<img src=\"google.com/bogus3.jpg\" /> " + ); + } + + public void testNewHtmlWhitelist() { + sanitize("<a href=http://google.com/boguslink>link</a>" + + "<b>BOLD</b>" + + "<i>italics</i>" + + "<u>underlined</u>" + + "<br/>break<br>break" + + "<font size=+1>Big_font_gone</font>" + , + "<a href=\"http://google.com/boguslink\">link</a>" + + "<b>BOLD</b>" + + "<i>italics</i>" + + "<u>underlined</u>" + + "<br />break<br />break" + + "<font size=\"+1\">Big_font_gone</font>" + ); + } + + public void testRemoveBackticksInAttributes() { + // IE treats backticks as quotes when re-serializing, but not when parsing + sanitize("<img alt=\"``onload=alert(1)\">", + "<img alt=\"``onload=alert(1) \" />"); + sanitize("<img alt=\"'``onload=alert(1)'\">", + "<img alt=\"'``onload=alert(1)' \" />"); + sanitize("<img alt=``onload=alert(1)\">", "<img alt=\"``onload=alert(1) \" />"); + + // Make sure we're not fooled by escaped backticks + sanitize("<img alt=\"``onload=alert(1)\">", + "<img alt=\"``onload=alert(1) \" />"); + sanitize("<img alt=\"``onload=alert(1)\">", + "<img alt=\"``onload=alert(1) \" />"); + + // Misc. dangerous cases: + sanitize("<img alt=`x`onload=alert(1)>", "<img alt=\"`x`onload=alert(1) \" />"); + sanitize("<img alt=foo`x`onload=alert(1)>", + "<img alt=\"foo`x`onload=alert(1) \" />"); + sanitize("<img alt=\"`whatever\">Hello world ` onload=alert(1) <br>", + "<img alt=\"`whatever \" />Hello world ` onload=alert(1) <br />"); + + // The tokenizer doesn't see these as entities because they lack a trailing semicolon, so it + // escapes the leading ampersands. + sanitize("<img alt=\"``onload=alert(1)\">", + "<img alt=\"`&#x000060onload=alert(1) \" />"); + + // Here there are no actual backticks, though there would be if we (or IE) did repeated + // unescaping. + sanitize("<img alt=\"&#x000060&#x000060onload=alert(2)\">", + "<img alt=\"&#x000060&#x000060onload=alert(2)\" />"); + sanitize("<img alt=\"&amp;#x000060&amp;#x000060onload=alert(2)\">", + "<img alt=\"&amp;#x000060&amp;#x000060onload=alert(2)\" />"); + } + + public void testMakeSafeStyle() { + sanitize("<div style=\"color:red\"></div>", "<div style=\"color:red\"></div>"); + sanitize("<div style=\"color:r\\ne\\t d d\\r\\n\"></div>", "<div></div>"); + sanitize("<div style=\"font-size:13.5pt; color:#804000 \"></div>", + "<div style=\"font-size:13.5pt;color:#804000\"></div>"); + sanitize("<div style=\"color:red;color\"></div>", "<div style=\"color:red\"></div>"); + sanitize("<div style=\"color:red;color:a:b\"></div>", "<div style=\"color:red\"></div>"); + sanitize("<div style=\"color:url(foo)\"></div>", "<div></div>"); + sanitize("<div style=\"color:white; list-style:url(foo.gif);\"></div>", + "<div style=\"color:white\"></div>"); + sanitize("<div style=\"color:rgb(255, 0, 0)\"></div>", + "<div style=\"color:rgb( 255 , 0 , 0 )\"></div>"); + sanitize("<div style=\"background-color:rgb(80%,92%,18%)\"></div>", + "<div style=\"background-color:rgb( 80% , 92% , 18% )\"></div>"); + sanitize("<div style=\"border-left:1px rgb(0,255,0) solid\"></div>", + "<div style=\"border-left:1px rgb( 0 , 255 , 0 ) solid\"></div>"); + sanitize("<div style=\"background:rgb(0,255,0) url(foo) no-repeat top\"></div>", + "<div style=\"background:rgb( 0 , 255 , 0 ) no-repeat top\"></div>"); + sanitize("<div style=\"display:none; border-color: #ffeeff \"></div>", + "<div style=\"display:none;border-color:#ffeeff\"></div>"); + + // check for CSS3 border-radius + sanitize("<div style=\"border-radius:10px\"></div>", + "<div style=\"border-radius:10px\"></div>"); + sanitize("<div style=\"border-bottom-left-radius:10px\"></div>", + "<div style=\"border-bottom-left-radius:10px\"></div>"); + sanitize("<div style=\"border-bottom-right-radius:10px\"></div>", + "<div style=\"border-bottom-right-radius:10px\"></div>"); + sanitize("<div style=\"border-top-left-radius:10px\"></div>", + "<div style=\"border-top-left-radius:10px\"></div>"); + sanitize("<div style=\"border-top-right-radius:10px\"></div>", + "<div style=\"border-top-right-radius:10px\"></div>"); + + // allow positive margins + sanitize("<div style=\"margin:10 0 10 0\"></div>", + "<div style=\"margin:10 0 10 0\"></div>"); + sanitize("<div style=\"margin-left:40px\"></div>", + "<div style=\"margin-left:40px\"></div>"); + + // negative margin would allow it to slip out of the box + sanitize("<div style=\"margin-left:-10\"></div>", "<div></div>"); + + // allow positive text-ident + sanitize("<div style=\"text-indent:10\"></div>", "<div style=\"text-indent:10\"></div>"); + sanitize("<div style=\"text-indent:0\"></div>", "<div style=\"text-indent:0\"></div>"); + + // todo Gmail disallows negative text-indents; OWASP is fine with them + // negative text-indent would allow it to slip out of the box +// sanitize("<div style=\"text-indent:-10\"></div>", "<div></div>"); + sanitize("<div style=\"text-indent:-10\"></div>", "<div style=\"text-indent:-10\"></div>"); + } + + public void testMakeSafeStyleWithQuotedStrings() { + sanitize("<div style=\"font-family:'courier new',monospace;font-size:x-small\"></div>", + "<div style=\"font-family:'courier new' , monospace;font-size:x-small\">" + + "</div>"); + sanitize("<div style=\"font-family:\"courier new\",monospace\"></div>", "<div></div>"); + sanitize("<div style=\"font-family:''\"></div>", "<div></div>"); + sanitize("<div style=\"font-family:a,''\"></div>", + "<div style=\"font-family:'a' ,\"></div>"); + sanitize("<div style=\"font-family:'',a,\"\",b\"></div>", + "<div style=\"font-family:, 'a' ,\"></div>"); + + sanitize("<div style=\"font-family:'\"></div>", "<div></div>"); + sanitize("<div style=\"font-family: 'courier new\",monospace;'\"></div>", "<div></div>"); + sanitize("<div style=\"font-family: \"courier new',monospace;\"></div>", "<div></div>"); + } + + public void testSeriouslyNoBackgroundImages() { + sanitize("<div style=\"background:url('http://www.here.com/awesome.png')\"></div>", + "<div></div>"); + sanitize("<div style=\"background-image:url('http://www.here.com/awesome.png')\"></div>", + "<div></div>"); + + sanitize("<div style=\"background:url('javascript:evil()')\"></div>", "<div></div>"); + sanitize("<div style=\"background-image:url('javascript:evil()')\"></div>", "<div></div>"); + } + + public void testExpression() { + sanitize("<div style=\"width: expression(alert(1))\"></div>", "<div></div>"); + } + + public void testStrayUrlConsideredHarmful() { + sanitize("<div style=\"float:url(\"></div>", "<div></div>"); + sanitize("<div style=\"float:\\075\\0072\\006C\\0028\"></div>", "<div></div>"); + } + + public void testObjectionableFunctions() { + sanitize("<div style=\"ex\\pression(123)\"></div>", "<div></div>"); + sanitize("<div style=\"_expression(123)\"></div>", "<div></div>"); + sanitize("<div style=\"expression(123)\"></div>", "<div></div>"); + sanitize("<div style=\"funkyFunction(123)\"></div>", "<div></div>"); + + sanitize("<div style=\"color:expression(alert('xss'))\"></div>", "<div></div>"); + sanitize("<div style=\"color:expression(alert\\000028\\000027xss\\000027\\000029)\"></div>", + "<div></div>"); + sanitize("<div style=\"color:expression\\000028alert\\000028\\000027xss\\000027" + + "\\000029\\000029\"></div>", "<div></div>"); + sanitize("<div style=\"color:expressio\\00006E\\000028alert\\000028\\000027xss\\000027" + + "\\000029\\000029\"\"></div>", "<div></div>"); + sanitize("<div style=\"color:expression\\(alert\\)\"></div>", "<div></div>"); + } + + public void testAbsolutePositionBanned() { + sanitize("<div style=\"position: absolute\"></div>", "<div></div>"); + } + + public void testNoTextShadow() { + // todo Gmail disallows this text-shadow; OWASP is fine with it +// sanitize("<div style=\"text-shadow: red -50px -100px 0px\"></div>", "<div></div>"); + sanitize("<div style=\"text-shadow: red -50px -100px 0px\"></div>", + "<div style=\"text-shadow:red -50px -100px 0px\"></div>"); + } + + public void testToStyle() { + sanitize("<div style=\"color:red\"></div>", "<div style=\"color:red\"></div>"); + sanitize("<div style=\"color: red\"></div>", "<div style=\"color:red\"></div>"); + sanitize("<div style=\"color :red\"></div>", "<div style=\"color:red\"></div>"); + sanitize("<div style=\"color :red; font-size:13.5pt;\"></div>", + "<div style=\"color:red;font-size:13.5pt\"></div>"); + sanitize("<div style=\"content:'\"'\"></div>", "<div></div>"); + } + + public void testNoColorStrings() { + sanitize("<div style=\"color: 'red';\"></div>", "<div></div>"); + } + + public void testTolerateMalformedBorder() { + sanitize("<div style=\"border-left-: solid thin red\"></div>", "<div></div>"); + } + + public void testRgba() { + sanitize("<div style=\"color:rgba(255, 0, 0, 0.5)\"></div>", + "<div style=\"color:rgba( 255 , 0 , 0 , 0.5 )\"></div>"); + } + + public void testFontStyle() { + // todo Gmail accepts !important while OWASP discards it; this is only beauty, not security +// sanitize("<div style=\"font-style:normal!important\"></div>", +// "<div style=\"font-style:normal!important\"></div>"); + sanitize("<div style=\"font-style:normal!important\"></div>", + "<div style=\"font-style:normal\"></div>"); + // todo Gmail accepts !important while OWASP discards it; this is only beauty, not security +// sanitize("<div style=\"font-style:oblique !important\"></div>", +// "<div style=\"font-style:oblique!important\"></div>"); + sanitize("<div style=\"font-style:oblique !important\"></div>", + "<div style=\"font-style:oblique\"></div>"); + sanitize("<div style=\"font-style:italic\"></div>", + "<div style=\"font-style:italic\"></div>"); + } + + private void sanitize(String dirtyHTML, String expectedHTML) { + final String cleansedHTML = HtmlSanitizer.sanitizeHtml(dirtyHTML); + assertEquals(expectedHTML, cleansedHTML); + } +} |