summaryrefslogtreecommitdiffstats
path: root/codebase
diff options
context:
space:
mode:
authorStanislav-Wolski <stanislau.wolski@gmail.com>2012-05-21 19:54:39 +0300
committerStanislav-Wolski <stanislau.wolski@gmail.com>2012-05-21 19:54:39 +0300
commit23ad1746c8a823f81099b66a4dcc66310c657827 (patch)
treee3f3e57478f86451f278190aae5932fb65475499 /codebase
parent2f3109a94c96af3cbaa8973407d27d072d489248 (diff)
downloadconnector-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.php9
-rw-r--r--codebase/dataprocessor.php5
-rw-r--r--codebase/xss_filter.php163
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("&amp;", "&lt;", "&gt;"), array("&amp;amp;", "&amp;lt;", "&amp;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