/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.core.util.filter.impl; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.olat.core.util.filter.Filter; /** * Description:<br> * This test case tests the cross site scripting filter * * <P> * Initial Date: 14.07.2009 <br> * @author gnaegi * @author Roman Haag, roman.haag@frentix.com */ @RunWith(JUnit4.class) public class XSSFilterTest { protected Filter vFilter; private int counter; private int testsToRun; @Before public void setup() { vFilter = new OWASPAntiSamyXSSFilter(-1, true); counter = 0; testsToRun = 0; } @After public void tearDown() { vFilter = null; System.out.println("Run " + counter + " out of " + testsToRun + " testcases successfully.\n\n"); } private void t(String input, String result) { t(input, result, vFilter); } private void t(String input, String result, Filter f) { String filterRes = f.filter(input); if (filterRes == result || filterRes.equals(result)){ counter ++; System.out.println("------------------------------------------------"); } else { System.out.println("---------------- E R R O R ---------------------"); } System.out.println(" Expected: " + result); System.out.println("************************************************\n\n"); Assert.assertEquals(result, filterRes); } @Test public void test_basics() { testsToRun = 8; t(null,null); t("", ""); t("hello", "hello"); t("°+\"*ç%&/()=?`", "°+"*ç%&/()=?`"); t("Du & ich", "Du & ich"); t("Du & ich", "Du & ich"); t("1<2", "1<2"); t("2>1", "2>1"); t(" "," "); } @Test public void test_balancing_tags() { testsToRun = 9; t("<b>hello", "<b>hello</b>"); t("<b>hello", "<b>hello</b>"); t("hello<b>", "hello"); t("hello</b>", "hello"); t("hello<b/>", "hello"); t("<b><b><b>hello", "<b><b><b>hello</b></b></b>"); t("</b><b>", ""); t("<b><i>hello</b>", "<b><i>hello</i></b>"); t("<b><i><em>hello</em></b>", "<b><i><em>hello</em></i></b>"); } @Test public void test_end_slashes() { testsToRun = 3; t("<img>", "<img />"); t("<img/>", "<img />"); t("<b/></b>", ""); } @Test public void test_balancing_angle_brackets() { testsToRun = 9; t("<img src=\"foo\"", "<img src=\"foo\" />"); t("b>", "b>"); t("<img src=\"foo\"/", "<img src=\"foo\" />"); t(">", ">"); //FIXME: what to do? it should work if in another tag! // t("foo<b", "foo<b"); // t("<span>foo<b</span>", "<span>foo<b</span>"); // t("b>foo", "b>foo"); // t("><b", "><b"); // t("><f", "><f"); t("b><", "b><"); t("><b>", ">"); } @Test public void test_attributes() { testsToRun = 6; t("<img src=foo>", "<img src=\"foo\" />"); t("<img asrc=foo>", "<img />"); t("<span title=\"bli\" > </span>", "<span title=\"bli\"> </span>"); t("<img src=test test>", "<img src=\"test\" />"); t("<img src=\"blibla\" alt=\"blubb\">", "<img alt=\"blubb\" src=\"blibla\" />"); //alt cannot contain < , title will allow it for jsMath t("<img src=\"blibla\" alt=\"a>b\">", "<img src=\"blibla\" />"); } @Test public void test_disallow_script_tags() { testsToRun = 14; t("script", "script"); t("<script>", ""); // t("<script", "<script"); t("<script", ""); t("<script/>", ""); t("</script>", ""); t("<script woo=yay>", ""); t("<script woo=\"yay\">", ""); t("<script woo=\"yay>", ""); t("<script woo=\"yay<b>", ""); t("<script<script>>", ""); t("<<script>script<script>>", "<"); t("<<script><script>>", "<"); t("<<script>script>>", "<"); t("<<script<script>>", "<"); } @Test public void test_protocols() { testsToRun = 11; t("<a href=\"http://foo\">bar</a>", "<a href=\"http://foo\">bar</a>"); // we don't allow ftp. //FIXME: is this ok? (strip link) // t("<a href=\"ftp://foo\">bar</a>", "<a href=\"#foo\">bar</a>"); t("<a href=\"ftp://foo\">bar</a>", "bar"); t("<a href=\"mailto:foo\">bar</a>", "<a href=\"mailto:foo\">bar</a>"); t("<a href=\"javascript:foo\">bar</a>", "bar"); t("<a href=\"java script:foo\">bar</a>", "bar"); t("<a href=\"java\tscript:foo\">bar</a>", "bar"); t("<a href=\"java\nscript:foo\">bar</a>", "bar"); t("<a href=\"java" + String.valueOf((char) 1) + "script:foo\">bar</a>", "bar"); t("<a href=\"jscript:foo\">bar</a>", "bar"); t("<a href=\"vbscript:foo\">bar</a>", "bar"); t("<a href=\"view-source:foo\">bar</a>", "bar"); } @Test public void test_link() { testsToRun = 1; t("<a href=\"blibla.html\" alt=\"blub\" target=\"_blank\">new window link</A>", "<a alt=\"blub\" href=\"blibla.html\" target=\"_blank\">new window link</a>"); } @Test public void test_link_htmlEntities() { testsToRun = 1; t("<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_S&gen--496\">new window link</a>", "<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_S&gen--496\">new window link</a>"); t("<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_Sägen--496\">new window link</a>", "<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_Sägen--496\">new window link</a>"); t("<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_Ságen--496\">new window link</a>", "<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_Ságen--496\">new window link</a>"); //escape unkown entity t("<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_S&xss;gen--496\">new window link</a>", "<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_S&xss;gen--496\">new window link</a>"); //check if escaped result is allowed t("<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_S&xss;gen--496\">new window link</a>", "<a href=\"http://www.schreinersicht.ch/artikel/Mehr_als_nur_S&xss;gen--496\">new window link</a>"); } @Test public void test_link_complexer(){ testsToRun = 1; t("<a class=\"o_icon_link_extern\" target=\"_blank\" href=\"http://www.frentix.com\" onclick=\"javascript:alert('hallo');\" title=\"a good link\">a complicated link</a>", "<a class=\"o_icon_link_extern\" href=\"http://www.frentix.com\" target=\"_blank\" title=\"a good link\">a complicated link</a>"); } @Test public void test_self_closing_tags() { testsToRun = 3; t("<img src=\"a\">", "<img src=\"a\" />"); t("<img src=\"a\">foo</img>", "<img src=\"a\" />foo"); t("</img>", ""); } @Test public void test_comments() { testsToRun = 4; t("<!-- a<b --->", ""); t("<!-- a<b -->don't remove me<!-- hello world -->", "don't remove me"); t("<!-- a<b \n <!-- hello world \n -->", ""); t("<!--comments1--> visible text <!--comments2-->", " visible text "); } @Test public void test_tiny_paragraph(){ testsToRun = 8; t("<span>bliblablu</span>", "<span>bliblablu</span>"); t("<p style=\"text-align: right;\">right orientation</p>", "<p style=\"text-align: right;\">right orientation</p>"); t("<h1>Big font</h1>", "<h1>Big font</h1>"); t("<h7>small font</h7>", "small font"); t("<span style=\"font-family: wingdings;\">invalid font</span>", "<span style=\"font-family: wingdings;\">invalid font</span>"); t("<span style=\"font-family: serif;\">invalid font</span>", "<span style=\"font-family: serif;\">invalid font</span>"); //FIXME:RH: to allow multiple fonts (as output from tiny) //committed as bug: http://code.google.com/p/owaspantisamy/issues/detail?id=49 // t("<span style=\"font-family: serif, arial;\">preformated</span>", "<span style=\"font-family: courier new , courier;\">preformated</span>"); t("<span class=\"schoen\">irgendwas</span>", "<span class=\"schoen\">irgendwas</span>"); } @Test public void test_tiny_lists(){ testsToRun = 2; //lists (output without \n as policy has formatOutput = false t("<ul>\n<li>a list: adsf</li>\n<li>adsf</li>\n<li>adsfas</li>\n</ul>", "<ul>\n<li>a list: adsf</li>\n<li>adsf</li>\n<li>adsfas</li>\n</ul>"); t("<ol style=\"font-size: 20pt;\">\n<li>numbered list</li>\n<li>adf</li>\n<li>asdfa</li>\n</ol>", "<ol style=\"font-size: 20.0pt;\">\n<li>numbered list</li>\n<li>adf</li>\n<li>asdfa</li>\n</ol>"); } @Test public void test_tiny_tables(){ testsToRun = 2; //tables t("<table border=\"1\" style=\"width: 268px; height: 81px;\" class=\"table\">\n<caption>bliblablue</caption>\n<tbody>\n<tr>\n<td>\n<p>adsfadsf</p>\n</td>\n<td>asdf</td>\n</tr>\n<tr>\n<td>asf</td>\n<td>\n<p>asdf</p>\n</td>\n</tr>\n</tbody>\n</table>", "<table border=\"1\" class=\"table\" style=\"width: 268.0px;height: 81.0px;\">\n<caption>bliblablue</caption>\n<tbody>\n<tr>\n<td>\n<p>adsfadsf</p>\n</td>\n<td>asdf</td>\n</tr>\n<tr>\n<td>asf</td>\n<td>\n<p>asdf</p>\n</td>\n</tr>\n</tbody>\n</table>"); t("<tr style=\"background-color: rgb(46, 147, 209);\">\n<td style=\"border: 1px solid rgb(240, 68, 14);\">asf</td>\n<td>\n<p>asdf</p>\n</td>\n</tr>","\nasf\n\n<p>asdf</p>\n"); } @Test public void test_tiny_singleElements(){ testsToRun = 1; //sup/sub t("<p><sup>super</sup>script <sub>sub</sub>script</p>", "<p><sup>super</sup>script <sub>sub</sub>script</p>"); } @Test public void test_tiny_jsmath(){ testsToRun = 2; t("<span title=\"a%20%3C%20b%20%3E%20c%20%3C%20/b%20%3E\"> </span>","<span title=\"a%20%3C%20b%20%3E%20c%20%3C%20/b%20%3E\"> </span>"); // should be saved with entities not with < etc... // t("<span title=\"a>b\"> </span>", "<span title=\"a>b\"> </span>"); } @Test public void test_font_awesome() { // for now i tags must have at least a space to not b removed t("<i class=\"o_icon o_icon_dev\"> </i> ", "<i class=\"o_icon o_icon_dev\"> </i> "); } @Test public void test_big_tiny_output(){ testsToRun = 1; String input = "<br>"; String output = "<br />"; t(input,output); } @Test public void test_rawText() { OWASPAntiSamyXSSFilter intlFilter = new OWASPAntiSamyXSSFilter(-1, false, true); t("Stéphane Rossé", "Stéphane Rossé", intlFilter); } @Test public void test_rawTextAttaqu() { OWASPAntiSamyXSSFilter intlFilter = new OWASPAntiSamyXSSFilter(-1, false, true); t("<script>alert('hello');<//script>", "<script>alert('hello');<//script>", intlFilter); } }