* (feature) Add new external library "RemoveXSS" for easily filtering potential Cross...
authorMichael Stucki <michael.stucki@typo3.org>
Mon, 15 Oct 2007 10:10:33 +0000 (10:10 +0000)
committerMichael Stucki <michael.stucki@typo3.org>
Mon, 15 Oct 2007 10:10:33 +0000 (10:10 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@2550 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/class.t3lib_div.php
typo3/contrib/RemoveXSS/RemoveXSS.php [new file with mode: 0644]

index cc63620..6365812 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2007-10-15  Michael Stucki  <michael@typo3.org>
+
+       * (feature) Add new external library "RemoveXSS" for easily filtering potential Cross Site Scripting (XSS) attacks. Can be used by any script. Usage: $filtered_string = t3lib_div::removeXSS($input_string); Thanks to Travis Puderbaugh <kallahar@quickwired.com> for providing this nice piece of code!
+
 2007-10-13  Ingo Renner  <ingo@typo3.org>
 
        * Fixed bug 6517: Add icons and grouping to the page type selector
index e1a6650..f33f0d2 100755 (executable)
@@ -358,6 +358,21 @@ class t3lib_div {
                return $mergedA;
        }
 
+       /**
+        * Wrapper for the RemoveXSS function.
+        * Removes potential XSS code from an input string.
+        *
+        * Using an external class by Travis Puderbaugh <kallahar@quickwired.com>
+        *
+        * @param       string          Input string
+        * @return      string          Input string with potential XSS code removed
+        */
+       public function removeXSS($string)      {
+               require_once(PATH_typo3.'contrib/RemoveXSS/RemoveXSS.php');
+               $string = RemoveXSS::RemoveXSS($string);
+               return $string;
+       }
+
 
 
 
diff --git a/typo3/contrib/RemoveXSS/RemoveXSS.php b/typo3/contrib/RemoveXSS/RemoveXSS.php
new file mode 100644 (file)
index 0000000..ca48f3b
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Usage: Run *every* variable passed in through it.
+ * The goal of this function is to be a generic function that can be used to
+ * parse almost any input and render it XSS safe. For more information on
+ * actual XSS attacks, check out http://ha.ckers.org/xss.html. Another
+ * excellent site is the XSS Database which details each attack and how it
+ * works.
+ *
+ * Used with permission by the author.
+ * URL: http://quickwired.com/smallprojects/php_xss_filter_function.php
+ *
+ * License:
+ * This code is public domain, you are free to do whatever you want with it,
+ * including adding it to your own project which can be under any license.
+ *
+ * $Id$
+ *
+ * @author     Travis Puderbaugh <kallahar@quickwired.com>
+ * @package RemoveXSS
+ */
+class RemoveXSS {
+
+       /**
+        * Wrapper for the RemoveXSS function.
+        * Removes potential XSS code from an input string.
+        *
+        * Using an external class by Travis Puderbaugh <kallahar@quickwired.com>
+        *
+        * @param       string          Input string
+        * @return      string          Input string with potential XSS code removed
+        */
+       function RemoveXSS($val)        {
+               // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
+               // this prevents some character re-spacing such as <java\0script>
+               // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
+               $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
+
+               // straight replacements, the user should never need these since they're normal characters
+               // this prevents like <IMG SRC=&#X40&#X61&#X76&#X61&#X73&#X63&#X72&#X69&#X70&#X74&#X3A&#X61&#X6C&#X65&#X72&#X74&#X28&#X27&#X58&#X53&#X53&#X27&#X29>
+               $search = 'abcdefghijklmnopqrstuvwxyz';
+               $search.= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+               $search.= '1234567890!@#$%^&*()';
+               $search.= '~`";:?+/={}[]-_|\'\\';
+
+               for ($i = 0; $i < strlen($search); $i++) {
+                       // ;? matches the ;, which is optional
+                       // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
+
+                       // &#x0040 @ search for the hex values
+                       $val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
+                       // &#00064 @ 0{0,7} matches '0' zero to seven times
+                       $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
+               }
+
+               // now the only remaining whitespace attacks are \t, \n, and \r
+               $ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
+               $ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
+               $ra = array_merge($ra1, $ra2);
+
+               $found = true; // keep replacing as long as the previous round replaced something
+               while ($found == true) {
+                       $val_before = $val;
+                       for ($i = 0; $i < sizeof($ra); $i++) {
+                               $pattern = '/';
+                               for ($j = 0; $j < strlen($ra[$i]); $j++) {
+                                       if ($j > 0) {
+                                               $pattern .= '(';
+                                               $pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
+                                               $pattern .= '|(&#0{0,8}([9][10][13]);?)?';
+                                               $pattern .= ')?';
+                                       }
+                                       $pattern .= $ra[$i][$j];
+                               }
+                               $pattern .= '/i';
+                               $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
+                               $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
+                               if ($val_before == $val) {
+                                       // no replacements were made, so exit the loop
+                                       $found = false;
+                               }
+                       }
+               }
+
+               return $val;
+       }
+}
+
+?>
\ No newline at end of file