diff options
author | Stanislav-Wolski <stanislau.wolski@gmail.com> | 2012-05-21 19:54:39 +0300 |
---|---|---|
committer | Stanislav-Wolski <stanislau.wolski@gmail.com> | 2012-05-21 19:54:39 +0300 |
commit | 23ad1746c8a823f81099b66a4dcc66310c657827 (patch) | |
tree | e3f3e57478f86451f278190aae5932fb65475499 /codebase | |
parent | 2f3109a94c96af3cbaa8973407d27d072d489248 (diff) | |
download | connector-php-23ad1746c8a823f81099b66a4dcc66310c657827.zip connector-php-23ad1746c8a823f81099b66a4dcc66310c657827.tar.gz connector-php-23ad1746c8a823f81099b66a4dcc66310c657827.tar.bz2 |
[add] xss filter
Diffstat (limited to 'codebase')
-rw-r--r-- | codebase/data_connector.php | 9 | ||||
-rw-r--r-- | codebase/dataprocessor.php | 5 | ||||
-rw-r--r-- | codebase/xss_filter.php | 163 |
3 files changed, 174 insertions, 3 deletions
diff --git a/codebase/data_connector.php b/codebase/data_connector.php index 45660db..ce454b9 100644 --- a/codebase/data_connector.php +++ b/codebase/data_connector.php @@ -9,8 +9,13 @@ class CommonDataProcessor extends DataProcessor{ protected function get_post_values($ids){ if (isset($_GET['action'])){ $data = array(); - if (isset($_POST["id"])) - $data[$_POST["id"]] = $_POST; + if (isset($_POST["id"])){ + $dataset = array(); + foreach($_POST as $key=>$value) + $dataset[$key] = ConnectorSecurity::filter($value); + + $data[$_POST["id"]] = $dataset; + } else $data["dummy_id"] = $_POST; return $data; diff --git a/codebase/dataprocessor.php b/codebase/dataprocessor.php index 348c8e2..8418d40 100644 --- a/codebase/dataprocessor.php +++ b/codebase/dataprocessor.php @@ -5,6 +5,9 @@ */ /*! Base DataProcessor handling **/ + +require_once("xss_filter.php"); + class DataProcessor{ protected $connector;//!< Connector instance protected $config;//!< DataConfig instance @@ -52,7 +55,7 @@ class DataProcessor{ if (sizeof($details)==1) continue; $name=$this->name_data($details[1]); - $data[$details[0]][$name]=$value; + $data[$details[0]][$name]=ConnectorSecurity::filter($value); } return $data; diff --git a/codebase/xss_filter.php b/codebase/xss_filter.php new file mode 100644 index 0000000..2ac55bb --- /dev/null +++ b/codebase/xss_filter.php @@ -0,0 +1,163 @@ +<?php + +// +----------------------------------------------------------------------+ +// | Copyright (c) 2001-2008 Liip AG | +// +----------------------------------------------------------------------+ +// | Licensed under the Apache License, Version 2.0 (the "License"); | +// | you may not use this file except in compliance with the License. | +// | You may obtain a copy of the License at | +// | http://www.apache.org/licenses/LICENSE-2.0 | +// | Unless required by applicable law or agreed to in writing, software | +// | distributed under the License is distributed on an "AS IS" BASIS, | +// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | +// | implied. See the License for the specific language governing | +// | permissions and limitations under the License. | +// +----------------------------------------------------------------------+ +// | Author: Christian Stocker <christian.stocker@liip.ch> | +// +----------------------------------------------------------------------+ + + +//original name was lx_externalinput_clean +//renamed to prevent possible conflicts +class dhx_externalinput_clean { + // this basic clean should clean html code from + // lot of possible malicious code for Cross Site Scripting + // use it whereever you get external input + + // you can also set $filterOut to some use html cleaning, but I don't know of any code, which could + // exploit that. But if you want to be sure, set it to eg. array("Tidy","Dom"); + static function basic($string, $filterIn = array("Tidy","Dom","Striptags"), $filterOut = "none") { + $string = self::tidyUp($string, $filterIn); + $string = str_replace(array("&", "<", ">"), array("&amp;", "&lt;", "&gt;"), $string); + + // fix &entitiy\n; + $string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u', "$1;", $string); + $string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $string); + + $string = html_entity_decode($string, ENT_COMPAT, "UTF-8"); + + // remove any attribute starting with "on" or xmlns + $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])(on|xmlns)[^>]*>#iUu', "$1>", $string); + + // remove javascript: and vbscript: protocol + $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2nojavascript...', $string); + $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2novbscript...', $string); + $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*-moz-binding[\x00-\x20]*:#Uu', '$1=$2nomozbinding...', $string); + $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*data[\x00-\x20]*:#Uu', '$1=$2nodata...', $string); + + //remove any style attributes, IE allows too much stupid things in them, eg. + //<span style="width: expression(alert('Ping!'));"></span> + // and in general you really don't want style declarations in your UGC + + $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])style[^>]*>#iUu', "$1>", $string); + + //remove namespaced elements (we do not need them...) + $string = preg_replace('#</*\w+:\w[^>]*>#i', "", $string); + + //remove really unwanted tags + do { + $oldstring = $string; + $string = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $string); + } while ($oldstring != $string); + + return self::tidyUp($string, $filterOut); + } + + static function tidyUp($string, $filters) { + if (is_array($filters)) { + foreach ($filters as $filter) { + $return = self::tidyUpWithFilter($string, $filter); + if ($return !== false) { + return $return; + } + } + } else { + $return = self::tidyUpWithFilter($string, $filters); + } + // if no filter matched, use the Striptags filter to be sure. + if ($return === false) { + return self::tidyUpModuleStriptags($string); + } else { + return $return; + } + } + + static private function tidyUpWithFilter($string, $filter) { + if (is_callable(array("self", "tidyUpModule" . $filter))) { + return call_user_func(array("self", "tidyUpModule" . $filter), $string); + } + return false; + } + + static private function tidyUpModuleStriptags($string) { + + return strip_tags($string); + } + + static private function tidyUpModuleNone($string) { + return $string; + } + + static private function tidyUpModuleDom($string) { + $dom = new domdocument(); + @$dom->loadHTML("<html><body>" . $string . "</body></html>"); + $string = ''; + foreach ($dom->documentElement->firstChild->childNodes as $child) { + $string .= $dom->saveXML($child); + } + return $string; + } + + static private function tidyUpModuleTidy($string) { + if (class_exists("tidy")) { + $tidy = new tidy(); + $tidyOptions = array("output-xhtml" => true, + "show-body-only" => true, + "clean" => true, + "wrap" => "350", + "indent" => true, + "indent-spaces" => 1, + "ascii-chars" => false, + "wrap-attributes" => false, + "alt-text" => "", + "doctype" => "loose", + "numeric-entities" => true, + "drop-proprietary-attributes" => true, + "enclose-text" => false, + "enclose-block-text" => false + + ); + $tidy->parseString($string, $tidyOptions, "utf8"); + $tidy->cleanRepair(); + return (string) $tidy; + } else { + return false; + } + } +} + +define("DHX_SECURITY_SAFETEXT", 1); +define("DHX_SECURITY_SAFEHTML", 2); +define("DHX_SECURITY_TRUSTED", 3); + +class ConnectorSecurity{ + static public $xss = DHX_SECURITY_SAFETEXT; + static public $csrf = false; + + static private $filterClass = null; + static function filter($value, $mode = false){ + if ($mode === false) + $mode = ConnectorSecurity::$xss; + + if ($mode == DHX_SECURITY_TRUSTED) + return $value; + if ($mode == DHX_SECURITY_SAFETEXT) + return filter_var($value, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES); + if ($mode == DHX_SECURITY_SAFEHTML){ + if (ConnectorSecurity::$filterClass == null) + ConnectorSecurity::$filterClass = new dhx_externalinput_clean(); + return ConnectorSecurity::$filterClass->basic($value); + } + throw new Error("Invalid security mode:"+$mode); + } +}
\ No newline at end of file |