summaryrefslogtreecommitdiffstats
path: root/codebase
diff options
context:
space:
mode:
authorDmitry <dmitry@dhtmlx.com>2012-05-22 16:51:16 +0200
committerDmitry <dmitry@dhtmlx.com>2012-05-22 16:51:16 +0200
commit026ddb3374e533dbd26a3374eb316092e762e2a3 (patch)
tree89a9ee5f03b3c755d9498681c0ec64cf7eb45bb8 /codebase
parentdff9912b9ee40fbac29c54b4cf67591e11b5e4cb (diff)
parent05ad07fee439616159c687a806270fd587af9abc (diff)
downloadconnector-php-026ddb3374e533dbd26a3374eb316092e762e2a3.zip
connector-php-026ddb3374e533dbd26a3374eb316092e762e2a3.tar.gz
connector-php-026ddb3374e533dbd26a3374eb316092e762e2a3.tar.bz2
Merge branch 'master' of 192.168.1.251:connector-php
Diffstat (limited to 'codebase')
-rw-r--r--codebase/data_connector.php30
-rw-r--r--codebase/dataprocessor.php5
-rw-r--r--codebase/xss_filter.php195
3 files changed, 225 insertions, 5 deletions
diff --git a/codebase/data_connector.php b/codebase/data_connector.php
index 36cafa0..ac76c74 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;
@@ -90,9 +95,13 @@ class DataConnector extends Connector{
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
if (!$item_type) $item_type="CommonDataItem";
if (!$data_type) $data_type="CommonDataProcessor";
- $section = array();
+
+ $this->sections = array();
+ $this->attributes = array();
+
if (!$render_type) $render_type="RenderStrategy";
parent::__construct($res,$type,$item_type,$data_type,$render_type);
+
}
protected $sections;
@@ -100,6 +109,11 @@ class DataConnector extends Connector{
$this->sections[$name] = $string;
}
+ protected $attributes;
+ public function add_top_attribute($name, $string){
+ $this->attributes[$name] = $string;
+ }
+
protected function parse_request_mode(){
//do nothing, at least for now
}
@@ -130,12 +144,20 @@ class DataConnector extends Connector{
if (isset($_GET["start"]) && isset($_GET["count"]))
$this->request->set_limit($_GET["start"],$_GET["count"]);
+
+ $key = ConnectorSecurity::checkCSRF($this->editing);
+ if ($key !== "")
+ $this->add_top_attribute("dhx_security", $key);
}
/*! renders self as xml, starting part
*/
protected function xml_start(){
- $start = "<data>";
+ $start = "<data";
+ foreach($this->attributes as $k=>$v)
+ $start .= " ".$k."='".$v."'";
+ $start.= ">";
+
foreach($this->sections as $k=>$v)
$start .= "<".$k.">".$v."</".$k.">\n";
return $start;
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..9018443
--- /dev/null
+++ b/codebase/xss_filter.php
@@ -0,0 +1,195 @@
+<?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 $security_key = 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);
+ }
+
+ static function CSRF_detected(){
+ LogMaster::log("[SECURITY] Possible CSRF attack detected", array(
+ "referer" => $_SERVER["HTTP_REFERER"],
+ "remote" => $_SERVER["REMOTE_ADDR"]
+ ));
+ LogMaster::log("Request data", $_POST);
+ die();
+ }
+ static function checkCSRF($edit){
+ @session_start();
+
+ if (ConnectorSecurity::$security_key){
+ if ($edit=== true){
+ if (!isset($_POST['dhx_security']))
+ return ConnectorSecurity::CSRF_detected();
+ $master_key = $_SESSION['dhx_security'];
+ $update_key = $_POST['dhx_security'];
+ if ($master_key != $update_key)
+ return ConnectorSecurity::CSRF_detected();
+
+ return "";
+ }
+ //data loading
+ if (!array_key_exists("dhx_security",$_SESSION)){
+ $_SESSION["dhx_security"] = md5(uniqid());
+ }
+
+ return $_SESSION["dhx_security"];
+ }
+ }
+
+} \ No newline at end of file