From cb1221013251b4e9cba8e129edc6b8dbd8fd5145 Mon Sep 17 00:00:00 2001
From: Till Brehm <tbrehm@ispconfig.org>
Date: Mon, 25 Aug 2014 09:33:09 -0400
Subject: [PATCH] FS#3640 - Add Intrusion Detection System
---
interface/lib/classes/IDS/license.txt | 18
interface/lib/classes/IDS/default_filter.xml | 787 +++++++
install/dist/lib/fedora.lib.php | 6
interface/lib/classes/IDS/Caching/MemcachedCache.php | 181 +
interface/lib/classes/IDS/Init.php | 174 +
security/ids.whitelist | 45
interface/lib/classes/IDS/Converter.php | 779 +++++++
interface/lib/classes/IDS/Monitor.php | 566 +++++
install/lib/installer_base.lib.php | 6
interface/lib/classes/IDS/Filter/Storage.php | 401 ++++
interface/lib/classes/IDS/Caching/DatabaseCache.php | 277 ++
interface/lib/classes/IDS/Filter.php | 175 +
interface/lib/classes/IDS/Caching/ApcCache.php | 144 +
interface/lib/classes/getconf.inc.php | 18
interface/lib/classes/db_mysql.inc.php | 47
interface/lib/classes/IDS/default_filter.json | 933 +++++++++
interface/lib/classes/IDS/Caching/CacheFactory.php | 85
install/dist/lib/gentoo.lib.php | 6
install/dist/lib/opensuse.lib.php | 6
interface/lib/classes/ids.inc.php | 149 +
security/security_settings.ini | 9
interface/lib/classes/IDS/Config.ini.php | 59
interface/lib/classes/IDS/.htaccess | 5
interface/lib/classes/IDS/Caching/CacheInterface.php | 64
interface/lib/classes/IDS/Caching/SessionCache.php | 136 +
interface/lib/classes/IDS/Event.php | 221 ++
interface/lib/classes/IDS/Caching/FileCache.php | 189 +
interface/lib/classes/IDS/Version.php | 49
security/apache_directives.blacklist | 3
security/ids.htmlfield | 5
interface/lib/app.inc.php | 13
interface/lib/classes/IDS/Report.php | 339 +++
interface/lib/classes/IDS/Config/Config.ini.php | 91
33 files changed, 5,979 insertions(+), 7 deletions(-)
diff --git a/install/dist/lib/fedora.lib.php b/install/dist/lib/fedora.lib.php
index a7179ef..7dd7d9b 100644
--- a/install/dist/lib/fedora.lib.php
+++ b/install/dist/lib/fedora.lib.php
@@ -1010,6 +1010,12 @@
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
$command = 'chown root:ispconfig '.$install_dir.'/security';
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.whitelist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.htmlfield';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/apache_directives.blacklist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
//* Make the global language file directory group writable
exec("chmod -R 770 $install_dir/interface/lib/lang");
diff --git a/install/dist/lib/gentoo.lib.php b/install/dist/lib/gentoo.lib.php
index 153a4e0..005a2fc 100644
--- a/install/dist/lib/gentoo.lib.php
+++ b/install/dist/lib/gentoo.lib.php
@@ -903,6 +903,12 @@
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
$command = 'chown root:ispconfig '.$install_dir.'/security';
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.whitelist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.htmlfield';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/apache_directives.blacklist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
//* Make the global language file directory group writable
exec("chmod -R 770 $install_dir/interface/lib/lang");
diff --git a/install/dist/lib/opensuse.lib.php b/install/dist/lib/opensuse.lib.php
index 935b816..ea13cd2 100644
--- a/install/dist/lib/opensuse.lib.php
+++ b/install/dist/lib/opensuse.lib.php
@@ -1081,6 +1081,12 @@
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
$command = 'chown root:ispconfig '.$install_dir.'/security';
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.whitelist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.htmlfield';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/apache_directives.blacklist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
//* Make the global language file directory group writable
exec("chmod -R 770 $install_dir/interface/lib/lang");
diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php
index 538f21e..a30a7ec 100644
--- a/install/lib/installer_base.lib.php
+++ b/install/lib/installer_base.lib.php
@@ -1937,6 +1937,12 @@
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
$command = 'chown root:ispconfig '.$install_dir.'/security';
caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.whitelist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/ids.htmlfield';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
+ $command = 'chown root:ispconfig '.$install_dir.'/security/apache_directives.blacklist';
+ caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
//* Make the global language file directory group writable
exec("chmod -R 770 $install_dir/interface/lib/lang");
diff --git a/interface/lib/app.inc.php b/interface/lib/app.inc.php
index 8832f45..615e390 100755
--- a/interface/lib/app.inc.php
+++ b/interface/lib/app.inc.php
@@ -48,6 +48,7 @@
private $_wb;
private $_loaded_classes = array();
private $_conf;
+ private $_security_config;
public $loaded_plugins = array();
@@ -109,7 +110,8 @@
}
$this->uses('functions'); // we need this before all others!
- $this->uses('auth,plugin');
+ $this->uses('auth,plugin,ini_parser,getconf');
+
}
public function __get($prop) {
@@ -327,4 +329,13 @@
//* possible future = new app($conf);
$app = new app();
+// load and enable PHP Intrusion Detection System (PHPIDS)
+$ids_security_config = $app->getconf->get_security_config('ids');
+
+if(is_dir(ISPC_CLASS_PATH.'/IDS') && $ids_security_config['ids_enabled'] == 'yes') {
+ $app->uses('ids');
+ $app->ids->start();
+}
+unset($ids_security_config);
+
?>
diff --git a/interface/lib/classes/IDS/.htaccess b/interface/lib/classes/IDS/.htaccess
new file mode 100644
index 0000000..878d02a
--- /dev/null
+++ b/interface/lib/classes/IDS/.htaccess
@@ -0,0 +1,5 @@
+# in case PHPIDS is placed in the web-root
+deny from all
+
+# silence is golden
+php_flag display_errors off
\ No newline at end of file
diff --git a/interface/lib/classes/IDS/Caching/ApcCache.php b/interface/lib/classes/IDS/Caching/ApcCache.php
new file mode 100644
index 0000000..e82cc88
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/ApcCache.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+
+namespace IDS\Caching;
+
+/**
+ * APC caching wrapper
+ *
+ * This class inhabits functionality to get and set cache via memcached.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Yves Berkholz <godzilla80@gmx.net>
+ * @copyright 2007-2009 The PHPIDS Groupoup
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.6.5
+ */
+class ApcCache implements CacheInterface
+{
+ /**
+ * Caching type
+ *
+ * @var string
+ */
+ private $type = null;
+
+ /**
+ * Cache configuration
+ *
+ * @var array
+ */
+ private $config = null;
+
+ /**
+ * Flag if the filter storage has been found in memcached
+ *
+ * @var boolean
+ */
+ private $isCached = false;
+
+ /**
+ * Holds an instance of this class
+ *
+ * @var object
+ */
+ private static $cachingInstance = null;
+
+ /**
+ * Constructor
+ *
+ * @param string $type caching type
+ * @param array $init the IDS_Init object
+ *
+ * @return void
+ */
+ public function __construct($type, $init)
+ {
+ $this->type = $type;
+ $this->config = $init->config['Caching'];
+ }
+
+ /**
+ * Returns an instance of this class
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return object $this
+ */
+ public static function getInstance($type, $init)
+ {
+ if (!self::$cachingInstance) {
+ self::$cachingInstance = new ApcCache($type, $init);
+ }
+
+ return self::$cachingInstance;
+ }
+
+ /**
+ * Writes cache data
+ *
+ * @param array $data the caching data
+ *
+ * @return object $this
+ */
+ public function setCache(array $data)
+ {
+ if (!$this->isCached) {
+ apc_store(
+ $this->config['key_prefix'] . '.storage',
+ $data,
+ $this->config['expiration_time']
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the cached data
+ *
+ * Note that this method returns false if either type or file cache is
+ * not set
+ *
+ * @return mixed cache data or false
+ */
+ public function getCache()
+ {
+ $data = apc_fetch($this->config['key_prefix'] . '.storage');
+ $this->isCached = !empty($data);
+
+ return $data;
+ }
+}
diff --git a/interface/lib/classes/IDS/Caching/CacheFactory.php b/interface/lib/classes/IDS/Caching/CacheFactory.php
new file mode 100644
index 0000000..c358332
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/CacheFactory.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS\Caching;
+
+/**
+ * Caching factory
+ *
+ * This class is used as a factory to load the correct concrete caching
+ * implementation.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class CacheFactory
+{
+ /**
+ * Factory method
+ *
+ * @param object $init the IDS_Init object
+ * @param string $type the caching type
+ *
+ * @return object the caching facility
+ */
+ public static function factory($init, $type)
+ {
+ $object = false;
+ $wrapper = preg_replace(
+ '/\W+/m',
+ null,
+ ucfirst($init->config['Caching']['caching'])
+ );
+ $class = '\\IDS\\Caching\\' . $wrapper . 'Cache';
+ $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . $wrapper . 'Cache.php';
+
+ if (file_exists($path)) {
+ include_once $path;
+
+ if (class_exists($class)) {
+ $object = call_user_func(
+ array('' . $class, 'getInstance'),
+ $type,
+ $init
+ );
+ }
+ }
+
+ return $object;
+ }
+}
diff --git a/interface/lib/classes/IDS/Caching/CacheInterface.php b/interface/lib/classes/IDS/Caching/CacheInterface.php
new file mode 100644
index 0000000..c1a6a60
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/CacheInterface.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS\Caching;
+
+/**
+ * Caching wrapper interface
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @since Version 0.4
+ * @link http://php-ids.org/
+ */
+interface CacheInterface
+{
+ /**
+ * Interface method
+ *
+ * @param array $data the cache data
+ *
+ * @return void
+ */
+ public function setCache(array $data);
+
+ /**
+ * Interface method
+ *
+ * @return void
+ */
+ public function getCache();
+}
diff --git a/interface/lib/classes/IDS/Caching/DatabaseCache.php b/interface/lib/classes/IDS/Caching/DatabaseCache.php
new file mode 100644
index 0000000..09c77a8
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/DatabaseCache.php
@@ -0,0 +1,277 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS\Caching;
+
+/**
+ *
+ */
+
+/**
+ * Database caching wrapper
+ *
+ * This class inhabits functionality to get and set cache via a database.
+ *
+ * Needed SQL:
+ *
+
+#create the database
+
+CREATE DATABASE IF NOT EXISTS `phpids` DEFAULT CHARACTER
+SET utf8 COLLATE utf8_general_ci;
+DROP TABLE IF EXISTS `cache`;
+
+#now select the created datbase and create the table
+
+CREATE TABLE `cache` (
+`type` VARCHAR( 32 ) NOT null ,
+`data` TEXT NOT null ,
+`created` DATETIME NOT null ,
+`modified` DATETIME NOT null
+) ENGINE = MYISAM ;
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Groupup
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class DatabaseCache implements CacheInterface
+{
+
+ /**
+ * Caching type
+ *
+ * @var string
+ */
+ private $type = null;
+
+ /**
+ * Cache configuration
+ *
+ * @var array
+ */
+ private $config = null;
+
+ /**
+ * DBH
+ *
+ * @var object
+ */
+ private $handle = null;
+
+ /**
+ * Holds an instance of this class
+ *
+ * @var object
+ */
+ private static $cachingInstance = null;
+
+ /**
+ * Constructor
+ *
+ * Connects to database.
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return void
+ */
+ public function __construct($type, $init)
+ {
+ $this->type = $type;
+ $this->config = $init->config['Caching'];
+ $this->handle = $this->connect();
+ }
+
+ /**
+ * Returns an instance of this class
+ *
+ * @static
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return object $this
+ */
+ public static function getInstance($type, $init)
+ {
+
+ if (!self::$cachingInstance) {
+ self::$cachingInstance = new DatabaseCache($type, $init);
+ }
+
+ return self::$cachingInstance;
+ }
+
+ /**
+ * Writes cache data into the database
+ *
+ * @param array $data the caching data
+ *
+ * @throws PDOException if a db error occurred
+ * @return object $this
+ */
+ public function setCache(array $data)
+ {
+ $handle = $this->handle;
+
+ $rows = $handle->query('SELECT created FROM `' . $this->config['table'].'`');
+
+ if (!$rows || $rows->rowCount() === 0) {
+
+ $this->write($handle, $data);
+ } else {
+
+ foreach ($rows as $row) {
+
+ if ((time()-strtotime($row['created'])) >
+ $this->config['expiration_time']) {
+
+ $this->write($handle, $data);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the cached data
+ *
+ * Note that this method returns false if either type or file cache is
+ * not set
+ *
+ * @throws PDOException if a db error occurred
+ * @return mixed cache data or false
+ */
+ public function getCache()
+ {
+ try {
+ $handle = $this->handle;
+ $result = $handle->prepare(
+ 'SELECT * FROM `' .
+ $this->config['table'] .
+ '` where type=?'
+ );
+ $result->execute(array($this->type));
+
+ foreach ($result as $row) {
+ return unserialize($row['data']);
+ }
+
+ } catch (\PDOException $e) {
+ throw new \PDOException('PDOException: ' . $e->getMessage());
+ }
+
+ return false;
+ }
+
+ /**
+ * Connect to database and return a handle
+ *
+ * @return object PDO
+ * @throws Exception if connection parameters are faulty
+ * @throws PDOException if a db error occurred
+ */
+ private function connect()
+ {
+ // validate connection parameters
+ if (!$this->config['wrapper']
+ || !$this->config['user']
+ || !$this->config['password']
+ || !$this->config['table']) {
+
+ throw new \Exception('Insufficient connection parameters');
+ }
+
+ // try to connect
+ try {
+ $handle = new \PDO(
+ $this->config['wrapper'],
+ $this->config['user'],
+ $this->config['password']
+ );
+ $handle->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
+
+ } catch (\PDOException $e) {
+ throw new \PDOException('PDOException: ' . $e->getMessage());
+ }
+
+ return $handle;
+ }
+
+ /**
+ * Write the cache data to the table
+ *
+ * @param object $handle the database handle
+ * @param array $data the caching data
+ *
+ * @return object PDO
+ * @throws PDOException if a db error occurred
+ */
+ private function write($handle, $data)
+ {
+ try {
+ $handle->query('TRUNCATE ' . $this->config['table'].'');
+ $statement = $handle->prepare(
+ 'INSERT INTO `' .
+ $this->config['table'].'` (
+ type,
+ data,
+ created,
+ modified
+ )
+ VALUES (
+ :type,
+ :data,
+ now(),
+ now()
+ )'
+ );
+
+ $statement->bindValue(
+ 'type',
+ $handle->quote($this->type)
+ );
+ $statement->bindValue('data', serialize($data));
+
+ if (!$statement->execute()) {
+ throw new \PDOException($statement->errorCode());
+ }
+ } catch (\PDOException $e) {
+ throw new \PDOException('PDOException: ' . $e->getMessage());
+ }
+ }
+}
diff --git a/interface/lib/classes/IDS/Caching/FileCache.php b/interface/lib/classes/IDS/Caching/FileCache.php
new file mode 100644
index 0000000..71f01c7
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/FileCache.php
@@ -0,0 +1,189 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS\Caching;
+
+use IDS\Init;
+
+/**
+ * File caching wrapper
+ *
+ * This class inhabits functionality to get and set cache via a static flatfile.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class FileCache implements CacheInterface
+{
+ /**
+ * Caching type
+ *
+ * @var string
+ */
+ private $type;
+
+ /**
+ * Cache configuration
+ *
+ * @var array
+ */
+ private $config;
+
+ /**
+ * Path to cache file
+ *
+ * @var string
+ */
+ private $path;
+
+ /**
+ * Holds an instance of this class
+ *
+ * @var object
+ */
+ private static $cachingInstance;
+
+ /**
+ * Constructor
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ * @throws \Exception
+ *
+ * @return void
+ */
+ public function __construct($type, Init $init)
+ {
+ $this->type = $type;
+ $this->config = $init->config['Caching'];
+ $this->path = $init->getBasePath() . $this->config['path'];
+
+ if (file_exists($this->path) && !is_writable($this->path)) {
+ throw new \Exception(
+ 'Make sure all files in ' .
+ htmlspecialchars($this->path, ENT_QUOTES, 'UTF-8') .
+ 'are writeable!'
+ );
+ }
+ }
+
+ /**
+ * Returns an instance of this class
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return object $this
+ */
+ public static function getInstance($type, $init)
+ {
+ if (!self::$cachingInstance) {
+ self::$cachingInstance = new FileCache($type, $init);
+ }
+
+ return self::$cachingInstance;
+ }
+
+ /**
+ * Writes cache data into the file
+ *
+ * @param array $data the cache data
+ *
+ * @throws Exception if cache file couldn't be created
+ * @return object $this
+ */
+ public function setCache(array $data)
+ {
+ if (!is_writable(preg_replace('/[\/][^\/]+\.[^\/]++$/', null, $this->path))) {
+ throw new \Exception(
+ 'Temp directory ' .
+ htmlspecialchars($this->path, ENT_QUOTES, 'UTF-8') .
+ ' seems not writable'
+ );
+ }
+
+ if (!$this->isValidFile($this->path)) {
+ $handle = @fopen($this->path, 'w+');
+
+ if (!$handle) {
+ throw new \Exception("Cache file couldn't be created");
+ }
+
+ $serialized = @serialize($data);
+ if (!$serialized) {
+ throw new \Exception("Cache data couldn't be serialized");
+ }
+
+ fwrite($handle, $serialized);
+ fclose($handle);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the cached data
+ *
+ * Note that this method returns false if either type or file cache is
+ * not set
+ *
+ * @return mixed cache data or false
+ */
+ public function getCache()
+ {
+ // make sure filters are parsed again if cache expired
+ if (!$this->isValidFile($this->path)) {
+ return false;
+ }
+
+ $data = unserialize(file_get_contents($this->path));
+
+ return $data;
+ }
+
+ /**
+ * Returns true if the cache file is still valid
+ *
+ * @param string $file
+ * @return bool
+ */
+ private function isValidFile($file)
+ {
+ return file_exists($file) && time() - filectime($file) <= $this->config['expiration_time'];
+ }
+}
diff --git a/interface/lib/classes/IDS/Caching/MemcachedCache.php b/interface/lib/classes/IDS/Caching/MemcachedCache.php
new file mode 100644
index 0000000..b3dd5b7
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/MemcachedCache.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS\Caching;
+
+/**
+ * File caching wrapper
+ *
+ * This class inhabits functionality to get and set cache via memcached.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Groupoup
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class MemcachedCache implements CacheInterface
+{
+ /**
+ * Caching type
+ *
+ * @var string
+ */
+ private $type = null;
+
+ /**
+ * Cache configuration
+ *
+ * @var array
+ */
+ private $config = null;
+
+ /**
+ * Flag if the filter storage has been found in memcached
+ *
+ * @var boolean
+ */
+ private $isCached = false;
+
+ /**
+ * Memcache object
+ *
+ * @var object
+ */
+ private $memcache = null;
+
+ /**
+ * Holds an instance of this class
+ *
+ * @var object
+ */
+ private static $cachingInstance = null;
+
+ /**
+ * Constructor
+ *
+ * @param string $type caching type
+ * @param array $init the IDS_Init object
+ *
+ * @return void
+ */
+ public function __construct($type, $init)
+ {
+
+ $this->type = $type;
+ $this->config = $init->config['Caching'];
+
+ $this->connect();
+ }
+
+ /**
+ * Returns an instance of this class
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return object $this
+ */
+ public static function getInstance($type, $init)
+ {
+ if (!self::$cachingInstance) {
+ self::$cachingInstance = new MemcachedCache($type, $init);
+ }
+
+ return self::$cachingInstance;
+ }
+
+ /**
+ * Writes cache data
+ *
+ * @param array $data the caching data
+ *
+ * @return object $this
+ */
+ public function setCache(array $data)
+ {
+ if (!$this->isCached) {
+ $this->memcache->set(
+ $this->config['key_prefix'] . '.storage',
+ $data,
+ false,
+ $this->config['expiration_time']
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the cached data
+ *
+ * Note that this method returns false if either type or file cache is
+ * not set
+ *
+ * @return mixed cache data or false
+ */
+ public function getCache()
+ {
+ $data = $this->memcache->get(
+ $this->config['key_prefix'] .
+ '.storage'
+ );
+ $this->isCached = !empty($data);
+
+ return $data;
+ }
+
+ /**
+ * Connect to the memcached server
+ *
+ * @throws Exception if connection parameters are insufficient
+ * @return void
+ */
+ private function connect()
+ {
+
+ if ($this->config['host'] && $this->config['port']) {
+ // establish the memcache connection
+ $this->memcache = new \Memcache;
+ $this->memcache->pconnect(
+ $this->config['host'],
+ $this->config['port']
+ );
+
+ } else {
+ throw new \Exception('Insufficient connection parameters');
+ }
+ }
+}
diff --git a/interface/lib/classes/IDS/Caching/SessionCache.php b/interface/lib/classes/IDS/Caching/SessionCache.php
new file mode 100644
index 0000000..7168a63
--- /dev/null
+++ b/interface/lib/classes/IDS/Caching/SessionCache.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+
+namespace IDS\Caching;
+
+/**
+ * File caching wrapper
+ *
+ * This class inhabits functionality to get and set cache via session.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class SessionCache implements CacheInterface
+{
+ /**
+ * Caching type
+ *
+ * @var string
+ */
+ private $type = null;
+
+ /**
+ * Cache configuration
+ *
+ * @var array
+ */
+ private $config = null;
+
+ /**
+ * Holds an instance of this class
+ *
+ * @var object
+ */
+ private static $cachingInstance = null;
+
+ /**
+ * Constructor
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return void
+ */
+ public function __construct($type, $init)
+ {
+ $this->type = $type;
+ $this->config = $init->config['Caching'];
+ }
+
+ /**
+ * Returns an instance of this class
+ *
+ * @param string $type caching type
+ * @param object $init the IDS_Init object
+ *
+ * @return object $this
+ */
+ public static function getInstance($type, $init)
+ {
+
+ if (!self::$cachingInstance) {
+ self::$cachingInstance = new SessionCache($type, $init);
+ }
+
+ return self::$cachingInstance;
+ }
+
+ /**
+ * Writes cache data into the session
+ *
+ * @param array $data the caching data
+ *
+ * @return object $this
+ */
+ public function setCache(array $data)
+ {
+
+ $_SESSION['PHPIDS'][$this->type] = $data;
+
+ return $this;
+ }
+
+ /**
+ * Returns the cached data
+ *
+ * Note that this method returns false if either type or file cache is not set
+ *
+ * @return mixed cache data or false
+ */
+ public function getCache()
+ {
+
+ if ($this->type && $_SESSION['PHPIDS'][$this->type]) {
+ return $_SESSION['PHPIDS'][$this->type];
+ }
+
+ return false;
+ }
+}
diff --git a/interface/lib/classes/IDS/Config.ini.php b/interface/lib/classes/IDS/Config.ini.php
new file mode 100644
index 0000000..f87ccc8
--- /dev/null
+++ b/interface/lib/classes/IDS/Config.ini.php
@@ -0,0 +1,59 @@
+; <?php die(); ?>
+
+; PHPIDS Config.ini
+
+; General configuration settings
+
+[General]
+
+ ; basic settings - customize to make the PHPIDS work at all
+ filter_type = xml
+
+ base_path = /full/path/to/IDS/
+ use_base_path = false
+
+ filter_path = default_filter.xml
+ tmp_path = tmp
+ scan_keys = false
+
+ ; in case you want to use a different HTMLPurifier source, specify it here
+ ; By default, those files are used that are being shipped with PHPIDS
+ HTML_Purifier_Cache = vendors/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer
+
+ ; define which fields contain html and need preparation before
+ ; hitting the PHPIDS rules (new in PHPIDS 0.5)
+ ;html[] = POST.__wysiwyg
+
+ ; define which fields contain JSON data and should be treated as such
+ ; for fewer false positives (new in PHPIDS 0.5.3)
+ ;json[] = POST.__jsondata
+
+ ; define which fields shouldn't be monitored (a[b]=c should be referenced via a.b)
+ exceptions[] = GET.__utmz
+ exceptions[] = GET.__utmc
+ exceptions[] = POST.maildir_path
+
+ ; you can use regular expressions for wildcard exceptions - example: /.*foo/i
+
+[Caching]
+
+ ; caching: session|file|database|memcached|apc|none
+ caching = file
+ expiration_time = 600
+
+ ; file cache
+ path = tmp/default_filter.cache
+
+ ; database cache
+ wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
+ user = phpids_user
+ password = 123456
+ table = cache
+
+ ; memcached
+ ;host = localhost
+ ;port = 11211
+ ;key_prefix = PHPIDS
+
+ ; apc
+ ;key_prefix = PHPIDS
diff --git a/interface/lib/classes/IDS/Config/Config.ini.php b/interface/lib/classes/IDS/Config/Config.ini.php
new file mode 100644
index 0000000..0800552
--- /dev/null
+++ b/interface/lib/classes/IDS/Config/Config.ini.php
@@ -0,0 +1,91 @@
+; <?php die(); ?>
+
+; PHPIDS Config.ini
+
+; General configuration settings
+
+[General]
+
+ ; basic settings - customize to make the PHPIDS work at all
+ filter_type = xml
+
+ base_path = /full/path/to/IDS/
+ use_base_path = false
+
+ filter_path = default_filter.xml
+ tmp_path = tmp
+ scan_keys = false
+
+ ; in case you want to use a different HTMLPurifier source, specify it here
+ ; By default, those files are used that are being shipped with PHPIDS
+ HTML_Purifier_Cache = vendors/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer
+
+ ; define which fields contain html and need preparation before
+ ; hitting the PHPIDS rules (new in PHPIDS 0.5)
+ ;html[] = POST.__wysiwyg
+ ;html[] = POST.records
+ ;html[] = REQUEST.records
+
+ ; define which fields contain JSON data and should be treated as such
+ ; for fewer false positives (new in PHPIDS 0.5.3)
+ ;json[] = POST.__jsondata
+
+ ; define which fields shouldn't be monitored (a[b]=c should be referenced via a.b)
+ ; exceptions[] = GET.__utmz
+ ; exceptions[] = GET.__utmc
+ ; exceptions[] = POST.maildir_path
+ ; exceptions[] = REQUEST.maildir_path
+ ; exceptions[] = REQUEST.website_path
+ ; exceptions[] = REQUEST.website_symlinks
+ ; exceptions[] = REQUEST.vhost_conf_dir
+ ; exceptions[] = REQUEST.vhost_conf_enabled_dir
+ ; exceptions[] = REQUEST.nginx_vhost_conf_dir
+ ; exceptions[] = REQUEST.nginx_vhost_conf_enabled_dir
+ ; exceptions[] = REQUEST.php_open_basedir
+ ; exceptions[] = REQUEST.awstats_pl
+ ; exceptions[] = POST.website_path
+ ; exceptions[] = POST.website_symlinks
+ ; exceptions[] = POST.vhost_conf_dir
+ ; exceptions[] = POST.vhost_conf_enabled_dir
+ ; exceptions[] = POST.nginx_vhost_conf_dir
+ ; exceptions[] = POST.nginx_vhost_conf_enabled_dir
+ ; exceptions[] = POST.php_open_basedir
+ ; exceptions[] = POST.awstats_pl
+ ; exceptions[] = REQUEST.fastcgi_starter_path
+ ; exceptions[] = REQUEST.fastcgi_bin
+ ; exceptions[] = POST.fastcgi_starter_path
+ ; exceptions[] = POST.fastcgi_bin
+ ; exceptions[] = REQUEST.jailkit_chroot_home
+ ; exceptions[] = POST.jailkit_chroot_home
+ ; exceptions[] = REQUEST.phpmyadmin_url
+ ; exceptions[] = REQUEST.phpmyadmin_url
+ ; exceptions[] = REQUEST.records.weak_password_txt
+ ; exceptions[] = POST.records.weak_password_txt
+
+
+
+ ; you can use regular expressions for wildcard exceptions - example: /.*foo/i
+
+[Caching]
+
+ ; caching: session|file|database|memcached|apc|none
+ caching = file
+ expiration_time = 600
+
+ ; file cache
+ path = tmp/default_filter.cache
+
+ ; database cache
+ wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
+ user = phpids_user
+ password = 123456
+ table = cache
+
+ ; memcached
+ ;host = localhost
+ ;port = 11211
+ ;key_prefix = PHPIDS
+
+ ; apc
+ ;key_prefix = PHPIDS
+
diff --git a/interface/lib/classes/IDS/Converter.php b/interface/lib/classes/IDS/Converter.php
new file mode 100644
index 0000000..770d1cc
--- /dev/null
+++ b/interface/lib/classes/IDS/Converter.php
@@ -0,0 +1,779 @@
+<?php
+
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+
+/**
+ * PHPIDS specific utility class to convert charsets manually
+ *
+ * Note that if you make use of IDS_Converter::runAll(), existing class
+ * methods will be executed in the same order as they are implemented in the
+ * class tree!
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+
+namespace IDS;
+
+class Converter
+{
+ /**
+ * Runs all converter functions
+ *
+ * Note that if you make use of IDS_Converter::runAll(), existing class
+ * methods will be executed in the same order as they are implemented in the
+ * class tree!
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function runAll($value)
+ {
+ foreach (get_class_methods(__CLASS__) as $method) {
+ if (strpos($method, 'run') !== 0) {
+ $value = self::$method($value);
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Check for comments and erases them if available
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromCommented($value)
+ {
+ // check for existing comments
+ if (preg_match('/(?:\<!-|-->|\/\*|\*\/|\/\/\W*\w+\s*$)|(?:--[^-]*-)/ms', $value)) {
+
+ $pattern = array(
+ '/(?:(?:<!)(?:(?:--(?:[^-]*(?:-[^-]+)*)--\s*)*)(?:>))/ms',
+ '/(?:(?:\/\*\/*[^\/\*]*)+\*\/)/ms',
+ '/(?:--[^-]*-)/ms'
+ );
+
+ $converted = preg_replace($pattern, ';', $value);
+ $value .= "\n" . $converted;
+ }
+
+ //make sure inline comments are detected and converted correctly
+ $value = preg_replace('/(<\w+)\/+(\w+=?)/m', '$1/$2', $value);
+ $value = preg_replace('/[^\\\:]\/\/(.*)$/m', '/**/$1', $value);
+ $value = preg_replace('/([^\-&])#.*[\r\n\v\f]/m', '$1', $value);
+ $value = preg_replace('/([^&\-])#.*\n/m', '$1 ', $value);
+ $value = preg_replace('/^#.*\n/m', ' ', $value);
+
+ return $value;
+ }
+
+ /**
+ * Strip newlines
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromWhiteSpace($value)
+ {
+ //check for inline linebreaks
+ $search = array('\r', '\n', '\f', '\t', '\v');
+ $value = str_replace($search, ';', $value);
+
+ // replace replacement characters regular spaces
+ $value = str_replace('�', ' ', $value);
+
+ //convert real linebreaks
+ return preg_replace('/(?:\n|\r|\v)/m', ' ', $value);
+ }
+
+ /**
+ * Checks for common charcode pattern and decodes them
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromJSCharcode($value)
+ {
+ $matches = array();
+
+ // check if value matches typical charCode pattern
+ if (preg_match_all('/(?:[\d+-=\/\* ]+(?:\s?,\s?[\d+-=\/\* ]+)){4,}/ms', $value, $matches)) {
+ $converted = '';
+ $string = implode(',', $matches[0]);
+ $string = preg_replace('/\s/', '', $string);
+ $string = preg_replace('/\w+=/', '', $string);
+ $charcode = explode(',', $string);
+
+ foreach ($charcode as $char) {
+ $char = preg_replace('/\W0/s', '', $char);
+
+ if (preg_match_all('/\d*[+-\/\* ]\d+/', $char, $matches)) {
+ $match = preg_split('/(\W?\d+)/', implode('', $matches[0]), null, PREG_SPLIT_DELIM_CAPTURE);
+
+ if (array_sum($match) >= 20 && array_sum($match) <= 127) {
+ $converted .= chr(array_sum($match));
+ }
+
+ } elseif (!empty($char) && $char >= 20 && $char <= 127) {
+ $converted .= chr($char);
+ }
+ }
+
+ $value .= "\n" . $converted;
+ }
+
+ // check for octal charcode pattern
+ if (preg_match_all('/(?:(?:[\\\]+\d+[ \t]*){8,})/ims', $value, $matches)) {
+ $converted = '';
+ $charcode = explode('\\', preg_replace('/\s/', '', implode(',', $matches[0])));
+
+ foreach (array_map('octdec', array_filter($charcode)) as $char) {
+ if (20 <= $char && $char <= 127) {
+ $converted .= chr($char);
+ }
+ }
+ $value .= "\n" . $converted;
+ }
+
+ // check for hexadecimal charcode pattern
+ if (preg_match_all('/(?:(?:[\\\]+\w+\s*){8,})/ims', $value, $matches)) {
+ $converted = '';
+ $charcode = explode('\\', preg_replace('/[ux]/', '', implode(',', $matches[0])));
+
+ foreach (array_map('hexdec', array_filter($charcode)) as $char) {
+ if (20 <= $char && $char <= 127) {
+ $converted .= chr($char);
+ }
+ }
+ $value .= "\n" . $converted;
+ }
+
+ return $value;
+ }
+
+ /**
+ * Eliminate JS regex modifiers
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertJSRegexModifiers($value)
+ {
+ return preg_replace('/\/[gim]+/', '/', $value);
+ }
+
+ /**
+ * Converts from hex/dec entities
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertEntities($value)
+ {
+ $converted = null;
+
+ //deal with double encoded payload
+ $value = preg_replace('/&/', '&', $value);
+
+ if (preg_match('/&#x?[\w]+/ms', $value)) {
+ $converted = preg_replace('/(&#x?[\w]{2}\d?);?/ms', '$1;', $value);
+ $converted = html_entity_decode($converted, ENT_QUOTES, 'UTF-8');
+ $value .= "\n" . str_replace(';;', ';', $converted);
+ }
+
+ // normalize obfuscated protocol handlers
+ $value = preg_replace(
+ '/(?:j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t\s*:)|(d\s*a\s*t\s*a\s*:)/ms',
+ 'javascript:',
+ $value
+ );
+
+ return $value;
+ }
+
+ /**
+ * Normalize quotes
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertQuotes($value)
+ {
+ // normalize different quotes to "
+ $pattern = array('\'', '`', '´', '’', '‘');
+ $value = str_replace($pattern, '"', $value);
+
+ //make sure harmless quoted strings don't generate false alerts
+ $value = preg_replace('/^"([^"=\\!><~]+)"$/', '$1', $value);
+
+ return $value;
+ }
+
+ /**
+ * Converts SQLHEX to plain text
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromSQLHex($value)
+ {
+ $matches = array();
+ if (preg_match_all('/(?:(?:\A|[^\d])0x[a-f\d]{3,}[a-f\d]*)+/im', $value, $matches)) {
+ foreach ($matches[0] as $match) {
+ $converted = '';
+ foreach (str_split($match, 2) as $hex_index) {
+ if (preg_match('/[a-f\d]{2,3}/i', $hex_index)) {
+ $converted .= chr(hexdec($hex_index));
+ }
+ }
+ $value = str_replace($match, $converted, $value);
+ }
+ }
+ // take care of hex encoded ctrl chars
+ $value = preg_replace('/0x\d+/m', ' 1 ', $value);
+
+ return $value;
+ }
+
+ /**
+ * Converts basic SQL keywords and obfuscations
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromSQLKeywords($value)
+ {
+ $pattern = array(
+ '/(?:is\s+null)|(like\s+null)|' .
+ '(?:(?:^|\W)in[+\s]*\([\s\d"]+[^()]*\))/ims'
+ );
+ $value = preg_replace($pattern, '"=0', $value);
+
+ $value = preg_replace('/[^\w\)]+\s*like\s*[^\w\s]+/ims', '1" OR "1"', $value);
+ $value = preg_replace('/null([,"\s])/ims', '0$1', $value);
+ $value = preg_replace('/\d+\./ims', ' 1', $value);
+ $value = preg_replace('/,null/ims', ',0', $value);
+ $value = preg_replace('/(?:between)/ims', 'or', $value);
+ $value = preg_replace('/(?:and\s+\d+\.?\d*)/ims', '', $value);
+ $value = preg_replace('/(?:\s+and\s+)/ims', ' or ', $value);
+
+ $pattern = array(
+ '/(?:not\s+between)|(?:is\s+not)|(?:not\s+in)|' .
+ '(?:xor|<>|rlike(?:\s+binary)?)|' .
+ '(?:regexp\s+binary)|' .
+ '(?:sounds\s+like)/ims'
+ );
+ $value = preg_replace($pattern, '!', $value);
+ $value = preg_replace('/"\s+\d/', '"', $value);
+ $value = preg_replace('/(\W)div(\W)/ims', '$1 OR $2', $value);
+ $value = preg_replace('/\/(?:\d+|null)/', null, $value);
+
+ return $value;
+ }
+
+ /**
+ * Detects nullbytes and controls chars via ord()
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromControlChars($value)
+ {
+ // critical ctrl values
+ $search = array(
+ chr(0), chr(1), chr(2), chr(3), chr(4), chr(5),
+ chr(6), chr(7), chr(8), chr(11), chr(12), chr(14),
+ chr(15), chr(16), chr(17), chr(18), chr(19), chr(24),
+ chr(25), chr(192), chr(193), chr(238), chr(255), '\\0'
+ );
+
+ $value = str_replace($search, '%00', $value);
+
+ //take care for malicious unicode characters
+ $value = urldecode(
+ preg_replace(
+ '/(?:%E(?:2|3)%8(?:0|1)%(?:A|8|9)\w|%EF%BB%BF|%EF%BF%BD)|(?:&#(?:65|8)\d{3};?)/i',
+ null,
+ urlencode($value)
+ )
+ );
+ $value = urlencode($value);
+ $value = preg_replace('/(?:%F0%80%BE)/i', '>', $value);
+ $value = preg_replace('/(?:%F0%80%BC)/i', '<', $value);
+ $value = preg_replace('/(?:%F0%80%A2)/i', '"', $value);
+ $value = preg_replace('/(?:%F0%80%A7)/i', '\'', $value);
+ $value = urldecode($value);
+
+ $value = preg_replace('/(?:%ff1c)/', '<', $value);
+ $value = preg_replace('/(?:&[#x]*(200|820|200|820|zwn?j|lrm|rlm)\w?;?)/i', null, $value);
+ $value = preg_replace(
+ '/(?:&#(?:65|8)\d{3};?)|' .
+ '(?:&#(?:56|7)3\d{2};?)|' .
+ '(?:&#x(?:fe|20)\w{2};?)|' .
+ '(?:&#x(?:d[c-f])\w{2};?)/i',
+ null,
+ $value
+ );
+
+ $value = str_replace(
+ array(
+ '«',
+ '〈',
+ '<',
+ '‹',
+ '〈',
+ '⟨'
+ ),
+ '<',
+ $value
+ );
+ $value = str_replace(
+ array(
+ '»',
+ '〉',
+ '>',
+ '›',
+ '〉',
+ '⟩'
+ ),
+ '>',
+ $value
+ );
+
+ return $value;
+ }
+
+ /**
+ * This method matches and translates base64 strings and fragments
+ * used in data URIs
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromNestedBase64($value)
+ {
+ $matches = array();
+ preg_match_all('/(?:^|[,&?])\s*([a-z0-9]{50,}=*)(?:\W|$)/im', $value, $matches);
+
+ foreach ($matches[1] as $item) {
+ if (isset($item) && !preg_match('/[a-f0-9]{32}/i', $item)) {
+ $base64_item = base64_decode($item);
+ $value = str_replace($item, $base64_item, $value);
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Detects nullbytes and controls chars via ord()
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromOutOfRangeChars($value)
+ {
+ $values = str_split($value);
+ foreach ($values as $item) {
+ if (ord($item) >= 127) {
+ $value = str_replace($item, ' ', $value);
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Strip XML patterns
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromXML($value)
+ {
+ $converted = strip_tags($value);
+ if (!$converted || $converted === $value) {
+ return $value;
+ } else {
+ return $value . "\n" . $converted;
+ }
+ }
+
+ /**
+ * This method converts JS unicode code points to
+ * regular characters
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromJSUnicode($value)
+ {
+ $matches = array();
+ preg_match_all('/\\\u[0-9a-f]{4}/ims', $value, $matches);
+
+ if (!empty($matches[0])) {
+ foreach ($matches[0] as $match) {
+ $chr = chr(hexdec(substr($match, 2, 4)));
+ $value = str_replace($match, $chr, $value);
+ }
+ $value .= "\n\u0001";
+ }
+
+ return $value;
+ }
+
+ /**
+ * Converts relevant UTF-7 tags to UTF-8
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromUTF7($value)
+ {
+ if (preg_match('/\+A\w+-?/m', $value)) {
+ if (function_exists('mb_convert_encoding')) {
+ if (version_compare(PHP_VERSION, '5.2.8', '<')) {
+ $tmp_chars = str_split($value);
+ $value = '';
+ foreach ($tmp_chars as $char) {
+ if (ord($char) <= 127) {
+ $value .= $char;
+ }
+ }
+ }
+ $value .= "\n" . mb_convert_encoding($value, 'UTF-8', 'UTF-7');
+ } else {
+ //list of all critical UTF7 codepoints
+ $schemes = array(
+ '+ACI-' => '"',
+ '+ADw-' => '<',
+ '+AD4-' => '>',
+ '+AFs-' => '[',
+ '+AF0-' => ']',
+ '+AHs-' => '{',
+ '+AH0-' => '}',
+ '+AFw-' => '\\',
+ '+ADs-' => ';',
+ '+ACM-' => '#',
+ '+ACY-' => '&',
+ '+ACU-' => '%',
+ '+ACQ-' => '$',
+ '+AD0-' => '=',
+ '+AGA-' => '`',
+ '+ALQ-' => '"',
+ '+IBg-' => '"',
+ '+IBk-' => '"',
+ '+AHw-' => '|',
+ '+ACo-' => '*',
+ '+AF4-' => '^',
+ '+ACIAPg-' => '">',
+ '+ACIAPgA8-' => '">'
+ );
+
+ $value = str_ireplace(
+ array_keys($schemes),
+ array_values($schemes),
+ $value
+ );
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Converts basic concatenations
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromConcatenated($value)
+ {
+ //normalize remaining backslashes
+ if ($value != preg_replace('/(\w)\\\/', "$1", $value)) {
+ $value .= preg_replace('/(\w)\\\/', "$1", $value);
+ }
+
+ $compare = stripslashes($value);
+
+ $pattern = array(
+ '/(?:<\/\w+>\+<\w+>)/s',
+ '/(?:":\d+[^"[]+")/s',
+ '/(?:"?"\+\w+\+")/s',
+ '/(?:"\s*;[^"]+")|(?:";[^"]+:\s*")/s',
+ '/(?:"\s*(?:;|\+).{8,18}:\s*")/s',
+ '/(?:";\w+=)|(?:!""&&")|(?:~)/s',
+ '/(?:"?"\+""?\+?"?)|(?:;\w+=")|(?:"[|&]{2,})/s',
+ '/(?:"\s*\W+")/s',
+ '/(?:";\w\s*\+=\s*\w?\s*")/s',
+ '/(?:"[|&;]+\s*[^|&\n]*[|&]+\s*"?)/s',
+ '/(?:";\s*\w+\W+\w*\s*[|&]*")/s',
+ '/(?:"\s*"\s*\.)/s',
+ '/(?:\s*new\s+\w+\s*[+",])/',
+ '/(?:(?:^|\s+)(?:do|else)\s+)/',
+ '/(?:[{(]\s*new\s+\w+\s*[)}])/',
+ '/(?:(this|self)\.)/',
+ '/(?:undefined)/',
+ '/(?:in\s+)/'
+ );
+
+ // strip out concatenations
+ $converted = preg_replace($pattern, null, $compare);
+
+ //strip object traversal
+ $converted = preg_replace('/\w(\.\w\()/', "$1", $converted);
+
+ // normalize obfuscated method calls
+ $converted = preg_replace('/\)\s*\+/', ")", $converted);
+
+ //convert JS special numbers
+ $converted = preg_replace(
+ '/(?:\(*[.\d]e[+-]*[^a-z\W]+\)*)|(?:NaN|Infinity)\W/ims',
+ 1,
+ $converted
+ );
+
+ if ($converted && ($compare != $converted)) {
+ $value .= "\n" . $converted;
+ }
+
+ return $value;
+ }
+
+ /**
+ * This method collects and decodes proprietary encoding types
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromProprietaryEncodings($value)
+ {
+ //Xajax error reportings
+ $value = preg_replace('/<!\[CDATA\[(\W+)\]\]>/im', '$1', $value);
+
+ //strip false alert triggering apostrophes
+ $value = preg_replace('/(\w)\"(s)/m', '$1$2', $value);
+
+ //strip quotes within typical search patterns
+ $value = preg_replace('/^"([^"=\\!><~]+)"$/', '$1', $value);
+
+ //OpenID login tokens
+ $value = preg_replace('/{[\w-]{8,9}\}(?:\{[\w=]{8}\}){2}/', null, $value);
+
+ //convert Content and \sdo\s to null
+ $value = preg_replace('/Content|\Wdo\s/', null, $value);
+
+ //strip emoticons
+ $value = preg_replace(
+ '/(?:\s[:;]-[)\/PD]+)|(?:\s;[)PD]+)|(?:\s:[)PD]+)|-\.-|\^\^/m',
+ null,
+ $value
+ );
+
+ //normalize separation char repetion
+ $value = preg_replace('/([.+~=*_\-;])\1{2,}/m', '$1', $value);
+
+ //normalize multiple single quotes
+ $value = preg_replace('/"{2,}/m', '"', $value);
+
+ //normalize quoted numerical values and asterisks
+ $value = preg_replace('/"(\d+)"/m', '$1', $value);
+
+ //normalize pipe separated request parameters
+ $value = preg_replace('/\|(\w+=\w+)/m', '&$1', $value);
+
+ //normalize ampersand listings
+ $value = preg_replace('/(\w\s)&\s(\w)/', '$1$2', $value);
+
+ //normalize escaped RegExp modifiers
+ $value = preg_replace('/\/\\\(\w)/', '/$1', $value);
+
+ return $value;
+ }
+
+ /**
+ * This method removes encoded sql # comments
+ *
+ * @param string $value the value to convert
+ *
+ * @static
+ * @return string
+ */
+ public static function convertFromUrlencodeSqlComment($value)
+ {
+ if (preg_match_all('/(?:\%23.*?\%0a)/im',$value,$matches)){
+ $converted = $value;
+ foreach($matches[0] as $match){
+ $converted = str_replace($match,' ',$converted);
+ }
+ $value .= "\n" . $converted;
+ }
+ return $value;
+ }
+
+ /**
+ * This method is the centrifuge prototype
+ *
+ * @param string $value the value to convert
+ * @param Monitor $monitor the monitor object
+ *
+ * @static
+ * @return string
+ */
+ public static function runCentrifuge($value, Monitor $monitor = null)
+ {
+ $threshold = 3.49;
+ if (strlen($value) > 25) {
+ //strip padding
+ $tmp_value = preg_replace('/\s{4}|==$/m', null, $value);
+ $tmp_value = preg_replace(
+ '/\s{4}|[\p{L}\d\+\-=,.%()]{8,}/m',
+ 'aaa',
+ $tmp_value
+ );
+
+ // Check for the attack char ratio
+ $tmp_value = preg_replace('/([*.!?+-])\1{1,}/m', '$1', $tmp_value);
+ $tmp_value = preg_replace('/"[\p{L}\d\s]+"/m', null, $tmp_value);
+
+ $stripped_length = strlen(
+ preg_replace(
+ '/[\d\s\p{L}\.:,%&\/><\-)!|]+/m',
+ null,
+ $tmp_value
+ )
+ );
+ $overall_length = strlen(
+ preg_replace(
+ '/([\d\s\p{L}:,\.]{3,})+/m',
+ 'aaa',
+ preg_replace('/\s{2,}/m', null, $tmp_value)
+ )
+ );
+
+ if ($stripped_length != 0 && $overall_length/$stripped_length <= $threshold) {
+ $monitor->centrifuge['ratio'] = $overall_length / $stripped_length;
+ $monitor->centrifuge['threshold'] =$threshold;
+
+ $value .= "\n$[!!!]";
+ }
+ }
+
+ if (strlen($value) > 40) {
+ // Replace all non-special chars
+ $converted = preg_replace('/[\w\s\p{L},.:!]/', null, $value);
+
+ // Split string into an array, unify and sort
+ $array = str_split($converted);
+ $array = array_unique($array);
+ asort($array);
+
+ // Normalize certain tokens
+ $schemes = array(
+ '~' => '+',
+ '^' => '+',
+ '|' => '+',
+ '*' => '+',
+ '%' => '+',
+ '&' => '+',
+ '/' => '+'
+ );
+
+ $converted = implode($array);
+
+ $_keys = array_keys($schemes);
+ $_values = array_values($schemes);
+
+ $converted = str_replace($_keys, $_values, $converted);
+
+ $converted = preg_replace('/[+-]\s*\d+/', '+', $converted);
+ $converted = preg_replace('/[()[\]{}]/', '(', $converted);
+ $converted = preg_replace('/[!?:=]/', ':', $converted);
+ $converted = preg_replace('/[^:(+]/', null, stripslashes($converted));
+
+ // Sort again and implode
+ $array = str_split($converted);
+ asort($array);
+ $converted = implode($array);
+
+ if (preg_match('/(?:\({2,}\+{2,}:{2,})|(?:\({2,}\+{2,}:+)|(?:\({3,}\++:{2,})/', $converted)) {
+ $monitor->centrifuge['converted'] = $converted;
+
+ return $value . "\n" . $converted;
+ }
+ }
+
+ return $value;
+ }
+}
diff --git a/interface/lib/classes/IDS/Event.php b/interface/lib/classes/IDS/Event.php
new file mode 100644
index 0000000..ebda171
--- /dev/null
+++ b/interface/lib/classes/IDS/Event.php
@@ -0,0 +1,221 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS;
+
+/**
+ * PHPIDS event object
+ *
+ * This class represents a certain event that occured while applying the filters
+ * to the supplied data. It aggregates a bunch of IDS_Filter implementations and
+ * is a assembled in IDS_Report.
+ *
+ * Note that this class implements both Countable and IteratorAggregate
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+class Event implements \Countable, \IteratorAggregate
+{
+ /**
+ * Event name
+ *
+ * @var string
+ */
+ protected $name = null;
+
+ /**
+ * Value of the event
+ *
+ * @var mixed
+ */
+ protected $value = null;
+
+ /**
+ * List of filter objects
+ *
+ * Filter objects in this array are those that matched the events value
+ *
+ * @var Filter[]|array
+ */
+ protected $filters = array();
+
+ /**
+ * Calculated impact
+ *
+ * Total impact of the event
+ *
+ * @var integer
+ */
+ protected $impact = 0;
+
+ /**
+ * Affecte tags
+ *
+ * @var string[]|array
+ */
+ protected $tags = array();
+
+ /**
+ * Constructor
+ *
+ * Fills event properties
+ *
+ * @param string $name the event name
+ * @param mixed $value the event value
+ * @param Filter[]|array $filters the corresponding filters
+ *
+ * @throws \InvalidArgumentException
+ * @return \IDS\Event
+ */
+ public function __construct($name, $value, array $filters)
+ {
+ if (!is_scalar($name)) {
+ throw new \InvalidArgumentException(
+ 'Expected $name to be a scalar,' . gettype($name) . ' given'
+ );
+ }
+
+ if (!is_scalar($value)) {
+ throw new \InvalidArgumentException(
+ 'Expected $value to be a scalar,' . gettype($value) . ' given'
+ );
+ }
+
+ $this->name = $name;
+ $this->value = $value;
+
+ foreach ($filters as $filter) {
+ if (!$filter instanceof Filter) {
+ throw new \InvalidArgumentException(
+ 'Filter must be derived from IDS_Filter'
+ );
+ }
+
+ $this->filters[] = $filter;
+ }
+ }
+
+ /**
+ * Returns event name
+ *
+ * The name of the event usually is the key of the variable that was
+ * considered to be malicious
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Returns event value
+ *
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Returns calculated impact
+ *
+ * @return integer
+ */
+ public function getImpact()
+ {
+ if (!$this->impact) {
+ $this->impact = 0;
+ foreach ($this->filters as $filter) {
+ $this->impact += $filter->getImpact();
+ }
+ }
+
+ return $this->impact;
+ }
+
+ /**
+ * Returns affected tags
+ *
+ * @return string[]|array
+ */
+ public function getTags()
+ {
+ foreach ($this->getFilters() as $filter) {
+ $this->tags = array_merge($this->tags, $filter->getTags());
+ }
+
+ return $this->tags = array_values(array_unique($this->tags));
+ }
+
+ /**
+ * Returns list of filter objects
+ *
+ * @return Filter[]|array
+ */
+ public function getFilters()
+ {
+ return $this->filters;
+ }
+
+ /**
+ * Returns number of filters
+ *
+ * To implement interface Countable this returns the number of filters
+ * appended.
+ *
+ * @return integer
+ */
+ public function count()
+ {
+ return count($this->getFilters());
+ }
+
+ /**
+ * IteratorAggregate iterator getter
+ *
+ * Returns an iterator to iterate over the appended filters.
+ *
+ * @return \Iterator the filter collection
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->getFilters());
+ }
+}
diff --git a/interface/lib/classes/IDS/Filter.php b/interface/lib/classes/IDS/Filter.php
new file mode 100644
index 0000000..573988f
--- /dev/null
+++ b/interface/lib/classes/IDS/Filter.php
@@ -0,0 +1,175 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS;
+
+/**
+ * PHPIDS Filter object
+ *
+ * Each object of this class serves as a container for a specific filter. The
+ * object provides methods to get information about this particular filter and
+ * also to match an arbitrary string against it.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class Filter
+{
+ /**
+ * Filter rule
+ *
+ * @var string
+ */
+ protected $rule;
+
+ /**
+ * List of tags of the filter
+ *
+ * @var string[]|array
+ */
+ protected $tags = array();
+
+ /**
+ * Filter impact level
+ *
+ * @var integer
+ */
+ protected $impact = 0;
+
+ /**
+ * Filter description
+ *
+ * @var string
+ */
+ protected $description = '';
+
+ /**
+ * Constructor
+ *
+ * @param integer $id filter id
+ * @param string $rule filter rule
+ * @param string $description filter description
+ * @param string[]|array $tags list of tags
+ * @param integer $impact filter impact level
+ *
+ * @return \IDS\Filter
+ */
+ public function __construct($id, $rule, $description, array $tags, $impact)
+ {
+ $this->id = $id;
+ $this->rule = $rule;
+ $this->tags = $tags;
+ $this->impact = $impact;
+ $this->description = $description;
+ }
+
+ /**
+ * Matches a string against current filter
+ *
+ * Matches given string against the filter rule the specific object of this
+ * class represents
+ *
+ * @param string $input the string input to match
+ *
+ * @throws \InvalidArgumentException if argument is no string
+ * @return boolean
+ */
+ public function match($input)
+ {
+ if (!is_string($input)) {
+ throw new \InvalidArgumentException(
+ 'Invalid argument. Expected a string, received ' . gettype($input)
+ );
+ }
+
+ return (bool) preg_match('/' . $this->getRule() . '/ms', strtolower($input));
+ }
+
+ /**
+ * Returns filter description
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Return list of affected tags
+ *
+ * Each filter rule is concerned with a certain kind of attack vectors.
+ * This method returns those affected kinds.
+ *
+ * @return string[]|array
+ */
+ public function getTags()
+ {
+ return $this->tags;
+ }
+
+ /**
+ * Returns filter rule
+ *
+ * @return string
+ */
+ public function getRule()
+ {
+ return $this->rule;
+ }
+
+ /**
+ * Get filter impact level
+ *
+ * @return integer
+ */
+ public function getImpact()
+ {
+ return $this->impact;
+ }
+
+ /**
+ * Get filter ID
+ *
+ * @return integer
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+}
diff --git a/interface/lib/classes/IDS/Filter/Storage.php b/interface/lib/classes/IDS/Filter/Storage.php
new file mode 100644
index 0000000..f17549b
--- /dev/null
+++ b/interface/lib/classes/IDS/Filter/Storage.php
@@ -0,0 +1,401 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS\Filter;
+
+use IDS\Init;
+use IDS\Caching\CacheFactory;
+
+/**
+ * Filter Storage
+ *
+ * This class provides various default functions for gathering filter patterns
+ * to be used later on by the detection mechanism. You might extend this class
+ * to your requirements.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+class Storage
+{
+ /**
+ * Filter source file
+ *
+ * @var string
+ */
+ protected $source = null;
+
+ /**
+ * Holds caching settings
+ *
+ * @var array
+ */
+ protected $cacheSettings = null;
+
+ /**
+ * Cache container
+ *
+ * @var object IDS_Caching wrapper
+ */
+ protected $cache = null;
+
+ /**
+ * Filter container
+ *
+ * @var array
+ */
+ protected $filterSet = array();
+
+ /**
+ * Constructor
+ *
+ * Loads filters based on provided IDS_Init settings.
+ *
+ * @param object $init IDS_Init instance
+ *
+ * @throws \InvalidArgumentException if unsupported filter type is given
+ * @return void
+ */
+ final public function __construct(Init $init)
+ {
+ if ($init->config) {
+
+ $caching = isset($init->config['Caching']['caching']) ? $init->config['Caching']['caching'] : 'none';
+
+ $type = $init->config['General']['filter_type'];
+ $this->source = $init->getBasePath(). $init->config['General']['filter_path'];
+
+ if ($caching && $caching !== 'none') {
+ $this->cacheSettings = $init->config['Caching'];
+ $this->cache = CacheFactory::factory($init, 'storage');
+ }
+
+ switch ($type) {
+ case 'xml':
+ return $this->getFilterFromXML();
+ case 'json':
+ return $this->getFilterFromJson();
+ default:
+ throw new \InvalidArgumentException('Unsupported filter type.');
+ }
+ }
+ }
+
+ /**
+ * Sets the filter array
+ *
+ * @param array $filterSet array containing multiple IDS_Filter instances
+ *
+ * @return object $this
+ */
+ final public function setFilterSet($filterSet)
+ {
+ foreach ($filterSet as $filter) {
+ $this->addFilter($filter);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns registered filters
+ *
+ * @return array
+ */
+ final public function getFilterSet()
+ {
+ return $this->filterSet;
+ }
+
+ /**
+ * Adds a filter
+ *
+ * @param object $filter IDS_Filter instance
+ *
+ * @return object $this
+ */
+ final public function addFilter(\IDS\Filter $filter)
+ {
+ $this->filterSet[] = $filter;
+
+ return $this;
+ }
+
+ /**
+ * Checks if any filters are cached
+ *
+ * @return mixed $filters cached filters or false
+ */
+ private function isCached()
+ {
+ $filters = false;
+
+ if ($this->cacheSettings) {
+ if ($this->cache) {
+ $filters = $this->cache->getCache();
+ }
+ }
+
+ return $filters;
+ }
+
+ /**
+ * Loads filters from XML using SimpleXML
+ *
+ * This function parses the provided source file and stores the result.
+ * If caching mode is enabled the result will be cached to increase
+ * the performance.
+ *
+ * @throws \InvalidArgumentException if source file doesn't exist
+ * @throws \RuntimeException if problems with fetching the XML data occur
+ * @return object $this
+ */
+ public function getFilterFromXML()
+ {
+ if (extension_loaded('SimpleXML')) {
+
+ /*
+ * See if filters are already available in the cache
+ */
+ $filters = $this->isCached();
+
+ /*
+ * If they aren't, parse the source file
+ */
+ if (!$filters) {
+
+ if (!file_exists($this->source)) {
+ throw new \InvalidArgumentException(
+ sprintf('Invalid config: %s doesn\'t exist.', $this->source)
+ );
+ }
+
+ if (LIBXML_VERSION >= 20621) {
+ $filters = simplexml_load_file($this->source, null, LIBXML_COMPACT);
+ } else {
+ $filters = simplexml_load_file($this->source);
+ }
+ }
+
+ /*
+ * In case we still don't have any filters loaded and exception
+ * will be thrown
+ */
+ if (empty($filters)) {
+ throw new \RuntimeException(
+ 'XML data could not be loaded.' .
+ ' Make sure you specified the correct path.'
+ );
+ }
+
+ /*
+ * Now the storage will be filled with IDS_Filter objects
+ */
+ $nocache = $filters instanceof \SimpleXMLElement;
+
+ if ($nocache)
+ {
+ // build filters and cache them for re-use on next run
+ $data = array();
+ $filters = $filters->filter;
+
+ foreach ($filters as $filter) {
+ $id = (string) $filter->id;
+ $rule = (string) $filter->rule;
+ $impact = (string) $filter->impact;
+ $tags = array_values((array) $filter->tags);
+ $description = (string) $filter->description;
+
+ $this->addFilter(
+ new \IDS\Filter(
+ $id,
+ $rule,
+ $description,
+ (array) $tags[0],
+ (int) $impact
+ )
+ );
+
+ $data[] = array(
+ 'id' => $id,
+ 'rule' => $rule,
+ 'impact' => $impact,
+ 'tags' => $tags,
+ 'description' => $description
+ );
+ }
+
+ /*
+ * If caching is enabled, the fetched data will be cached
+ */
+ if ($this->cacheSettings) {
+ $this->cache->setCache($data);
+ }
+
+ } else {
+
+ // build filters from cached content
+ $this->addFiltersFromArray($filters);
+ }
+
+ return $this;
+ }
+
+ throw new \RuntimeException('SimpleXML is not loaded.');
+ }
+
+ /**
+ * Loads filters from Json file using ext/Json
+ *
+ * This function parses the provided source file and stores the result.
+ * If caching mode is enabled the result will be cached to increase
+ * the performance.
+ *
+ * @throws \RuntimeException if problems with fetching the JSON data occur
+ * @return object $this
+ */
+ public function getFilterFromJson()
+ {
+
+ if (extension_loaded('Json')) {
+
+ /*
+ * See if filters are already available in the cache
+ */
+ $filters = $this->isCached();
+
+ /*
+ * If they aren't, parse the source file
+ */
+ if (!$filters) {
+ if (!file_exists($this->source)) {
+ throw new \InvalidArgumentException(
+ sprintf('Invalid config: %s doesn\'t exist.', $this->source)
+ );
+ }
+ $filters = json_decode(file_get_contents($this->source));
+ }
+
+ if (!$filters) {
+ throw new \RuntimeException('JSON data could not be loaded. Make sure you specified the correct path.');
+ }
+
+ /*
+ * Now the storage will be filled with IDS_Filter objects
+ */
+ $nocache = !is_array($filters);
+
+ if ($nocache) {
+
+ // build filters and cache them for re-use on next run
+ $data = array();
+ $filters = $filters->filters->filter;
+
+ foreach ($filters as $filter) {
+
+ $id = (string) $filter->id;
+ $rule = (string) $filter->rule;
+ $impact = (string) $filter->impact;
+ $tags = array_values((array) $filter->tags);
+ $description = (string) $filter->description;
+
+ $this->addFilter(
+ new \IDS\Filter(
+ $id,
+ $rule,
+ $description,
+ (array) $tags[0],
+ (int) $impact
+ )
+ );
+
+ $data[] = array(
+ 'id' => $id,
+ 'rule' => $rule,
+ 'impact' => $impact,
+ 'tags' => $tags,
+ 'description' => $description
+ );
+ }
+
+ /*
+ * If caching is enabled, the fetched data will be cached
+ */
+ if ($this->cacheSettings) {
+ $this->cache->setCache($data);
+ }
+
+ } else {
+
+ // build filters from cached content
+ $this->addFiltersFromArray($filters);
+ }
+
+ return $this;
+ }
+
+ throw new \RuntimeException('json extension is not loaded.');
+ }
+
+ /**
+ * This functions adds an array of filters to the IDS_Storage object.
+ * Each entry within the array is expected to be an simple array containing all parts of the filter.
+ *
+ * @param array $filters
+ */
+ private function addFiltersFromArray(array $filters)
+ {
+ foreach ($filters as $filter) {
+
+ $id = $filter['id'];
+ $rule = $filter['rule'];
+ $impact = $filter['impact'];
+ $tags = $filter['tags'];
+ $description = $filter['description'];
+
+ $this->addFilter(
+ new \IDS\Filter(
+ $id,
+ $rule,
+ $description,
+ (array) $tags[0],
+ (int) $impact
+ )
+ );
+ }
+ }
+}
diff --git a/interface/lib/classes/IDS/Init.php b/interface/lib/classes/IDS/Init.php
new file mode 100644
index 0000000..1b6269a
--- /dev/null
+++ b/interface/lib/classes/IDS/Init.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS;
+
+/**
+ * Framework initiation
+ *
+ * This class is used for the purpose to initiate the framework and inhabits
+ * functionality to parse the needed configuration file.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Groupup
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ * @since Version 0.4
+ */
+class Init
+{
+ /**
+ * Holds config settings
+ *
+ * @var array
+ */
+ public $config = array();
+
+ /**
+ * Instance of this class depending on the supplied config file
+ *
+ * @var Init[]|array
+ * @static
+ */
+ private static $instances = array();
+
+ /**
+ * Constructor
+ *
+ * Includes needed classes and parses the configuration file
+ *
+ * @param array $config
+ *
+ * @return \IDS\Init $this
+ */
+ public function __construct(array $config = array())
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * Returns an instance of this class. Also a PHP version check
+ * is being performed to avoid compatibility problems with PHP < 5.1.6
+ *
+ * @param string|null $configPath the path to the config file
+ *
+ * @throws \InvalidArgumentException
+ * @return self
+ */
+ public static function init($configPath = null)
+ {
+ if (!$configPath) {
+ return new self();
+ }
+ if (!isset(self::$instances[$configPath])) {
+ if (!file_exists($configPath) || !is_readable($configPath)) {
+ throw new \InvalidArgumentException("Invalid config path '$configPath'");
+ }
+ self::$instances[$configPath] = new static(parse_ini_file($configPath, true));
+ }
+
+ return self::$instances[$configPath];
+ }
+
+ /**
+ * This method checks if a base path is given and usage is set to true.
+ * If all that tests succeed the base path will be returned as a string -
+ * else null will be returned.
+ *
+ * @return string|null the base path or null
+ */
+ public function getBasePath()
+ {
+ return (!empty($this->config['General']['base_path'])
+ && !empty($this->config['General']['use_base_path']))
+ ? $this->config['General']['base_path'] : null;
+ }
+
+ /**
+ * Merges new settings into the exsiting ones or overwrites them
+ *
+ * @param array $config the config array
+ * @param boolean $overwrite config overwrite flag
+ *
+ * @return void
+ */
+ public function setConfig(array $config, $overwrite = false)
+ {
+ if ($overwrite) {
+ $this->config = $this->mergeConfig($this->config, $config);
+ } else {
+ $this->config = $this->mergeConfig($config, $this->config);
+ }
+ }
+
+ /**
+ * Merge config hashes recursivly
+ *
+ * The algorithm merges configuration arrays recursively. If an element is
+ * an array in both, the values will be appended. If it is a scalar in both,
+ * the value will be replaced.
+ *
+ * @param array $current The legacy hash
+ * @param array $successor The hash which values count more when in doubt
+ * @return array Merged hash
+ */
+ protected function mergeConfig($current, $successor)
+ {
+ if (is_array($current) and is_array($successor)) {
+ foreach ($successor as $key => $value) {
+ if (isset($current[$key])
+ and is_array($value)
+ and is_array($current[$key])) {
+
+ $current[$key] = $this->mergeConfig($current[$key], $value);
+ } else {
+ $current[$key] = $successor[$key];
+ }
+ }
+ }
+
+ return $current;
+ }
+
+ /**
+ * Returns the config array
+ *
+ * @return array the config array
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+}
diff --git a/interface/lib/classes/IDS/Monitor.php b/interface/lib/classes/IDS/Monitor.php
new file mode 100644
index 0000000..f93e748
--- /dev/null
+++ b/interface/lib/classes/IDS/Monitor.php
@@ -0,0 +1,566 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS;
+
+use IDS\Filter\Storage;
+
+/**
+ * Monitoring engine
+ *
+ * This class represents the core of the frameworks attack detection mechanism
+ * and provides functions to scan incoming data for malicious appearing script
+ * fragments.
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+class Monitor
+{
+ /**
+ * Tags to define what to search for
+ *
+ * Accepted values are xss, csrf, sqli, dt, id, lfi, rfe, spam, dos
+ *
+ * @var array
+ */
+ private $tags = null;
+
+ /**
+ * Container for filter rules
+ *
+ * Holds an instance of Storage
+ *
+ * @var Storage
+ */
+ private $storage = null;
+
+ /**
+ * Scan keys switch
+ *
+ * Enabling this property will cause the monitor to scan both the key and
+ * the value of variables
+ *
+ * @var boolean
+ */
+ public $scanKeys = false;
+
+ /**
+ * Exception container
+ *
+ * Using this array it is possible to define variables that must not be
+ * scanned. Per default, utmz google analytics parameters are permitted.
+ *
+ * @var array
+ */
+ private $exceptions = array();
+
+ /**
+ * Html container
+ *
+ * Using this array it is possible to define variables that legally
+ * contain html and have to be prepared before hitting the rules to
+ * avoid too many false alerts
+ *
+ * @var array
+ */
+ private $html = array();
+
+ /**
+ * JSON container
+ *
+ * Using this array it is possible to define variables that contain
+ * JSON data - and should be treated as such
+ *
+ * @var array
+ */
+ private $json = array();
+
+ /**
+ * Holds HTMLPurifier object
+ *
+ * @var \HTMLPurifier
+ */
+ private $htmlPurifier = null;
+
+ /**
+ * HTMLPurifier cache directory
+ *
+ * @var string
+ */
+ private $HTMLPurifierCache = '';
+
+ /**
+ * This property holds the tmp JSON string from the _jsonDecodeValues() callback
+ *
+ * @var string
+ */
+ private $tmpJsonString = '';
+
+ /**
+ * Constructor
+ *
+ * @throws \InvalidArgumentException When PHP version is less than what the library supports
+ * @throws \Exception
+ * @param Init $init instance of IDS_Init
+ * @param array|null $tags list of tags to which filters should be applied
+ * @return Monitor
+ */
+ public function __construct(Init $init, array $tags = null)
+ {
+ $this->storage = new Storage($init);
+ $this->tags = $tags;
+ $this->scanKeys = $init->config['General']['scan_keys'];
+ $this->exceptions = isset($init->config['General']['exceptions']) ? $init->config['General']['exceptions'] : array();
+ $this->html = isset($init->config['General']['html']) ? $init->config['General']['html'] : array();
+ $this->json = isset($init->config['General']['json']) ? $init->config['General']['json'] : array();
+
+ if (isset($init->config['General']['HTML_Purifier_Cache'])) {
+ $this->HTMLPurifierCache = $init->getBasePath() . $init->config['General']['HTML_Purifier_Cache'];
+ }
+
+ $tmpPath = $init->getBasePath() . $init->config['General']['tmp_path'];
+
+ if (!is_writeable($tmpPath)) {
+ throw new \InvalidArgumentException("Please make sure the folder '$tmpPath' is writable");
+ }
+ }
+
+ /**
+ * Starts the scan mechanism
+ *
+ * @param array $request
+ * @return Report
+ */
+ public function run(array $request)
+ {
+ $report = new Report;
+ foreach ($request as $key => $value) {
+ $report = $this->iterate($key, $value, $report);
+ }
+ return $report;
+ }
+
+ /**
+ * Iterates through given data and delegates it to IDS_Monitor::_detect() in
+ * order to check for malicious appearing fragments
+ *
+ * @param string $key the former array key
+ * @param array|string $value the former array value
+ * @param Report $report
+ * @return Report
+ */
+ private function iterate($key, $value, Report $report)
+ {
+ if (is_array($value)) {
+ foreach ($value as $subKey => $subValue) {
+ $this->iterate("$key.$subKey", $subValue, $report);
+ }
+ } elseif (is_string($value)) {
+ if ($filter = $this->detect($key, $value)) {
+ $report->addEvent(new Event($key, $value, $filter));
+ }
+ }
+ return $report;
+ }
+
+ /**
+ * Checks whether given value matches any of the supplied filter patterns
+ *
+ * @param mixed $key the key of the value to scan
+ * @param mixed $value the value to scan
+ *
+ * @return Filter[] array of filter(s) that matched the value
+ */
+ private function detect($key, $value)
+ {
+ // define the pre-filter
+ $preFilter = '([^\w\s/@!?\.]+|(?:\./)|(?:@@\w+)|(?:\+ADw)|(?:union\s+select))i';
+
+ // to increase performance, only start detection if value isn't alphanumeric
+ if ((!$this->scanKeys || !$key || !preg_match($preFilter, $key)) && (!$value || !preg_match($preFilter, $value))) {
+ return array();
+ }
+
+ // check if this field is part of the exceptions
+ foreach ($this->exceptions as $exception) {
+ $matches = array();
+ if (($exception === $key) || preg_match('((/.*/[^eE]*)$)', $exception, $matches) && isset($matches[1]) && preg_match($matches[1], $key)) {
+ return array();
+ }
+ }
+
+ // check for magic quotes and remove them if necessary
+ if (function_exists('get_magic_quotes_gpc') && !get_magic_quotes_gpc()) {
+ $value = preg_replace('(\\\(["\'/]))im', '$1', $value);
+ }
+
+ // if html monitoring is enabled for this field - then do it!
+ if (is_array($this->html) && in_array($key, $this->html, true)) {
+ list($key, $value) = $this->purifyValues($key, $value);
+ }
+
+ // check if json monitoring is enabled for this field
+ if (is_array($this->json) && in_array($key, $this->json, true)) {
+ list($key, $value) = $this->jsonDecodeValues($key, $value);
+ }
+
+ // use the converter
+ $value = Converter::runAll($value);
+ $value = Converter::runCentrifuge($value, $this);
+
+ // scan keys if activated via config
+ $key = $this->scanKeys ? Converter::runAll($key) : $key;
+ $key = $this->scanKeys ? Converter::runCentrifuge($key, $this) : $key;
+
+ $filterSet = $this->storage->getFilterSet();
+
+ if ($tags = $this->tags) {
+ $filterSet = array_filter(
+ $filterSet,
+ function (Filter $filter) use ($tags) {
+ return (bool) array_intersect($tags, $filter->getTags());
+ }
+ );
+ }
+
+ $scanKeys = $this->scanKeys;
+ $filterSet = array_filter(
+ $filterSet,
+ function (Filter $filter) use ($key, $value, $scanKeys) {
+ return $filter->match($value) || $scanKeys && $filter->match($key);
+ }
+ );
+
+ return $filterSet;
+ }
+
+
+ /**
+ * Purifies given key and value variables using HTMLPurifier
+ *
+ * This function is needed whenever there is variables for which HTML
+ * might be allowed like e.g. WYSIWYG post bodies. It will detect malicious
+ * code fragments and leaves harmless parts untouched.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @since 0.5
+ * @throws \Exception
+ *
+ * @return array tuple [key,value]
+ */
+ private function purifyValues($key, $value)
+ {
+ /*
+ * Perform a pre-check if string is valid for purification
+ */
+ if ($this->purifierPreCheck($key, $value)) {
+ if (!is_writeable($this->HTMLPurifierCache)) {
+ throw new \Exception($this->HTMLPurifierCache . ' must be writeable');
+ }
+
+ /** @var $config \HTMLPurifier_Config */
+ $config = \HTMLPurifier_Config::createDefault();
+ $config->set('Attr.EnableID', true);
+ $config->set('Cache.SerializerPath', $this->HTMLPurifierCache);
+ $config->set('Output.Newline', "\n");
+ $this->htmlPurifier = new \HTMLPurifier($config);
+
+ $value = preg_replace('([\x0b-\x0c])', ' ', $value);
+ $key = preg_replace('([\x0b-\x0c])', ' ', $key);
+
+ $purifiedValue = $this->htmlPurifier->purify($value);
+ $purifiedKey = $this->htmlPurifier->purify($key);
+
+ $plainValue = strip_tags($value);
+ $plainKey = strip_tags($key);
+
+ $value = $value != $purifiedValue || $plainValue ? $this->diff($value, $purifiedValue, $plainValue) : null;
+ $key = $key != $purifiedKey ? $this->diff($key, $purifiedKey, $plainKey) : null;
+ }
+ return array($key, $value);
+ }
+
+ /**
+ * This method makes sure no dangerous markup can be smuggled in
+ * attributes when HTML mode is switched on.
+ *
+ * If the precheck considers the string too dangerous for
+ * purification false is being returned.
+ *
+ * @param string $key
+ * @param string $value
+ * @since 0.6
+ *
+ * @return boolean
+ */
+ private function purifierPreCheck($key = '', $value = '')
+ {
+ /*
+ * Remove control chars before pre-check
+ */
+ $tmpValue = preg_replace('/\p{C}/', null, $value);
+ $tmpKey = preg_replace('/\p{C}/', null, $key);
+
+ $preCheck = '/<(script|iframe|applet|object)\W/i';
+ return !(preg_match($preCheck, $tmpKey) || preg_match($preCheck, $tmpValue));
+ }
+
+ /**
+ * This method calculates the difference between the original
+ * and the purified markup strings.
+ *
+ * @param string $original the original markup
+ * @param string $purified the purified markup
+ * @param string $plain the string without html
+ * @since 0.5
+ *
+ * @return string the difference between the strings
+ */
+ private function diff($original, $purified, $plain)
+ {
+ /*
+ * deal with over-sensitive alt-attribute addition of the purifier
+ * and other common html formatting problems
+ */
+ $purified = preg_replace('/\s+alt="[^"]*"/m', null, $purified);
+ $purified = preg_replace('/=?\s*"\s*"/m', null, $purified);
+ $original = preg_replace('/\s+alt="[^"]*"/m', null, $original);
+ $original = preg_replace('/=?\s*"\s*"/m', null, $original);
+ $original = preg_replace('/style\s*=\s*([^"])/m', 'style = "$1', $original);
+
+ # deal with oversensitive CSS normalization
+ $original = preg_replace('/(?:([\w\-]+:)+\s*([^;]+;\s*))/m', '$1$2', $original);
+
+ # strip whitespace between tags
+ $original = trim(preg_replace('/>\s*</m', '><', $original));
+ $purified = trim(preg_replace('/>\s*</m', '><', $purified));
+
+ $original = preg_replace('/(=\s*(["\'`])[^>"\'`]*>[^>"\'`]*["\'`])/m', 'alt$1', $original);
+
+ // no purified html is left
+ if (!$purified) {
+ return $original;
+ }
+
+ // calculate the diff length
+ $length = mb_strlen($original) - mb_strlen($purified);
+
+ /*
+ * Calculate the difference between the original html input
+ * and the purified string.
+ */
+ $array1 = preg_split('/(?<!^)(?!$)/u', html_entity_decode(urldecode($original)));
+ $array2 = preg_split('/(?<!^)(?!$)/u', $purified);
+
+ // create an array containing the single character differences
+ $differences = array_diff_assoc($array1, $array2);
+
+ // return the diff - ready to hit the converter and the rules
+ $differences = trim(implode('', $differences));
+ $diff = $length <= 10 ? $differences : mb_substr($differences, 0, strlen($original));
+
+ // clean up spaces between tag delimiters
+ $diff = preg_replace('/>\s*</m', '><', $diff);
+
+ // correct over-sensitively stripped bad html elements
+ $diff = preg_replace('/[^<](iframe|script|embed|object|applet|base|img|style)/m', '<$1', $diff );
+
+ return mb_strlen($diff) >= 4 ? $diff . $plain : null;
+ }
+
+ /**
+ * This method prepares incoming JSON data for the PHPIDS detection
+ * process. It utilizes _jsonConcatContents() as callback and returns a
+ * string version of the JSON data structures.
+ *
+ * @param string $key
+ * @param string $value
+ * @since 0.5.3
+ *
+ * @return array tuple [key,value]
+ */
+ private function jsonDecodeValues($key, $value)
+ {
+ $decodedKey = json_decode($key);
+ $decodedValue = json_decode($value);
+
+ if ($decodedValue && is_array($decodedValue) || is_object($decodedValue)) {
+ array_walk_recursive($decodedValue, array($this, 'jsonConcatContents'));
+ $value = $this->tmpJsonString;
+ } else {
+ $this->tmpJsonString .= " " . $decodedValue . "\n";
+ }
+
+ if ($decodedKey && is_array($decodedKey) || is_object($decodedKey)) {
+ array_walk_recursive($decodedKey, array($this, 'jsonConcatContents'));
+ $key = $this->tmpJsonString;
+ } else {
+ $this->tmpJsonString .= " " . $decodedKey . "\n";
+ }
+
+ return array($key, $value);
+ }
+
+ /**
+ * This is the callback used in _jsonDecodeValues(). The method
+ * concatenates key and value and stores them in $this->tmpJsonString.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @since 0.5.3
+ *
+ * @return void
+ */
+ private function jsonConcatContents($key, $value)
+ {
+ if (is_string($key) && is_string($value)) {
+ $this->tmpJsonString .= $key . " " . $value . "\n";
+ } else {
+ $this->jsonDecodeValues(json_encode($key), json_encode($value));
+ }
+ }
+
+ /**
+ * Sets exception array
+ *
+ * @param string[]|string $exceptions the thrown exceptions
+ *
+ * @return void
+ */
+ public function setExceptions($exceptions)
+ {
+ $this->exceptions = (array) $exceptions;
+ }
+
+ /**
+ * Returns exception array
+ *
+ * @return array
+ */
+ public function getExceptions()
+ {
+ return $this->exceptions;
+ }
+
+ /**
+ * Sets html array
+ *
+ * @param string[]|string $html the fields containing html
+ * @since 0.5
+ *
+ * @return void
+ */
+ public function setHtml($html)
+ {
+ $this->html = (array) $html;
+ }
+
+ /**
+ * Adds a value to the html array
+ *
+ * @since 0.5
+ *
+ * @param mixed $value
+ * @return void
+ */
+ public function addHtml($value)
+ {
+ $this->html[] = $value;
+ }
+
+ /**
+ * Returns html array
+ *
+ * @since 0.5
+ *
+ * @return array the fields that contain allowed html
+ */
+ public function getHtml()
+ {
+ return $this->html;
+ }
+
+ /**
+ * Sets json array
+ *
+ * @param string[]|string $json the fields containing json
+ * @since 0.5.3
+ *
+ * @return void
+ */
+ public function setJson($json)
+ {
+ $this->json = (array) $json;
+ }
+
+ /**
+ * Adds a value to the json array
+ *
+ * @param string $value the value containing JSON data
+ * @since 0.5.3
+ *
+ * @return void
+ */
+ public function addJson($value)
+ {
+ $this->json[] = $value;
+ }
+
+ /**
+ * Returns json array
+ *
+ * @since 0.5.3
+ *
+ * @return array the fields that contain json
+ */
+ public function getJson()
+ {
+ return $this->json;
+ }
+
+ /**
+ * Returns storage container
+ *
+ * @return array
+ */
+ public function getStorage()
+ {
+ return $this->storage;
+ }
+}
diff --git a/interface/lib/classes/IDS/Report.php b/interface/lib/classes/IDS/Report.php
new file mode 100644
index 0000000..daebfc0
--- /dev/null
+++ b/interface/lib/classes/IDS/Report.php
@@ -0,0 +1,339 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS;
+
+/**
+ * PHPIDS report object
+ *
+ * The report objects collects a number of events and thereby presents the
+ * detected results. It provides a convenient API to work with the results.
+ *
+ * Note that this class implements Countable, IteratorAggregate and
+ * a __toString() method
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+class Report implements \Countable, \IteratorAggregate
+{
+ /**
+ * Event container
+ *
+ * @var Event[]|array
+ */
+ protected $events = array();
+
+ /**
+ * List of affected tags
+ *
+ * This list of tags is collected from the collected event objects on
+ * demand when IDS_Report->getTags() is called
+ *
+ * @var string[]|array
+ */
+ protected $tags = array();
+
+ /**
+ * Impact level
+ *
+ * The impact level is calculated on demand by adding the results of the
+ * event objects on IDS\Report->getImpact()
+ *
+ * @var integer
+ */
+ protected $impact = 0;
+
+ /**
+ * Centrifuge data
+ *
+ * This variable - initiated as an empty array - carries all information
+ * about the centrifuge data if available
+ *
+ * @var array
+ */
+ protected $centrifuge = array();
+
+ /**
+ * Constructor
+ *
+ * @param array $events the events the report should include
+ *
+ * @return Report
+ */
+ public function __construct(array $events = null)
+ {
+ foreach ((array) $events as $event) {
+ $this->addEvent($event);
+ }
+ }
+
+ /**
+ * Adds an IDS_Event object to the report
+ *
+ * @param Event $event IDS_Event
+ *
+ * @return self $this
+ */
+ public function addEvent(Event $event)
+ {
+ $this->clear();
+ $this->events[$event->getName()] = $event;
+
+ return $this;
+ }
+
+ /**
+ * Get event by name
+ *
+ * In most cases an event is identified by the key of the variable that
+ * contained maliciously appearing content
+ *
+ * @param string|integer $name the event name
+ *
+ * @throws \InvalidArgumentException if argument is invalid
+ * @return Event|null IDS_Event object or false if the event does not exist
+ */
+ public function getEvent($name)
+ {
+ if (!is_scalar($name)) {
+ throw new \InvalidArgumentException('Invalid argument type given');
+ }
+
+ return $this->hasEvent($name) ? $this->events[$name] : null;
+ }
+
+ /**
+ * Returns list of events
+ *
+ * @return string[]|array
+ */
+
+ public function getEvents()
+ {
+ return $this->events;
+ }
+
+ /**
+ * Returns list of affected tags
+ *
+ * @return string[]|array
+ */
+ public function getTags()
+ {
+ if (!$this->tags) {
+ $this->tags = array();
+
+ foreach ($this->events as $event) {
+ $this->tags = array_merge($this->tags, $event->getTags());
+ }
+
+ $this->tags = array_values(array_unique($this->tags));
+ }
+
+ return $this->tags;
+ }
+
+ /**
+ * Returns total impact
+ *
+ * Each stored IDS_Event object and its IDS_Filter sub-object are called
+ * to calculate the overall impact level of this request
+ *
+ * @return integer
+ */
+ public function getImpact()
+ {
+ if (!$this->impact) {
+ $this->impact = 0;
+ foreach ($this->events as $event) {
+ $this->impact += $event->getImpact();
+ }
+ }
+
+ return $this->impact;
+ }
+
+ /**
+ * Checks if a specific event with given name exists
+ *
+ * @param string|integer $name the event name
+ *
+ * @throws \InvalidArgumentException if argument is illegal
+ * @return boolean
+ */
+ public function hasEvent($name)
+ {
+ if (!is_scalar($name)) {
+ throw new \InvalidArgumentException('Invalid argument given');
+ }
+
+ return isset($this->events[$name]);
+ }
+
+ /**
+ * Returns total amount of events
+ *
+ * @return integer
+ */
+ public function count()
+ {
+ return count($this->events);
+ }
+
+ /**
+ * Return iterator object
+ *
+ * In order to provide the possibility to directly iterate over the
+ * IDS_Event object the IteratorAggregate is implemented. One can easily
+ * use foreach() to iterate through all stored IDS_Event objects.
+ *
+ * @return \Iterator the event collection
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->events);
+ }
+
+ /**
+ * Checks if any events are registered
+ *
+ * @return boolean
+ */
+ public function isEmpty()
+ {
+ return empty($this->events);
+ }
+
+ /**
+ * Clears calculated/collected values
+ *
+ * @return void
+ */
+ protected function clear()
+ {
+ $this->impact = 0;
+ $this->tags = array();
+ }
+
+ /**
+ * This method returns the centrifuge property or null if not
+ * filled with data
+ *
+ * @return array
+ */
+ public function getCentrifuge()
+ {
+ return $this->centrifuge;
+ }
+
+ /**
+ * This method sets the centrifuge property
+ *
+ * @param array $centrifuge the centrifuge data
+ *
+ * @throws \InvalidArgumentException if argument is illegal
+ * @return void
+ */
+ public function setCentrifuge(array $centrifuge = array())
+ {
+ if (!$centrifuge) {
+ throw new \InvalidArgumentException('Empty centrifuge given');
+ }
+ $this->centrifuge = $centrifuge;
+ }
+
+ /**
+ * Directly outputs all available information
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $output = '';
+ if (!$this->isEmpty()) {
+ $output .= vsprintf(
+ "Total impact: %d<br/>\nAffected tags: %s<br/>\n",
+ array(
+ $this->getImpact(),
+ implode(', ', $this->getTags())
+ )
+ );
+
+ foreach ($this->events as $event) {
+ $output .= vsprintf(
+ "<br/>\nVariable: %s | Value: %s<br/>\nImpact: %d | Tags: %s<br/>\n",
+ array(
+ htmlspecialchars($event->getName()),
+ htmlspecialchars($event->getValue()),
+ $event->getImpact(),
+ implode(', ', $event->getTags())
+ )
+ );
+
+ foreach ($event as $filter) {
+ $output .= vsprintf(
+ "Description: %s | Tags: %s | ID %s<br/>\n",
+ array(
+ $filter->getDescription(),
+ implode(', ', $filter->getTags()),
+ $filter->getId()
+ )
+ );
+ }
+ }
+
+ $output .= '<br/>';
+
+ if ($centrifuge = $this->getCentrifuge()) {
+ $output .= vsprintf(
+ "Centrifuge detection data<br/> Threshold: %s<br/> Ratio: %s",
+ array(
+ isset($centrifuge['threshold']) && $centrifuge['threshold'] ? $centrifuge['threshold'] : '---',
+ isset($centrifuge['ratio']) && $centrifuge['ratio'] ? $centrifuge['ratio'] : '---'
+ )
+ );
+ if (isset($centrifuge['converted'])) {
+ $output .= '<br/> Converted: ' . $centrifuge['converted'];
+ }
+ $output .= "<br/><br/>\n";
+ }
+ }
+
+ return $output;
+ }
+}
diff --git a/interface/lib/classes/IDS/Version.php b/interface/lib/classes/IDS/Version.php
new file mode 100644
index 0000000..b32438f
--- /dev/null
+++ b/interface/lib/classes/IDS/Version.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * PHPIDS
+ *
+ * Requirements: PHP5, SimpleXML
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5.1.6+
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+namespace IDS;
+
+/**
+ * PHPIDS version class
+ *
+ * @category Security
+ * @package PHPIDS
+ * @author Christian Matthies <ch0012@gmail.com>
+ * @author Mario Heiderich <mario.heiderich@gmail.com>
+ * @author Lars Strojny <lars@strojny.net>
+ * @copyright 2007-2009 The PHPIDS Group
+ * @license http://www.gnu.org/licenses/lgpl.html LGPL
+ * @link http://php-ids.org/
+ */
+abstract class Version
+{
+ const VERSION = 'master';
+}
diff --git a/interface/lib/classes/IDS/default_filter.json b/interface/lib/classes/IDS/default_filter.json
new file mode 100644
index 0000000..c158ded
--- /dev/null
+++ b/interface/lib/classes/IDS/default_filter.json
@@ -0,0 +1,933 @@
+{
+ "filters":{
+ "filter":[
+ {
+ "id":"1",
+ "rule":"(?:\"[^\"]*[^-]?>)|(?:[^\\w\\s]\\s*\\\/>)|(?:>\")",
+ "description":"Finds html breaking injections including whitespace attacks",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"2",
+ "rule":"(?:\"+.*[<=]\\s*\"[^\"]+\")|(?:\"\\s*\\w+\\s*=)|(?:>\\w=\\\/)|(?:#.+\\)[\"\\s]*>)|(?:\"\\s*(?:src|style|on\\w+)\\s*=\\s*\")|(?:[^\"]?\"[,;\\s]+\\w*[\\[\\(])",
+ "description":"Finds attribute breaking injections including whitespace attacks",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"3",
+ "rule":"(?:^>[\\w\\s]*<\\\/?\\w{2,}>)",
+ "description":"Finds unquoted attribute breaking injections",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"2"
+ },
+ {
+ "id":"4",
+ "rule":"(?:[+\\\/]\\s*name[\\W\\d]*[)+])|(?:;\\W*url\\s*=)|(?:[^\\w\\s\\\/?:>]\\s*(?:location|referrer|name)\\s*[^\\\/\\w\\s-])",
+ "description":"Detects url-, name-, JSON, and referrer-contained payload attacks",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"5",
+ "rule":"(?:\\W\\s*hash\\s*[^\\w\\s-])|(?:\\w+=\\W*[^,]*,[^\\s(]\\s*\\()|(?:\\?\"[^\\s\"]\":)|(?:(?<!\\\/)__[a-z]+__)|(?:(?:^|[\\s)\\]\\}])(?:s|g)etter\\s*=)",
+ "description":"Detects hash-contained xss payload attacks, setter usage and property overloading",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"6",
+ "rule":"(?:with\\s*\\(\\s*.+\\s*\\)\\s*\\w+\\s*\\()|(?:(?:do|while|for)\\s*\\([^)]*\\)\\s*\\{)|(?:\\\/[\\w\\s]*\\[\\W*\\w)",
+ "description":"Detects self contained xss via with(), common loops and regex to string conversion",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"7",
+ "rule":"(?:[=(].+\\?.+:)|(?:with\\([^)]*\\)\\))|(?:\\.\\s*source\\W)",
+ "description":"Detects JavaScript with(), ternary operators and XML predicate attacks",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"8",
+ "rule":"(?:\\\/\\w*\\s*\\)\\s*\\()|(?:\\([\\w\\s]+\\([\\w\\s]+\\)[\\w\\s]+\\))|(?:(?<!(?:mozilla\\\/\\d\\.\\d\\s))\\([^)[]+\\[[^\\]]+\\][^)]*\\))|(?:[^\\s!][{([][^({[]+[{([][^}\\])]+[}\\])][\\s+\",\\d]*[}\\])])|(?:\"\\)?\\]\\W*\\[)|(?:=\\s*[^\\s:;]+\\s*[{([][^}\\])]+[}\\])];)",
+ "description":"Detects self-executing JavaScript functions",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"9",
+ "rule":"(?:\\\\u00[a-f0-9]{2})|(?:\\\\x0*[a-f0-9]{2})|(?:\\\\\\d{2,3})",
+ "description":"Detects the IE octal, hex and unicode entities",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"2"
+ },
+ {
+ "id":"10",
+ "rule":"(?:(?:\\\/|\\\\)?\\.+(\\\/|\\\\)(?:\\.+)?)|(?:\\w+\\.exe\\??\\s)|(?:;\\s*\\w+\\s*\\\/[\\w*-]+\\\/)|(?:\\d\\.\\dx\\|)|(?:%(?:c0\\.|af\\.|5c\\.))|(?:\\\/(?:%2e){2})",
+ "description":"Detects basic directory traversal",
+ "tags":{
+ "tag":[
+ "dt",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"11",
+ "rule":"(?:%c0%ae\\\/)|(?:(?:\\\/|\\\\)(home|conf|usr|etc|proc|opt|s?bin|local|dev|tmp|kern|[br]oot|sys|system|windows|winnt|program|%[a-z_-]{3,}%)(?:\\\/|\\\\))|(?:(?:\\\/|\\\\)inetpub|localstart\\.asp|boot\\.ini)",
+ "description":"Detects specific directory and path traversal",
+ "tags":{
+ "tag":[
+ "dt",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"12",
+ "rule":"(?:etc\\\/\\W*passwd)",
+ "description":"Detects etc\/passwd inclusion attempts",
+ "tags":{
+ "tag":[
+ "dt",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"13",
+ "rule":"(?:%u(?:ff|00|e\\d)\\w\\w)|(?:(?:%(?:e\\w|c[^3\\W]|))(?:%\\w\\w)(?:%\\w\\w)?)",
+ "description":"Detects halfwidth\/fullwidth encoded unicode HTML breaking attempts",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"3"
+ },
+ {
+ "id":"14",
+ "rule":"(?:#@~\\^\\w+)|(?:\\w+script:|@import[^\\w]|;base64|base64,)|(?:\\w\\s*\\([\\w\\s]+,[\\w\\s]+,[\\w\\s]+,[\\w\\s]+,[\\w\\s]+,[\\w\\s]+\\))",
+ "description":"Detects possible includes, VBSCript\/JScript encodeed and packed functions",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"15",
+ "rule":"([^*:\\s\\w,.\\\/?+-]\\s*)?(?<![a-z]\\s)(?<![a-z\\\/_@\\-\\|])(\\s*return\\s*)?(?:create(?:element|attribute|textnode)|[a-z]+events?|setattribute|getelement\\w+|appendchild|createrange|createcontextualfragment|removenode|parentnode|decodeuricomponent|\\wettimeout|(?:ms)?setimmediate|option|useragent)(?(1)[^\\w%\"]|(?:\\s*[^@\\s\\w%\",.+\\-]))",
+ "description":"Detects JavaScript DOM\/miscellaneous properties and methods",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"16",
+ "rule":"([^*\\s\\w,.\\\/?+-]\\s*)?(?<![a-mo-z]\\s)(?<![a-z\\\/_@])(\\s*return\\s*)?(?:alert|inputbox|showmod(?:al|eless)dialog|showhelp|infinity|isnan|isnull|iterator|msgbox|executeglobal|expression|prompt|write(?:ln)?|confirm|dialog|urn|(?:un)?eval|exec|execscript|tostring|status|execute|window|unescape|navigate|jquery|getscript|extend|prototype)(?(1)[^\\w%\"]|(?:\\s*[^@\\s\\w%\",.:\\\/+\\-]))",
+ "description":"Detects possible includes and typical script methods",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"17",
+ "rule":"([^*:\\s\\w,.\\\/?+-]\\s*)?(?<![a-z]\\s)(?<![a-z\\\/_@])(\\s*return\\s*)?(?:hash|name|href|navigateandfind|source|pathname|close|constructor|port|protocol|assign|replace|back|forward|document|ownerdocument|window|top|this|self|parent|frames|_?content|date|cookie|innerhtml|innertext|csstext+?|outerhtml|print|moveby|resizeto|createstylesheet|stylesheets)(?(1)[^\\w%\"]|(?:\\s*[^@\\\/\\s\\w%.+\\-]))",
+ "description":"Detects JavaScript object properties and methods",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"18",
+ "rule":"([^*:\\s\\w,.\\\/?+-]\\s*)?(?<![a-z]\\s)(?<![a-z\\\/_@\\-\\|])(\\s*return\\s*)?(?:join|pop|push|reverse|reduce|concat|map|shift|sp?lice|sort|unshift)(?(1)[^\\w%\"]|(?:\\s*[^@\\s\\w%,.+\\-]))",
+ "description":"Detects JavaScript array properties and methods",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"19",
+ "rule":"([^*:\\s\\w,.\\\/?+-]\\s*)?(?<![a-z]\\s)(?<![a-z\\\/_@\\-\\|])(\\s*return\\s*)?(?:set|atob|btoa|charat|charcodeat|charset|concat|crypto|frames|fromcharcode|indexof|lastindexof|match|navigator|toolbar|menubar|replace|regexp|slice|split|substr|substring|escape|\\w+codeuri\\w*)(?(1)[^\\w%\"]|(?:\\s*[^@\\s\\w%,.+\\-]))",
+ "description":"Detects JavaScript string properties and methods",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"20",
+ "rule":"(?:\\)\\s*\\[)|([^*\":\\s\\w,.\\\/?+-]\\s*)?(?<![a-z]\\s)(?<![a-z_@\\|])(\\s*return\\s*)?(?:globalstorage|sessionstorage|postmessage|callee|constructor|content|domain|prototype|try|catch|top|call|apply|url|function|object|array|string|math|if|for\\s*(?:each)?|elseif|case|switch|regex|boolean|location|(?:ms)?setimmediate|settimeout|setinterval|void|setexpression|namespace|while)(?(1)[^\\w%\"]|(?:\\s*[^@\\s\\w%\".+\\-\\\/]))",
+ "description":"Detects JavaScript language constructs",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"21",
+ "rule":"(?:,\\s*(?:alert|showmodaldialog|eval)\\s*,)|(?::\\s*eval\\s*[^\\s])|([^:\\s\\w,.\\\/?+-]\\s*)?(?<![a-z\\\/_@])(\\s*return\\s*)?(?:(?:document\\s*\\.)?(?:.+\\\/)?(?:alert|eval|msgbox|showmod(?:al|eless)dialog|showhelp|prompt|write(?:ln)?|confirm|dialog|open))\\s*(?:[^.a-z\\s\\-]|(?:\\s*[^\\s\\w,.@\\\/+-]))|(?:java[\\s\\\/]*\\.[\\s\\\/]*lang)|(?:\\w\\s*=\\s*new\\s+\\w+)|(?:&\\s*\\w+\\s*\\)[^,])|(?:\\+[\\W\\d]*new\\s+\\w+[\\W\\d]*\\+)|(?:document\\.\\w)",
+ "description":"Detects very basic XSS probings",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"3"
+ },
+ {
+ "id":"22",
+ "rule":"(?:=\\s*(?:top|this|window|content|self|frames|_content))|(?:\\\/\\s*[gimx]*\\s*[)}])|(?:[^\\s]\\s*=\\s*script)|(?:\\.\\s*constructor)|(?:default\\s+xml\\s+namespace\\s*=)|(?:\\\/\\s*\\+[^+]+\\s*\\+\\s*\\\/)",
+ "description":"Detects advanced XSS probings via Script(), RexExp, constructors and XML namespaces",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"23",
+ "rule":"(?:\\.\\s*\\w+\\W*=)|(?:\\W\\s*(?:location|document)\\s*\\W[^({[;]+[({[;])|(?:\\(\\w+\\?[:\\w]+\\))|(?:\\w{2,}\\s*=\\s*\\d+[^&\\w]\\w+)|(?:\\]\\s*\\(\\s*\\w+)",
+ "description":"Detects JavaScript location\/document property access and window access obfuscation",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"24",
+ "rule":"(?:[\".]script\\s*\\()|(?:\\$\\$?\\s*\\(\\s*[\\w\"])|(?:\\\/[\\w\\s]+\\\/\\.)|(?:=\\s*\\\/\\w+\\\/\\s*\\.)|(?:(?:this|window|top|parent|frames|self|content)\\[\\s*[(,\"]*\\s*[\\w\\$])|(?:,\\s*new\\s+\\w+\\s*[,;)])",
+ "description":"Detects basic obfuscated JavaScript script injections",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"25",
+ "rule":"(?:=\\s*[$\\w]\\s*[\\(\\[])|(?:\\(\\s*(?:this|top|window|self|parent|_?content)\\s*\\))|(?:src\\s*=s*(?:\\w+:|\\\/\\\/))|(?:\\w+\\[(\"\\w+\"|\\w+\\|\\|))|(?:[\\d\\W]\\|\\|[\\d\\W]|\\W=\\w+,)|(?:\\\/\\s*\\+\\s*[a-z\"])|(?:=\\s*\\$[^([]*\\()|(?:=\\s*\\(\\s*\")",
+ "description":"Detects obfuscated JavaScript script injections",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"26",
+ "rule":"(?:[^:\\s\\w]+\\s*[^\\w\\\/](href|protocol|host|hostname|pathname|hash|port|cookie)[^\\w])",
+ "description":"Detects JavaScript cookie stealing and redirection attempts",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"27",
+ "rule":"(?:(?:vbs|vbscript|data):.*[,+])|(?:\\w+\\s*=\\W*(?!https?)\\w+:)|(jar:\\w+:)|(=\\s*\"?\\s*vbs(?:ript)?:)|(language\\s*=\\s?\"?\\s*vbs(?:ript)?)|on\\w+\\s*=\\*\\w+\\-\"?",
+ "description":"Detects data: URL injections, VBS injections and common URI schemes",
+ "tags":{
+ "tag":[
+ "xss",
+ "rfe"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"28",
+ "rule":"(?:firefoxurl:\\w+\\|)|(?:(?:file|res|telnet|nntp|news|mailto|chrome)\\s*:\\s*[%&#xu\\\/]+)|(wyciwyg|firefoxurl\\s*:\\s*\\\/\\s*\\\/)",
+ "description":"Detects IE firefoxurl injections, cache poisoning attempts and local file inclusion\/execution",
+ "tags":{
+ "tag":[
+ "xss",
+ "rfe",
+ "lfi",
+ "csrf"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"29",
+ "rule":"(?:binding\\s?=|moz-binding|behavior\\s?=)|(?:[\\s\\\/]style\\s*=\\s*[-\\\\])",
+ "description":"Detects bindings and behavior injections",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"30",
+ "rule":"(?:=\\s*\\w+\\s*\\+\\s*\")|(?:\\+=\\s*\\(\\s\")|(?:!+\\s*[\\d.,]+\\w?\\d*\\s*\\?)|(?:=\\s*\\[s*\\])|(?:\"\\s*\\+\\s*\")|(?:[^\\s]\\[\\s*\\d+\\s*\\]\\s*[;+])|(?:\"\\s*[&|]+\\s*\")|(?:\\\/\\s*\\?\\s*\")|(?:\\\/\\s*\\)\\s*\\[)|(?:\\d\\?.+:\\d)|(?:]\\s*\\[\\W*\\w)|(?:[^\\s]\\s*=\\s*\\\/)",
+ "description":"Detects common XSS concatenation patterns 1\/2",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"31",
+ "rule":"(?:=\\s*\\d*\\.\\d*\\?\\d*\\.\\d*)|(?:[|&]{2,}\\s*\")|(?:!\\d+\\.\\d*\\?\")|(?:\\\/:[\\w.]+,)|(?:=[\\d\\W\\s]*\\[[^]]+\\])|(?:\\?\\w+:\\w+)",
+ "description":"Detects common XSS concatenation patterns 2\/2",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"32",
+ "rule":"(?:[^\\w\\s=]on(?!g\\>)\\w+[^=_+-]*=[^$]+(?:\\W|\\>)?)",
+ "description":"Detects possible event handlers",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"33",
+ "rule":"(?:\\<\\w*:?\\s(?:[^\\>]*)t(?!rong))|(?:\\<scri)|(<\\w+:\\w+)",
+ "description":"Detects obfuscated script tags and XML wrapped HTML",
+ "tags":{
+ "tag":"xss"
+ },
+ "impact":"4"
+ },
+ {
+ "id":"34",
+ "rule":"(?:\\<\\\/\\w+\\s\\w+)|(?:@(?:cc_on|set)[\\s@,\"=])",
+ "description":"Detects attributes in closing tags and conditional compilation tokens",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"35",
+ "rule":"(?:--[^\\n]*$)|(?:\\<!-|-->)|(?:[^*]\\\/\\*|\\*\\\/[^*])|(?:(?:[\\W\\d]#|--|{)$)|(?:\\\/{3,}.*$)|(?:<!\\[\\W)|(?:\\]!>)",
+ "description":"Detects common comment types",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id"
+ ]
+ },
+ "impact":"3"
+ },
+ {
+ "id":"37",
+ "rule":"(?:\\<base\\s+)|(?:<!(?:element|entity|\\[CDATA))",
+ "description":"Detects base href injections and XML entity injections",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"38",
+ "rule":"(?:\\<[\\\/]?(?:[i]?frame|applet|isindex|marquee|keygen|script|audio|video|input|button|textarea|style|base|body|meta|link|object|embed|param|plaintext|xm\\w+|image|im(?:g|port)))",
+ "description":"Detects possibly malicious html elements including some attributes",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe",
+ "lfi"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"39",
+ "rule":"(?:\\\\x[01fe][\\db-ce-f])|(?:%[01fe][\\db-ce-f])|(?:&#[01fe][\\db-ce-f])|(?:\\\\[01fe][\\db-ce-f])|(?:&#x[01fe][\\db-ce-f])",
+ "description":"Detects nullbytes and other dangerous characters",
+ "tags":{
+ "tag":[
+ "id",
+ "rfe",
+ "xss"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"40",
+ "rule":"(?:\\)\\s*when\\s*\\d+\\s*then)|(?:\"\\s*(?:#|--|{))|(?:\\\/\\*!\\s?\\d+)|(?:ch(?:a)?r\\s*\\(\\s*\\d)|(?:(?:(n?and|x?or|not)\\s+|\\|\\||\\&\\&)\\s*\\w+\\()",
+ "description":"Detects MySQL comments, conditions and ch(a)r injections",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"41",
+ "rule":"(?:[\\s()]case\\s*\\()|(?:\\)\\s*like\\s*\\()|(?:having\\s*[^\\s]+\\s*[^\\w\\s])|(?:if\\s?\\([\\d\\w]\\s*[=<>~])",
+ "description":"Detects conditional SQL injection attempts",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"42",
+ "rule":"(?:\"\\s*or\\s*\"?\\d)|(?:\\\\x(?:23|27|3d))|(?:^.?\"$)|(?:(?:^[\"\\\\]*(?:[\\d\"]+|[^\"]+\"))+\\s*(?:n?and|x?or|not|\\|\\||\\&\\&)\\s*[\\w\"[+&!@(),.-])|(?:[^\\w\\s]\\w+\\s*[|-]\\s*\"\\s*\\w)|(?:@\\w+\\s+(and|or)\\s*[\"\\d]+)|(?:@[\\w-]+\\s(and|or)\\s*[^\\w\\s])|(?:[^\\w\\s:]\\s*\\d\\W+[^\\w\\s]\\s*\".)|(?:\\Winformation_schema|table_name\\W)",
+ "description":"Detects classic SQL injection probings 1\/2",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"43",
+ "rule":"(?:\"\\s*\\*.+(?:or|id)\\W*\"\\d)|(?:\\^\")|(?:^[\\w\\s\"-]+(?<=and\\s)(?<=or\\s)(?<=xor\\s)(?<=nand\\s)(?<=not\\s)(?<=\\|\\|)(?<=\\&\\&)\\w+\\()|(?:\"[\\s\\d]*[^\\w\\s]+\\W*\\d\\W*.*[\"\\d])|(?:\"\\s*[^\\w\\s?]+\\s*[^\\w\\s]+\\s*\")|(?:\"\\s*[^\\w\\s]+\\s*[\\W\\d].*(?:#|--))|(?:\".*\\*\\s*\\d)|(?:\"\\s*or\\s[^\\d]+[\\w-]+.*\\d)|(?:[()*<>%+-][\\w-]+[^\\w\\s]+\"[^,])",
+ "description":"Detects classic SQL injection probings 2\/2",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"44",
+ "rule":"(?:\\d\"\\s+\"\\s+\\d)|(?:^admin\\s*\"|(\\\/\\*)+\"+\\s?(?:--|#|\\\/\\*|{)?)|(?:\"\\s*or[\\w\\s-]+\\s*[+<>=(),-]\\s*[\\d\"])|(?:\"\\s*[^\\w\\s]?=\\s*\")|(?:\"\\W*[+=]+\\W*\")|(?:\"\\s*[!=|][\\d\\s!=+-]+.*[\"(].*$)|(?:\"\\s*[!=|][\\d\\s!=]+.*\\d+$)|(?:\"\\s*like\\W+[\\w\"(])|(?:\\sis\\s*0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:\"[<>~]+\")",
+ "description":"Detects basic SQL authentication bypass attempts 1\/3",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"45",
+ "rule":"(?:union\\s*(?:all|distinct|[(!@]*)\\s*[([]*\\s*select)|(?:\\w+\\s+like\\s+\\\")|(?:like\\s*\"\\%)|(?:\"\\s*like\\W*[\"\\d])|(?:\"\\s*(?:n?and|x?or|not |\\|\\||\\&\\&)\\s+[\\s\\w]+=\\s*\\w+\\s*having)|(?:\"\\s*\\*\\s*\\w+\\W+\")|(?:\"\\s*[^?\\w\\s=.,;)(]+\\s*[(@\"]*\\s*\\w+\\W+\\w)|(?:select\\s*[\\[\\]()\\s\\w\\.,\"-]+from)|(?:find_in_set\\s*\\()",
+ "description":"Detects basic SQL authentication bypass attempts 2\/3",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"46",
+ "rule":"(?:in\\s*\\(+\\s*select)|(?:(?:n?and|x?or|not |\\|\\||\\&\\&)\\s+[\\s\\w+]+(?:regexp\\s*\\(|sounds\\s+like\\s*\"|[=\\d]+x))|(\"\\s*\\d\\s*(?:--|#))|(?:\"[%&<>^=]+\\d\\s*(=|or))|(?:\"\\W+[\\w+-]+\\s*=\\s*\\d\\W+\")|(?:\"\\s*is\\s*\\d.+\"?\\w)|(?:\"\\|?[\\w-]{3,}[^\\w\\s.,]+\")|(?:\"\\s*is\\s*[\\d.]+\\s*\\W.*\")",
+ "description":"Detects basic SQL authentication bypass attempts 3\/3",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"47",
+ "rule":"(?:[\\d\\W]\\s+as\\s*[\"\\w]+\\s*from)|(?:^[\\W\\d]+\\s*(?:union|select|create|rename|truncate|load|alter|delete|update|insert|desc))|(?:(?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\\s+(?:(?:group_)concat|char|load_file)\\s?\\(?)|(?:end\\s*\\);)|(\"\\s+regexp\\W)|(?:[\\s(]load_file\\s*\\()",
+ "description":"Detects concatenated basic SQL injection and SQLLFI attempts",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id",
+ "lfi"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"48",
+ "rule":"(?:@.+=\\s*\\(\\s*select)|(?:\\d+\\s*or\\s*\\d+\\s*[\\-+])|(?:\\\/\\w+;?\\s+(?:having|and|or|select)\\W)|(?:\\d\\s+group\\s+by.+\\()|(?:(?:;|#|--)\\s*(?:drop|alter))|(?:(?:;|#|--)\\s*(?:update|insert)\\s*\\w{2,})|(?:[^\\w]SET\\s*@\\w+)|(?:(?:n?and|x?or|not |\\|\\||\\&\\&)[\\s(]+\\w+[\\s)]*[!=+]+[\\s\\d]*[\"=()])",
+ "description":"Detects chained SQL injection attempts 1\/2",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"49",
+ "rule":"(?:\"\\s+and\\s*=\\W)|(?:\\(\\s*select\\s*\\w+\\s*\\()|(?:\\*\\\/from)|(?:\\+\\s*\\d+\\s*\\+\\s*@)|(?:\\w\"\\s*(?:[-+=|@]+\\s*)+[\\d(])|(?:coalesce\\s*\\(|@@\\w+\\s*[^\\w\\s])|(?:\\W!+\"\\w)|(?:\";\\s*(?:if|while|begin))|(?:\"[\\s\\d]+=\\s*\\d)|(?:order\\s+by\\s+if\\w*\\s*\\()|(?:[\\s(]+case\\d*\\W.+[tw]hen[\\s(])",
+ "description":"Detects chained SQL injection attempts 2\/2",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"50",
+ "rule":"(?:(select|;)\\s+(?:benchmark|if|sleep)\\s*?\\(\\s*\\(?\\s*\\w+)",
+ "description":"Detects SQL benchmark and sleep injection attempts including conditional queries",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"51",
+ "rule":"(?:create\\s+function\\s+\\w+\\s+returns)|(?:;\\s*(?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\\s*[\\[(]?\\w{2,})",
+ "description":"Detects MySQL UDF injection and other data\/structure manipulation attempts",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"52",
+ "rule":"(?:alter\\s*\\w+.*character\\s+set\\s+\\w+)|(\";\\s*waitfor\\s+time\\s+\")|(?:\";.*:\\s*goto)",
+ "description":"Detects MySQL charset switch and MSSQL DoS attempts",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"53",
+ "rule":"(?:procedure\\s+analyse\\s*\\()|(?:;\\s*(declare|open)\\s+[\\w-]+)|(?:create\\s+(procedure|function)\\s*\\w+\\s*\\(\\s*\\)\\s*-)|(?:declare[^\\w]+[@#]\\s*\\w+)|(exec\\s*\\(\\s*@)",
+ "description":"Detects MySQL and PostgreSQL stored procedure\/function injections",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"54",
+ "rule":"(?:select\\s*pg_sleep)|(?:waitfor\\s*delay\\s?\"+\\s?\\d)|(?:;\\s*shutdown\\s*(?:;|--|#|\\\/\\*|{))",
+ "description":"Detects Postgres pg_sleep injection, waitfor delay attacks and database shutdown attempts",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"55",
+ "rule":"(?:\\sexec\\s+xp_cmdshell)|(?:\"\\s*!\\s*[\"\\w])|(?:from\\W+information_schema\\W)|(?:(?:(?:current_)?user|database|schema|connection_id)\\s*\\([^\\)]*)|(?:\";?\\s*(?:select|union|having)\\s*[^\\s])|(?:\\wiif\\s*\\()|(?:exec\\s+master\\.)|(?:union select @)|(?:union[\\w(\\s]*select)|(?:select.*\\w?user\\()|(?:into[\\s+]+(?:dump|out)file\\s*\")",
+ "description":"Detects MSSQL code execution and information gathering attempts",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"56",
+ "rule":"(?:merge.*using\\s*\\()|(execute\\s*immediate\\s*\")|(?:\\W+\\d*\\s*having\\s*[^\\s\\-])|(?:match\\s*[\\w(),+-]+\\s*against\\s*\\()",
+ "description":"Detects MATCH AGAINST, MERGE, EXECUTE IMMEDIATE and HAVING injections",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"57",
+ "rule":"(?:,.*[)\\da-f\"]\"(?:\".*\"|\\Z|[^\"]+))|(?:\\Wselect.+\\W*from)|((?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\\s*\\(\\s*space\\s*\\()",
+ "description":"Detects MySQL comment-\/space-obfuscated injections and backtick termination",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"58",
+ "rule":"(?:@[\\w-]+\\s*\\()|(?:]\\s*\\(\\s*[\"!]\\s*\\w)|(?:<[?%](?:php)?.*(?:[?%]>)?)|(?:;[\\s\\w|]*\\$\\w+\\s*=)|(?:\\$\\w+\\s*=(?:(?:\\s*\\$?\\w+\\s*[(;])|\\s*\".*\"))|(?:;\\s*\\{\\W*\\w+\\s*\\()",
+ "description":"Detects code injection attempts 1\/3",
+ "tags":{
+ "tag":[
+ "id",
+ "rfe",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"59",
+ "rule":"(?:(?:[;]+|(<[?%](?:php)?)).*(?:define|eval|file_get_contents|include|require|require_once|set|shell_exec|phpinfo|system|passthru|preg_\\w+|execute)\\s*[\"(@])",
+ "description":"Detects code injection attempts 2\/3",
+ "tags":{
+ "tag":[
+ "id",
+ "rfe",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"60",
+ "rule":"(?:(?:[;]+|(<[?%](?:php)?)).*[^\\w](?:echo|print|print_r|var_dump|[fp]open))|(?:;\\s*rm\\s+-\\w+\\s+)|(?:;.*{.*\\$\\w+\\s*=)|(?:\\$\\w+\\s*\\[\\]\\s*=\\s*)",
+ "description":"Detects code injection attempts 3\/3",
+ "tags":{
+ "tag":[
+ "id",
+ "rfe",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"62",
+ "rule":"(?:function[^(]*\\([^)]*\\))|(?:(?:delete|void|throw|instanceof|new|typeof)[^\\w.]+\\w+\\s*[([])|([)\\]]\\s*\\.\\s*\\w+\\s*=)|(?:\\(\\s*new\\s+\\w+\\s*\\)\\.)",
+ "description":"Detects common function declarations and special JS operators",
+ "tags":{
+ "tag":[
+ "id",
+ "rfe",
+ "lfi"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"63",
+ "rule":"(?:[\\w.-]+@[\\w.-]+%(?:[01][\\db-ce-f])+\\w+:)",
+ "description":"Detects common mail header injections",
+ "tags":{
+ "tag":[
+ "id",
+ "spam"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"64",
+ "rule":"(?:\\.pl\\?\\w+=\\w?\\|\\w+;)|(?:\\|\\(\\w+=\\*)|(?:\\*\\s*\\)+\\s*;)",
+ "description":"Detects perl echo shellcode injection and LDAP vectors",
+ "tags":{
+ "tag":[
+ "lfi",
+ "rfe"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"65",
+ "rule":"(?:(^|\\W)const\\s+[\\w\\-]+\\s*=)|(?:(?:do|for|while)\\s*\\([^;]+;+\\))|(?:(?:^|\\W)on\\w+\\s*=[\\w\\W]*(?:on\\w+|alert|eval|print|confirm|prompt))|(?:groups=\\d+\\(\\w+\\))|(?:(.)\\1{128,})",
+ "description":"Detects basic XSS DoS attempts",
+ "tags":{
+ "tag":[
+ "rfe",
+ "dos"
+ ]
+ },
+ "impact":"5"
+ },
+ {
+ "id":"67",
+ "rule":"(?:\\({2,}\\+{2,}:{2,})|(?:\\({2,}\\+{2,}:+)|(?:\\({3,}\\++:{2,})|(?:\\$\\[!!!\\])",
+ "description":"Detects unknown attack vectors based on PHPIDS Centrifuge detection",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf",
+ "id",
+ "rfe",
+ "lfi"
+ ]
+ },
+ "impact":"7"
+ },
+ {
+ "id":"68",
+ "rule":"(?:[\\s\\\/\"]+[-\\w\\\/\\\\\\*]+\\s*=.+(?:\\\/\\s*>))",
+ "description":"Finds attribute breaking injections including obfuscated attributes",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"69",
+ "rule":"(?:(?:msgbox|eval)\\s*\\+|(?:language\\s*=\\*vbscript))",
+ "description":"Finds basic VBScript injection attempts",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"70",
+ "rule":"(?:\\[\\$(?:ne|eq|lte?|gte?|n?in|mod|all|size|exists|type|slice|or)\\])",
+ "description":"Finds basic MongoDB SQL injection attempts",
+ "tags":{
+ "tag":"sqli"
+ },
+ "impact":"4"
+ },
+ {
+ "id":"71",
+ "rule":"(?:[\\s\\d\\\/\"]+(?:on\\w+|style|poster|background)=[$\"\\w])|(?:-type\\s*:\\s*multipart)",
+ "description":"Finds malicious attribute injection attempts and MHTML attacks",
+ "tags":{
+ "tag":[
+ "xss",
+ "csrf"
+ ]
+ },
+ "impact":"6"
+ },
+ {
+ "id":"72",
+ "rule":"(?:(sleep\\((\\s*)(\\d*)(\\s*)\\)|benchmark\\((.*)\\,(.*)\\)))",
+ "description":"Detects blind sqli tests using sleep() or benchmark().",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"73",
+ "rule":"(?:(\\%SYSTEMROOT\\%))",
+ "description":"An attacker is trying to locate a file to read or write.",
+ "tags":{
+ "tag":[
+ "files",
+ "id"
+ ]
+ },
+ "impact":"4"
+ },
+ {
+ "id":"75",
+ "rule":"(?:(((.*)\\%[c|d|i|e|f|g|o|s|u|x|p|n]){8}))",
+ "description":"Looking for a format string attack",
+ "tags":{
+ "tag":"format string"
+ },
+ "impact":"4"
+ },
+ {
+ "id":"76",
+ "rule":"(?:(union(.*)select(.*)from))",
+ "description":"Looking for basic sql injection. Common attack string for mysql, oracle and others.",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"3"
+ },
+ {
+ "id":"77",
+ "rule":"(?:^(-0000023456|4294967295|4294967296|2147483648|2147483647|0000012345|-2147483648|-2147483649|0000023456|2.2250738585072007e-308|1e309)$)",
+ "description":"Looking for integer overflow attacks, these are taken from skipfish, except 2.2250738585072007e-308 is the \"magic number\" crash",
+ "tags":{
+ "tag":[
+ "sqli",
+ "id"
+ ]
+ },
+ "impact":"3"
+ },
+ {
+ "id":"78",
+ "rule":"(?:%23.*?%0a)",
+ "description":"Detects SQL comment filter evasion",
+ "tags":{
+ "tag":[
+ "format string"
+ ]
+ },
+ "impact":"4"
+ }
+ ]
+ }
+}
diff --git a/interface/lib/classes/IDS/default_filter.xml b/interface/lib/classes/IDS/default_filter.xml
new file mode 100644
index 0000000..fdd9cef
--- /dev/null
+++ b/interface/lib/classes/IDS/default_filter.xml
@@ -0,0 +1,787 @@
+<filters>
+ <filter>
+ <id>1</id>
+ <rule><![CDATA[(?:"[^"]*[^-]?>)|(?:[^\w\s]\s*\/>)|(?:>")]]></rule>
+ <description>Finds html breaking injections including whitespace attacks</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>2</id>
+ <rule><![CDATA[(?:"+.*[<=]\s*"[^"]+")|(?:"\s*\w+\s*=)|(?:>\w=\/)|(?:#.+\)["\s]*>)|(?:"\s*(?:src|style|on\w+)\s*=\s*")|(?:[^"]?"[,;\s]+\w*[\[\(])]]></rule>
+ <description>Finds attribute breaking injections including whitespace attacks</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>3</id>
+ <rule><![CDATA[(?:^>[\w\s]*<\/?\w{2,}>)]]></rule>
+ <description>Finds unquoted attribute breaking injections</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>2</impact>
+ </filter>
+ <filter>
+ <id>4</id>
+ <rule><![CDATA[(?:[+\/]\s*name[\W\d]*[)+])|(?:;\W*url\s*=)|(?:[^\w\s\/?:>]\s*(?:location|referrer|name)\s*[^\/\w\s-])]]></rule>
+ <description>Detects url-, name-, JSON, and referrer-contained payload attacks</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>5</id>
+ <rule><![CDATA[(?:\W\s*hash\s*[^\w\s-])|(?:\w+=\W*[^,]*,[^\s(]\s*\()|(?:\?"[^\s"]":)|(?:(?<!\/)__[a-z]+__)|(?:(?:^|[\s)\]\}])(?:s|g)etter\s*=)]]></rule>
+ <description>Detects hash-contained xss payload attacks, setter usage and property overloading</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>6</id>
+ <rule><![CDATA[(?:with\s*\(\s*.+\s*\)\s*\w+\s*\()|(?:(?:do|while|for)\s*\([^)]*\)\s*\{)|(?:\/[\w\s]*\[\W*\w)]]></rule>
+ <description>Detects self contained xss via with(), common loops and regex to string conversion</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>7</id>
+ <rule><![CDATA[(?:[=(].+\?.+:)|(?:with\([^)]*\)\))|(?:\.\s*source\W)]]></rule>
+ <description>Detects JavaScript with(), ternary operators and XML predicate attacks</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>8</id>
+ <rule><![CDATA[(?:\/\w*\s*\)\s*\()|(?:\([\w\s]+\([\w\s]+\)[\w\s]+\))|(?:(?<!(?:mozilla\/\d\.\d\s))\([^)[]+\[[^\]]+\][^)]*\))|(?:[^\s!][{([][^({[]+[{([][^}\])]+[}\])][\s+",\d]*[}\])])|(?:"\)?\]\W*\[)|(?:=\s*[^\s:;]+\s*[{([][^}\])]+[}\])];)]]></rule>
+ <description>Detects self-executing JavaScript functions</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>9</id>
+ <rule><![CDATA[(?:\\u00[a-f0-9]{2})|(?:\\x0*[a-f0-9]{2})|(?:\\\d{2,3})]]></rule>
+ <description>Detects the IE octal, hex and unicode entities</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>2</impact>
+ </filter>
+ <filter>
+ <id>10</id>
+ <rule><![CDATA[(?:(?:\/|\\)?\.+(\/|\\)(?:\.+)?)|(?:\w+\.exe\??\s)|(?:;\s*\w+\s*\/[\w*-]+\/)|(?:\d\.\dx\|)|(?:%(?:c0\.|af\.|5c\.))|(?:\/(?:%2e){2})]]></rule>
+ <description>Detects basic directory traversal</description>
+ <tags>
+ <tag>dt</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>11</id>
+ <rule><![CDATA[(?:%c0%ae\/)|(?:(?:\/|\\)(home|conf|usr|etc|proc|opt|s?bin|local|dev|tmp|kern|[br]oot|sys|system|windows|winnt|program|%[a-z_-]{3,}%)(?:\/|\\))|(?:(?:\/|\\)inetpub|localstart\.asp|boot\.ini)]]></rule>
+ <description>Detects specific directory and path traversal</description>
+ <tags>
+ <tag>dt</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>12</id>
+ <rule><![CDATA[(?:etc\/\W*passwd)]]></rule>
+ <description>Detects etc/passwd inclusion attempts</description>
+ <tags>
+ <tag>dt</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>13</id>
+ <rule><![CDATA[(?:%u(?:ff|00|e\d)\w\w)|(?:(?:%(?:e\w|c[^3\W]|))(?:%\w\w)(?:%\w\w)?)]]></rule>
+ <description>Detects halfwidth/fullwidth encoded unicode HTML breaking attempts</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>3</impact>
+ </filter>
+ <filter>
+ <id>14</id>
+ <rule><![CDATA[(?:#@~\^\w+)|(?:\w+script:|@import[^\w]|;base64|base64,)|(?:\w\s*\([\w\s]+,[\w\s]+,[\w\s]+,[\w\s]+,[\w\s]+,[\w\s]+\))]]></rule>
+ <description>Detects possible includes, VBSCript/JScript encodeed and packed functions</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>15</id>
+ <rule><![CDATA[([^*:\s\w,.\/?+-]\s*)?(?<![a-z]\s)(?<![a-z\/_@\-\|])(\s*return\s*)?(?:create(?:element|attribute|textnode)|[a-z]+events?|setattribute|getelement\w+|appendchild|createrange|createcontextualfragment|removenode|parentnode|decodeuricomponent|\wettimeout|(?:ms)?setimmediate|option|useragent)(?(1)[^\w%"]|(?:\s*[^@\s\w%",.+\-]))]]></rule>
+ <description>Detects JavaScript DOM/miscellaneous properties and methods</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>16</id>
+ <rule><![CDATA[([^*\s\w,.\/?+-]\s*)?(?<![a-mo-z]\s)(?<![a-z\/_@])(\s*return\s*)?(?:alert|inputbox|showmod(?:al|eless)dialog|showhelp|infinity|isnan|isnull|iterator|msgbox|executeglobal|expression|prompt|write(?:ln)?|confirm|dialog|urn|(?:un)?eval|exec|execscript|tostring|status|execute|window|unescape|navigate|jquery|getscript|extend|prototype)(?(1)[^\w%"]|(?:\s*[^@\s\w%",.:\/+\-]))]]></rule>
+ <description>Detects possible includes and typical script methods</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>17</id>
+ <rule><![CDATA[([^*:\s\w,.\/?+-]\s*)?(?<![a-z]\s)(?<![a-z\/_@])(\s*return\s*)?(?:hash|name|href|navigateandfind|source|pathname|close|constructor|port|protocol|assign|replace|back|forward|document|ownerdocument|window|top|this|self|parent|frames|_?content|date|cookie|innerhtml|innertext|csstext+?|outerhtml|print|moveby|resizeto|createstylesheet|stylesheets)(?(1)[^\w%"]|(?:\s*[^@\/\s\w%.+\-]))]]></rule>
+ <description>Detects JavaScript object properties and methods</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>18</id>
+ <rule><![CDATA[([^*:\s\w,.\/?+-]\s*)?(?<![a-z]\s)(?<![a-z\/_@\-\|])(\s*return\s*)?(?:join|pop|push|reverse|reduce|concat|map|shift|sp?lice|sort|unshift)(?(1)[^\w%"]|(?:\s*[^@\s\w%,.+\-]))]]></rule>
+ <description>Detects JavaScript array properties and methods</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>19</id>
+ <rule><![CDATA[([^*:\s\w,.\/?+-]\s*)?(?<![a-z]\s)(?<![a-z\/_@\-\|])(\s*return\s*)?(?:set|atob|btoa|charat|charcodeat|charset|concat|crypto|frames|fromcharcode|indexof|lastindexof|match|navigator|toolbar|menubar|replace|regexp|slice|split|substr|substring|escape|\w+codeuri\w*)(?(1)[^\w%"]|(?:\s*[^@\s\w%,.+\-]))]]></rule>
+ <description>Detects JavaScript string properties and methods</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>20</id>
+ <rule><![CDATA[(?:\)\s*\[)|([^*":\s\w,.\/?+-]\s*)?(?<![a-z]\s)(?<![a-z_@\|])(\s*return\s*)?(?:globalstorage|sessionstorage|postmessage|callee|constructor|content|domain|prototype|try|catch|top|call|apply|url|function|object|array|string|math|if|for\s*(?:each)?|elseif|case|switch|regex|boolean|location|(?:ms)?setimmediate|settimeout|setinterval|void|setexpression|namespace|while)(?(1)[^\w%"]|(?:\s*[^@\s\w%".+\-\/]))]]></rule>
+ <description>Detects JavaScript language constructs</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>21</id>
+ <rule><![CDATA[(?:,\s*(?:alert|showmodaldialog|eval)\s*,)|(?::\s*eval\s*[^\s])|([^:\s\w,.\/?+-]\s*)?(?<![a-z\/_@])(\s*return\s*)?(?:(?:document\s*\.)?(?:.+\/)?(?:alert|eval|msgbox|showmod(?:al|eless)dialog|showhelp|prompt|write(?:ln)?|confirm|dialog|open))\s*(?:[^.a-z\s\-]|(?:\s*[^\s\w,.@\/+-]))|(?:java[\s\/]*\.[\s\/]*lang)|(?:\w\s*=\s*new\s+\w+)|(?:&\s*\w+\s*\)[^,])|(?:\+[\W\d]*new\s+\w+[\W\d]*\+)|(?:document\.\w)]]></rule>
+ <description>Detects very basic XSS probings</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>3</impact>
+ </filter>
+ <filter>
+ <id>22</id>
+ <rule><![CDATA[(?:=\s*(?:top|this|window|content|self|frames|_content))|(?:\/\s*[gimx]*\s*[)}])|(?:[^\s]\s*=\s*script)|(?:\.\s*constructor)|(?:default\s+xml\s+namespace\s*=)|(?:\/\s*\+[^+]+\s*\+\s*\/)]]></rule>
+ <description>Detects advanced XSS probings via Script(), RexExp, constructors and XML namespaces</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>23</id>
+ <rule><![CDATA[(?:\.\s*\w+\W*=)|(?:\W\s*(?:location|document)\s*\W[^({[;]+[({[;])|(?:\(\w+\?[:\w]+\))|(?:\w{2,}\s*=\s*\d+[^&\w]\w+)|(?:\]\s*\(\s*\w+)]]></rule>
+ <description>Detects JavaScript location/document property access and window access obfuscation</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>24</id>
+ <rule><![CDATA[(?:[".]script\s*\()|(?:\$\$?\s*\(\s*[\w"])|(?:\/[\w\s]+\/\.)|(?:=\s*\/\w+\/\s*\.)|(?:(?:this|window|top|parent|frames|self|content)\[\s*[(,"]*\s*[\w\$])|(?:,\s*new\s+\w+\s*[,;)])]]></rule>
+ <description>Detects basic obfuscated JavaScript script injections</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>25</id>
+ <rule><![CDATA[(?:=\s*[$\w]\s*[\(\[])|(?:\(\s*(?:this|top|window|self|parent|_?content)\s*\))|(?:src\s*=s*(?:\w+:|\/\/))|(?:\w+\[("\w+"|\w+\|\|))|(?:[\d\W]\|\|[\d\W]|\W=\w+,)|(?:\/\s*\+\s*[a-z"])|(?:=\s*\$[^([]*\()|(?:=\s*\(\s*")]]></rule>
+ <description>Detects obfuscated JavaScript script injections</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>26</id>
+ <rule><![CDATA[(?:[^:\s\w]+\s*[^\w\/](href|protocol|host|hostname|pathname|hash|port|cookie)[^\w])]]></rule>
+ <description>Detects JavaScript cookie stealing and redirection attempts</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>27</id>
+ <rule><![CDATA[(?:(?:vbs|vbscript|data):.*[,+])|(?:\w+\s*=\W*(?!https?)\w+:)|(jar:\w+:)|(=\s*"?\s*vbs(?:ript)?:)|(language\s*=\s?"?\s*vbs(?:ript)?)|on\w+\s*=\*\w+\-"?]]></rule>
+ <description>Detects data: URL injections, VBS injections and common URI schemes</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>28</id>
+ <rule><![CDATA[(?:firefoxurl:\w+\|)|(?:(?:file|res|telnet|nntp|news|mailto|chrome)\s*:\s*[%&#xu\/]+)|(wyciwyg|firefoxurl\s*:\s*\/\s*\/)]]></rule>
+ <description>Detects IE firefoxurl injections, cache poisoning attempts and local file inclusion/execution</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>29</id>
+ <rule><![CDATA[(?:binding\s?=|moz-binding|behavior\s?=)|(?:[\s\/]style\s*=\s*[-\\])]]></rule>
+ <description>Detects bindings and behavior injections</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>30</id>
+ <rule><![CDATA[(?:=\s*\w+\s*\+\s*")|(?:\+=\s*\(\s")|(?:!+\s*[\d.,]+\w?\d*\s*\?)|(?:=\s*\[s*\])|(?:"\s*\+\s*")|(?:[^\s]\[\s*\d+\s*\]\s*[;+])|(?:"\s*[&|]+\s*")|(?:\/\s*\?\s*")|(?:\/\s*\)\s*\[)|(?:\d\?.+:\d)|(?:]\s*\[\W*\w)|(?:[^\s]\s*=\s*\/)]]></rule>
+ <description>Detects common XSS concatenation patterns 1/2</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>31</id>
+ <rule><![CDATA[(?:=\s*\d*\.\d*\?\d*\.\d*)|(?:[|&]{2,}\s*")|(?:!\d+\.\d*\?")|(?:\/:[\w.]+,)|(?:=[\d\W\s]*\[[^]]+\])|(?:\?\w+:\w+)]]></rule>
+ <description>Detects common XSS concatenation patterns 2/2</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>32</id>
+ <rule><![CDATA[(?:[^\w\s=]on(?!g\>)\w+[^=_+-]*=[^$]+(?:\W|\>)?)]]></rule>
+ <description>Detects possible event handlers</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>33</id>
+ <rule><![CDATA[(?:\<\w*:?\s(?:[^\>]*)t(?!rong))|(?:\<scri)|(<\w+:\w+)]]></rule>
+ <description>Detects obfuscated script tags and XML wrapped HTML</description>
+ <tags>
+ <tag>xss</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>34</id>
+ <rule><![CDATA[(?:\<\/\w+\s\w+)|(?:@(?:cc_on|set)[\s@,"=])]]></rule>
+ <description>Detects attributes in closing tags and conditional compilation tokens</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>35</id>
+ <rule><![CDATA[(?:--[^\n]*$)|(?:\<!-|-->)|(?:[^*]\/\*|\*\/[^*])|(?:(?:[\W\d]#|--|{)$)|(?:\/{3,}.*$)|(?:<!\[\W)|(?:\]!>)]]></rule>
+ <description>Detects common comment types</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>3</impact>
+ </filter>
+ <filter>
+ <id>37</id>
+ <rule><![CDATA[(?:\<base\s+)|(?:<!(?:element|entity|\[CDATA))]]></rule>
+ <description>Detects base href injections and XML entity injections</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>38</id>
+ <rule><![CDATA[(?:\<[\/]?(?:[i]?frame|applet|isindex|marquee|keygen|script|audio|video|input|button|textarea|style|base|body|meta|link|object|embed|param|plaintext|xm\w+|image|im(?:g|port)))]]></rule>
+ <description>Detects possibly malicious html elements including some attributes</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>39</id>
+ <rule><![CDATA[(?:\\x[01fe][\db-ce-f])|(?:%[01fe][\db-ce-f])|(?:&#[01fe][\db-ce-f])|(?:\\[01fe][\db-ce-f])|(?:&#x[01fe][\db-ce-f])]]></rule>
+ <description>Detects nullbytes and other dangerous characters</description>
+ <tags>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>xss</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>40</id>
+ <rule><![CDATA[(?:\)\s*when\s*\d+\s*then)|(?:"\s*(?:#|--|{))|(?:\/\*!\s?\d+)|(?:ch(?:a)?r\s*\(\s*\d)|(?:(?:(n?and|x?or|not)\s+|\|\||\&\&)\s*\w+\()]]></rule>
+ <description>Detects MySQL comments, conditions and ch(a)r injections</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>41</id>
+ <rule><![CDATA[(?:[\s()]case\s*\()|(?:\)\s*like\s*\()|(?:having\s*[^\s]+\s*[^\w\s])|(?:if\s?\([\d\w]\s*[=<>~])]]></rule>
+ <description>Detects conditional SQL injection attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>42</id>
+ <rule><![CDATA[(?:"\s*or\s*"?\d)|(?:\\x(?:23|27|3d))|(?:^.?"$)|(?:(?:^["\\]*(?:[\d"]+|[^"]+"))+\s*(?:n?and|x?or|not|\|\||\&\&)\s*[\w"[+&!@(),.-])|(?:[^\w\s]\w+\s*[|-]\s*"\s*\w)|(?:@\w+\s+(and|or)\s*["\d]+)|(?:@[\w-]+\s(and|or)\s*[^\w\s])|(?:[^\w\s:]\s*\d\W+[^\w\s]\s*".)|(?:\Winformation_schema|table_name\W)]]></rule>
+ <description>Detects classic SQL injection probings 1/2</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>43</id>
+ <rule><![CDATA[(?:"\s*\*.+(?:or|id)\W*"\d)|(?:\^")|(?:^[\w\s"-]+(?<=and\s)(?<=or\s)(?<=xor\s)(?<=nand\s)(?<=not\s)(?<=\|\|)(?<=\&\&)\w+\()|(?:"[\s\d]*[^\w\s]+\W*\d\W*.*["\d])|(?:"\s*[^\w\s?]+\s*[^\w\s]+\s*")|(?:"\s*[^\w\s]+\s*[\W\d].*(?:#|--))|(?:".*\*\s*\d)|(?:"\s*or\s[^\d]+[\w-]+.*\d)|(?:[()*<>%+-][\w-]+[^\w\s]+"[^,])]]></rule>
+ <description>Detects classic SQL injection probings 2/2</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>44</id>
+ <rule><![CDATA[(?:\d"\s+"\s+\d)|(?:^admin\s*"|(\/\*)+"+\s?(?:--|#|\/\*|{)?)|(?:"\s*or[\w\s-]+\s*[+<>=(),-]\s*[\d"])|(?:"\s*[^\w\s]?=\s*")|(?:"\W*[+=]+\W*")|(?:"\s*[!=|][\d\s!=+-]+.*["(].*$)|(?:"\s*[!=|][\d\s!=]+.*\d+$)|(?:"\s*like\W+[\w"(])|(?:\sis\s*0\W)|(?:where\s[\s\w\.,-]+\s=)|(?:"[<>~]+")]]></rule>
+ <description>Detects basic SQL authentication bypass attempts 1/3</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>45</id>
+ <rule><![CDATA[(?:union\s*(?:all|distinct|[(!@]*)\s*[([]*\s*select)|(?:\w+\s+like\s+\")|(?:like\s*"\%)|(?:"\s*like\W*["\d])|(?:"\s*(?:n?and|x?or|not |\|\||\&\&)\s+[\s\w]+=\s*\w+\s*having)|(?:"\s*\*\s*\w+\W+")|(?:"\s*[^?\w\s=.,;)(]+\s*[(@"]*\s*\w+\W+\w)|(?:select\s*[\[\]()\s\w\.,"-]+from)|(?:find_in_set\s*\()]]></rule>
+ <description>Detects basic SQL authentication bypass attempts 2/3</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>46</id>
+ <rule><![CDATA[(?:in\s*\(+\s*select)|(?:(?:n?and|x?or|not |\|\||\&\&)\s+[\s\w+]+(?:regexp\s*\(|sounds\s+like\s*"|[=\d]+x))|("\s*\d\s*(?:--|#))|(?:"[%&<>^=]+\d\s*(=|or))|(?:"\W+[\w+-]+\s*=\s*\d\W+")|(?:"\s*is\s*\d.+"?\w)|(?:"\|?[\w-]{3,}[^\w\s.,]+")|(?:"\s*is\s*[\d.]+\s*\W.*")]]></rule>
+ <description>Detects basic SQL authentication bypass attempts 3/3</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>47</id>
+ <rule><![CDATA[(?:[\d\W]\s+as\s*["\w]+\s*from)|(?:^[\W\d]+\s*(?:union|select|create|rename|truncate|load|alter|delete|update|insert|desc))|(?:(?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\s+(?:(?:group_)concat|char|load_file)\s?\(?)|(?:end\s*\);)|("\s+regexp\W)|(?:[\s(]load_file\s*\()]]></rule>
+ <description>Detects concatenated basic SQL injection and SQLLFI attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>48</id>
+ <rule><![CDATA[(?:@.+=\s*\(\s*select)|(?:\d+\s*or\s*\d+\s*[\-+])|(?:\/\w+;?\s+(?:having|and|or|select)\W)|(?:\d\s+group\s+by.+\()|(?:(?:;|#|--)\s*(?:drop|alter))|(?:(?:;|#|--)\s*(?:update|insert)\s*\w{2,})|(?:[^\w]SET\s*@\w+)|(?:(?:n?and|x?or|not |\|\||\&\&)[\s(]+\w+[\s)]*[!=+]+[\s\d]*["=()])]]></rule>
+ <description>Detects chained SQL injection attempts 1/2</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>49</id>
+ <rule><![CDATA[(?:"\s+and\s*=\W)|(?:\(\s*select\s*\w+\s*\()|(?:\*\/from)|(?:\+\s*\d+\s*\+\s*@)|(?:\w"\s*(?:[-+=|@]+\s*)+[\d(])|(?:coalesce\s*\(|@@\w+\s*[^\w\s])|(?:\W!+"\w)|(?:";\s*(?:if|while|begin))|(?:"[\s\d]+=\s*\d)|(?:order\s+by\s+if\w*\s*\()|(?:[\s(]+case\d*\W.+[tw]hen[\s(])]]></rule>
+ <description>Detects chained SQL injection attempts 2/2</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>50</id>
+ <rule><![CDATA[(?:(select|;)\s+(?:benchmark|if|sleep)\s*?\(\s*\(?\s*\w+)]]></rule>
+ <description>Detects SQL benchmark and sleep injection attempts including conditional queries</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>51</id>
+ <rule><![CDATA[(?:create\s+function\s+\w+\s+returns)|(?:;\s*(?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\s*[\[(]?\w{2,})]]></rule>
+ <description>Detects MySQL UDF injection and other data/structure manipulation attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>52</id>
+ <rule><![CDATA[(?:alter\s*\w+.*character\s+set\s+\w+)|(";\s*waitfor\s+time\s+")|(?:";.*:\s*goto)]]></rule>
+ <description>Detects MySQL charset switch and MSSQL DoS attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>53</id>
+ <rule><![CDATA[(?:procedure\s+analyse\s*\()|(?:;\s*(declare|open)\s+[\w-]+)|(?:create\s+(procedure|function)\s*\w+\s*\(\s*\)\s*-)|(?:declare[^\w]+[@#]\s*\w+)|(exec\s*\(\s*@)]]></rule>
+ <description>Detects MySQL and PostgreSQL stored procedure/function injections</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>54</id>
+ <rule><![CDATA[(?:select\s*pg_sleep)|(?:waitfor\s*delay\s?"+\s?\d)|(?:;\s*shutdown\s*(?:;|--|#|\/\*|{))]]></rule>
+ <description>Detects Postgres pg_sleep injection, waitfor delay attacks and database shutdown attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>55</id>
+ <rule><![CDATA[(?:\sexec\s+xp_cmdshell)|(?:"\s*!\s*["\w])|(?:from\W+information_schema\W)|(?:(?:(?:current_)?user|database|schema|connection_id)\s*\([^\)]*)|(?:";?\s*(?:select|union|having)\s*[^\s])|(?:\wiif\s*\()|(?:exec\s+master\.)|(?:union select @)|(?:union[\w(\s]*select)|(?:select.*\w?user\()|(?:into[\s+]+(?:dump|out)file\s*")]]></rule>
+ <description>Detects MSSQL code execution and information gathering attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>56</id>
+ <rule><![CDATA[(?:merge.*using\s*\()|(execute\s*immediate\s*")|(?:\W+\d*\s*having\s*[^\s\-])|(?:match\s*[\w(),+-]+\s*against\s*\()]]></rule>
+ <description>Detects MATCH AGAINST, MERGE, EXECUTE IMMEDIATE and HAVING injections</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>57</id>
+ <rule><![CDATA[(?:,.*[)\da-f"]"(?:".*"|\Z|[^"]+))|(?:\Wselect.+\W*from)|((?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\s*\(\s*space\s*\()]]></rule>
+ <description>Detects MySQL comment-/space-obfuscated injections and backtick termination</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>58</id>
+ <rule><![CDATA[(?:@[\w-]+\s*\()|(?:]\s*\(\s*["!]\s*\w)|(?:<[?%](?:php)?.*(?:[?%]>)?)|(?:;[\s\w|]*\$\w+\s*=)|(?:\$\w+\s*=(?:(?:\s*\$?\w+\s*[(;])|\s*".*"))|(?:;\s*\{\W*\w+\s*\()]]></rule>
+ <description>Detects code injection attempts 1/3</description>
+ <tags>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>59</id>
+ <rule><![CDATA[(?:(?:[;]+|(<[?%](?:php)?)).*(?:define|eval|file_get_contents|include|require|require_once|set|shell_exec|phpinfo|system|passthru|preg_\w+|execute)\s*["(@])]]></rule>
+ <description>Detects code injection attempts 2/3</description>
+ <tags>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>60</id>
+ <rule><![CDATA[(?:(?:[;]+|(<[?%](?:php)?)).*[^\w](?:echo|print|print_r|var_dump|[fp]open))|(?:;\s*rm\s+-\w+\s+)|(?:;.*{.*\$\w+\s*=)|(?:\$\w+\s*\[\]\s*=\s*)]]></rule>
+ <description>Detects code injection attempts 3/3</description>
+ <tags>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>62</id>
+ <rule><![CDATA[(?:function[^(]*\([^)]*\))|(?:(?:delete|void|throw|instanceof|new|typeof)[^\w.]+\w+\s*[([])|([)\]]\s*\.\s*\w+\s*=)|(?:\(\s*new\s+\w+\s*\)\.)]]></rule>
+ <description>Detects common function declarations and special JS operators</description>
+ <tags>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>63</id>
+ <rule><![CDATA[(?:[\w.-]+@[\w.-]+%(?:[01][\db-ce-f])+\w+:)]]></rule>
+ <description>Detects common mail header injections</description>
+ <tags>
+ <tag>id</tag>
+ <tag>spam</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>64</id>
+ <rule><![CDATA[(?:\.pl\?\w+=\w?\|\w+;)|(?:\|\(\w+=\*)|(?:\*\s*\)+\s*;)]]></rule>
+ <description>Detects perl echo shellcode injection and LDAP vectors</description>
+ <tags>
+ <tag>lfi</tag>
+ <tag>rfe</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>65</id>
+ <rule><![CDATA[(?:(^|\W)const\s+[\w\-]+\s*=)|(?:(?:do|for|while)\s*\([^;]+;+\))|(?:(?:^|\W)on\w+\s*=[\w\W]*(?:on\w+|alert|eval|print|confirm|prompt))|(?:groups=\d+\(\w+\))|(?:(.)\1{128,})]]></rule>
+ <description>Detects basic XSS DoS attempts</description>
+ <tags>
+ <tag>rfe</tag>
+ <tag>dos</tag>
+ </tags>
+ <impact>5</impact>
+ </filter>
+ <filter>
+ <id>67</id>
+ <rule><![CDATA[(?:\({2,}\+{2,}:{2,})|(?:\({2,}\+{2,}:+)|(?:\({3,}\++:{2,})|(?:\$\[!!!\])]]></rule>
+ <description>Detects unknown attack vectors based on PHPIDS Centrifuge detection</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ <tag>id</tag>
+ <tag>rfe</tag>
+ <tag>lfi</tag>
+ </tags>
+ <impact>7</impact>
+ </filter>
+ <filter>
+ <id>68</id>
+ <rule><![CDATA[(?:[\s\/"]+[-\w\/\\\*]+\s*=.+(?:\/\s*>))]]></rule>
+ <description>Finds attribute breaking injections including obfuscated attributes</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>69</id>
+ <rule><![CDATA[(?:(?:msgbox|eval)\s*\+|(?:language\s*=\*vbscript))]]></rule>
+ <description>Finds basic VBScript injection attempts</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>70</id>
+ <rule><![CDATA[(?:\[\$(?:ne|eq|lte?|gte?|n?in|mod|all|size|exists|type|slice|or)\])]]></rule>
+ <description>Finds basic MongoDB SQL injection attempts</description>
+ <tags>
+ <tag>sqli</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>71</id>
+ <rule><![CDATA[(?:[\s\d\/"]+(?:on\w+|style|poster|background)=[$"\w])|(?:-type\s*:\s*multipart)]]></rule>
+ <description>Finds malicious attribute injection attempts and MHTML attacks</description>
+ <tags>
+ <tag>xss</tag>
+ <tag>csrf</tag>
+ </tags>
+ <impact>6</impact>
+ </filter>
+ <filter>
+ <id>72</id>
+ <rule><![CDATA[(?:(sleep\((\s*)(\d*)(\s*)\)|benchmark\((.*)\,(.*)\)))]]></rule>
+ <description>Detects blind sqli tests using sleep() or benchmark().</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>73</id>
+ <rule><![CDATA[(?:(\%SYSTEMROOT\%))]]></rule>
+ <description>An attacker is trying to locate a file to read or write.</description>
+ <tags>
+ <tag>files</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>75</id>
+ <rule><![CDATA[(?:(((.*)\%[c|d|i|e|f|g|o|s|u|x|p|n]){8}))]]></rule>
+ <description>Looking for a format string attack</description>
+ <tags>
+ <tag>format string</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+ <filter>
+ <id>76</id>
+ <rule><![CDATA[(?:(union(.*)select(.*)from))]]></rule>
+ <description>Looking for basic sql injection. Common attack string for mysql, oracle and others.</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>3</impact>
+ </filter>
+ <filter>
+ <id>77</id>
+ <rule><![CDATA[(?:^(-0000023456|4294967295|4294967296|2147483648|2147483647|0000012345|-2147483648|-2147483649|0000023456|2.2250738585072007e-308|1e309)$)]]></rule>
+ <description>Looking for integer overflow attacks, these are taken from skipfish, except 2.2250738585072007e-308 is the "magic number" crash</description>
+ <tags>
+ <tag>sqli</tag>
+ <tag>id</tag>
+ </tags>
+ <impact>3</impact>
+ </filter>
+ <filter>
+ <id>78</id>
+ <rule><![CDATA[(?:%23.*?%0a)]]></rule>
+ <description>Detects SQL comment filter evasion</description>
+ <tags>
+ <tag>format string</tag>
+ </tags>
+ <impact>4</impact>
+ </filter>
+</filters>
diff --git a/interface/lib/classes/IDS/license.txt b/interface/lib/classes/IDS/license.txt
new file mode 100644
index 0000000..4a3cd1b
--- /dev/null
+++ b/interface/lib/classes/IDS/license.txt
@@ -0,0 +1,18 @@
+ *
+ * The files in the folder IDS and its subfolders belong to the
+ * PHP Intrusion Detection System software and are licensed under LGPL.
+ *
+ * Copyright (c) 2008 PHPIDS group (https://phpids.org)
+ *
+ * PHPIDS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PHPIDS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
\ No newline at end of file
diff --git a/interface/lib/classes/db_mysql.inc.php b/interface/lib/classes/db_mysql.inc.php
index 56d43f8..b96b8d0 100644
--- a/interface/lib/classes/db_mysql.inc.php
+++ b/interface/lib/classes/db_mysql.inc.php
@@ -121,6 +121,52 @@
parent::query( 'SET NAMES '.$this->dbCharset);
parent::query( "SET character_set_results = '".$this->dbCharset."', character_set_client = '".$this->dbCharset."', character_set_connection = '".$this->dbCharset."', character_set_database = '".$this->dbCharset."', character_set_server = '".$this->dbCharset."'");
}
+
+ private function securityScan($string) {
+ global $app, $conf;
+
+ // get security config
+ if(isset($app)) {
+ $app->uses('getconf');
+ $ids_config = $app->getconf->get_security_config('ids');
+
+ if($ids_config['sql_scan_enabled'] == 'yes') {
+
+ $string_orig = $string;
+
+ //echo $string;
+ $chars = array(';', '#', '/*', '*/', '--', ' UNION ', '\\\'', '\\"');
+
+ $string = str_replace('\\\\', '', $string);
+ $string = preg_replace('/(^|[^\\\])([\'"])(.*?[^\\\])\\2/is', '$1', $string);
+ $ok = true;
+
+ if(substr_count($string, "`") % 2 != 0 || substr_count($string, "'") % 2 != 0 || substr_count($string, '"') % 2 != 0) {
+ $app->log("SQL injection warning (" . $string_orig . ")",2);
+ $ok = false;
+ } else {
+ foreach($chars as $char) {
+ if(strpos($string, $char) !== false) {
+ $ok = false;
+ $app->log("SQL injection warning (" . $string_orig . ")",2);
+ break;
+ }
+ }
+ }
+ if($ok == true) {
+ return true;
+ } else {
+ if($ids_config['sql_scan_action'] == 'warn') {
+ // we return false in warning level.
+ return false;
+ } else {
+ // if sql action = 'block' or anything else then stop here.
+ $app->error('Possible SQL injection. All actions have been logged.');
+ }
+ }
+ }
+ }
+ }
public function query($queryString) {
global $conf;
@@ -143,6 +189,7 @@
}
}
} while($ok == false);
+ $this->securityScan($queryString);
$this->queryId = parent::query($queryString);
$this->updateError('DB::query('.$queryString.') -> mysqli_query');
if($this->errorNumber && $conf['demo_mode'] === false) debug_print_backtrace();
diff --git a/interface/lib/classes/getconf.inc.php b/interface/lib/classes/getconf.inc.php
index 5cc223a..0cc282e 100644
--- a/interface/lib/classes/getconf.inc.php
+++ b/interface/lib/classes/getconf.inc.php
@@ -31,6 +31,7 @@
class getconf {
private $config;
+ private $security_config;
public function get_server_config($server_id, $section = '') {
global $app;
@@ -55,15 +56,20 @@
return ($section == '') ? $this->config['global'] : $this->config['global'][$section];
}
+ // Function has been moved to $app->get_security_config($section)
public function get_security_config($section = '') {
global $app;
+
+ if(is_array($this->security_config)) {
+ return ($section == '') ? $this->security_config : $this->security_config[$section];
+ } else {
+ $this->uses('ini_parser');
+ $security_config_path = '/usr/local/ispconfig/security/security_settings.ini';
+ if(!is_file($security_config_path)) $security_config_path = realpath(ISPC_ROOT_PATH.'/../security/security_settings.ini');
+ $this->security_config = $this->ini_parser->parse_ini_string(file_get_contents($security_config_path));
- $app->uses('ini_parser');
- $security_config_path = '/usr/local/ispconfig/security/security_settings.ini';
- if(!is_file($security_config_path)) $security_config_path = realpath(ISPC_ROOT_PATH.'/../security/security_settings.ini');
- $security_config = $app->ini_parser->parse_ini_string(file_get_contents($security_config_path));
-
- return ($section == '') ? $security_config : $security_config[$section];
+ return ($section == '') ? $this->security_config : $this->security_config[$section];
+ }
}
}
diff --git a/interface/lib/classes/ids.inc.php b/interface/lib/classes/ids.inc.php
new file mode 100644
index 0000000..a98b0b2
--- /dev/null
+++ b/interface/lib/classes/ids.inc.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+Copyright (c) 2014, Till Brehm, ISPConfig UG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+class ids {
+
+ public function start()
+ {
+ global $app, $conf;
+
+ $security_config = $app->getconf->get_security_config('ids');
+
+ set_include_path(
+ get_include_path()
+ . PATH_SEPARATOR
+ . ISPC_CLASS_PATH.'/'
+ );
+
+ require_once(ISPC_CLASS_PATH.'/IDS/Init.php');
+ require_once(ISPC_CLASS_PATH.'/IDS/Monitor.php');
+ require_once(ISPC_CLASS_PATH.'/IDS/Filter.php');
+ require_once(ISPC_CLASS_PATH.'/IDS/Filter/Storage.php');
+ require_once(ISPC_CLASS_PATH.'/IDS/Report.php');
+ require_once(ISPC_CLASS_PATH.'/IDS/Event.php');
+ require_once(ISPC_CLASS_PATH.'/IDS/Converter.php');
+
+ $ids_request = array(
+ 'SESSION' => $_SESSION,
+ 'GET' => $_GET,
+ 'POST' => $_POST,
+ 'COOKIE' => $_COOKIE
+ );
+
+ $ids_init = IDS\Init::init(ISPC_CLASS_PATH.'/IDS/Config/Config.ini.php');
+
+ $ids_init->config['General']['base_path'] = ISPC_CLASS_PATH.'/IDS/';
+ $ids_init->config['General']['tmp_path'] = '../../../temp';
+ $ids_init->config['General']['use_base_path'] = true;
+ $ids_init->config['Caching']['caching'] = 'none';
+ $ids_init->config['Logging']['path'] = '../../../temp/ids.log';
+
+ $current_script_name = trim($_SERVER['SCRIPT_NAME']);
+
+ // Get whitelist
+ $whitelist_path = '/usr/local/ispconfig/security/ids.whitelist';
+ if(is_file('/usr/local/ispconfig/security/ids.whitelist.custom')) $whitelist_path = '/usr/local/ispconfig/security/ids.whitelist.custom';
+ if(!is_file($whitelist_path)) $whitelist_path = realpath(ISPC_ROOT_PATH.'/../security/ids.whitelist');
+
+ $whitelist_lines = file($whitelist_path);
+ if(is_array($whitelist_lines)) {
+ foreach($whitelist_lines as $line) {
+ $line = trim($line);
+ if(substr($line,0,1) != '#') {
+ list($user,$path,$varname) = explode(':',$line);
+ if($current_script_name == $path) {
+ if($user = 'any'
+ || ($user == 'user' && ($_SESSION['s']['user']['typ'] == 'user' || $_SESSION['s']['user']['typ'] == 'admin'))
+ || ($user == 'admin' && $_SESSION['s']['user']['typ'] == 'admin')) {
+ $ids_init->config['General']['exceptions'][] = $varname;
+
+ }
+ }
+ }
+ }
+ }
+
+ // Get HTML fields
+ $htmlfield_path = '/usr/local/ispconfig/security/ids.htmlfield';
+ if(is_file('/usr/local/ispconfig/security/ids.htmlfield.custom')) $htmlfield_path = '/usr/local/ispconfig/security/ids.htmlfield.custom';
+ if(!is_file($htmlfield_path)) $htmlfield_path = realpath(ISPC_ROOT_PATH.'/../security/ids.htmlfield');
+
+ $htmlfield_lines = file($htmlfield_path);
+ if(is_array($htmlfield_lines)) {
+ foreach($htmlfield_lines as $line) {
+ $line = trim($line);
+ if(substr($line,0,1) != '#') {
+ list($user,$path,$varname) = explode(':',$line);
+ if($current_script_name == $path) {
+ if($user = 'any'
+ || ($user == 'user' && ($_SESSION['s']['user']['typ'] == 'user' || $_SESSION['s']['user']['typ'] == 'admin'))
+ || ($user == 'admin' && $_SESSION['s']['user']['typ'] == 'admin')) {
+ $ids_init->config['General']['html'][] = $varname;
+ }
+ }
+ }
+ }
+ }
+
+ $ids = new IDS\Monitor($ids_init);
+ $ids_result = $ids->run($ids_request);
+
+ if (!$ids_result->isEmpty()) {
+
+ $impact = $ids_result->getImpact();
+
+ if($impact >= $security_config['ids_log_level']) {
+ $ids_log = ISPC_ROOT_PATH.'/temp/ids.log';
+ if(!is_file($ids_log)) touch($ids_log);
+
+ $user = isset($_SESSION['s']['user']['typ'])?$_SESSION['s']['user']['typ']:'any';
+
+ $log_lines = '';
+ foreach ($ids_result->getEvents() as $event) {
+ $log_lines .= $user.':'.$current_script_name.':'.$event->getName()."\n";
+ }
+ file_put_contents($ids_log,$log_lines,FILE_APPEND);
+
+ }
+
+ if($impact >= $security_config['ids_warn_level']) {
+ $app->log("PHP IDS Alert.".$ids_result, 2);
+ }
+
+ if($impact >= $security_config['ids_block_level']) {
+ $app->error("Possible attack detected. This action has been logged.",'', true, 2);
+ }
+
+ }
+ }
+
+}
+
+?>
diff --git a/security/apache_directives.blacklist b/security/apache_directives.blacklist
new file mode 100644
index 0000000..edb4b50
--- /dev/null
+++ b/security/apache_directives.blacklist
@@ -0,0 +1,3 @@
+/^\s*(LoadModule|LoadFile|Include)(\s+|[\\\\])/mi
+/^\s*(SuexecUserGroup|suPHP_UserGroup|suPHP_PHPPath|suPHP_ConfigPath)(\s+|[\\\\])/mi
+/^\s*(FCGIWrapper|FastCgiExternalServer)(\s+|[\\\\])/mi
\ No newline at end of file
diff --git a/security/ids.htmlfield b/security/ids.htmlfield
new file mode 100644
index 0000000..2c6e92a
--- /dev/null
+++ b/security/ids.htmlfield
@@ -0,0 +1,5 @@
+# Format: usertype:url_path:field
+# usertype can be: any/client/admin
+# Example:
+# admin:/admin/language_edit.php:POST.records.weak_password_txt
+admin:/admin/language_edit.php:POST.records
\ No newline at end of file
diff --git a/security/ids.whitelist b/security/ids.whitelist
new file mode 100644
index 0000000..58a96e6
--- /dev/null
+++ b/security/ids.whitelist
@@ -0,0 +1,45 @@
+# Format: usertype:url_path:field
+# usertype can be: any/client/admin
+# Example:
+# admin:/admin/language_edit.php:POST.records.weak_password_txt
+admin:/admin/server_config_edit.php:POST.maildir_path
+admin:/admin/server_config_edit.php:POST.website_path
+admin:/admin/server_config_edit.php:POST.website_symlinks
+admin:/admin/server_config_edit.php:POST.vhost_conf_dir
+admin:/admin/server_config_edit.php:POST.vhost_conf_enabled_dir
+admin:/admin/server_config_edit.php:POST.nginx_vhost_conf_dir
+admin:/admin/server_config_edit.php:POST.nginx_vhost_conf_enabled_dir
+admin:/admin/server_config_edit.php:POST.php_open_basedir
+admin:/admin/server_config_edit.php:POST.awstats_pl
+admin:/admin/server_config_edit.php:POST.fastcgi_starter_path
+admin:/admin/server_config_edit.php:POST.fastcgi_bin
+admin:/admin/server_config_edit.php:POST.jailkit_chroot_home
+admin:/admin/remote_user_edit.php:POST.remote_functions.1
+admin:/admin/firewall_edit.php:POST.tcp_port
+admin:/admin/system_config_edit.php:POST.admin_dashlets_right
+admin:/admin/system_config_edit.php:POST.reseller_dashlets_left
+admin:/admin/system_config_edit.php:POST.reseller_dashlets_right
+admin:/admin/language_edit.php:POST.records.weak_password_txt
+user:/client/client_message.php:POST.message
+user:/client/message_template_edit.php:POST.subject
+admin:/dns/dns_template_edit.php:POST.template
+admin:/nav.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_sys_state.php:SESSION.s.module.nav.1.items.0.title
+admin:/capp.php:SESSION.s.module.nav.1.items.0.title
+admin:/keepalive.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/log_list.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/datalog_list.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_data.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_sys_state.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_monit.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_munin.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_data.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/show_log.php:SESSION.s.module.nav.1.items.0.title
+admin:/monitor/log_del.php:SESSION.s.module.nav.1.items.0.title
+admin:/keepalive.php:SESSION.s.module.nav.1.items.0.title
+admin:/capp.php:SESSION.s.module.nav.1.items.0.title
+admin:/sites/web_vhost_subdomain_edit.php:POST.php_open_basedir
+admin:/sites/web_domain_edit.php:POST.php_open_basedir
+admin:/sites/web_domain_edit.php:POST.apache_directives
+user:/sites/shell_user_edit.php:POST.ssh_rsa
+user:/sites/cron_edit.php:POST.command
\ No newline at end of file
diff --git a/security/security_settings.ini b/security/security_settings.ini
index 4dfe001..43bcebf 100644
--- a/security/security_settings.ini
+++ b/security/security_settings.ini
@@ -16,6 +16,15 @@
admin_allow_software_repo=superadmin
remote_api_allowed=yes
+[ids]
+ids_enabled=yes
+ids_log_level=1
+ids_warn_level=5
+ids_block_level=30
+sql_scan_enabled=yes
+sql_scan_action=warn
+apache_directives_scan_enabled=yes
+
[systemcheck]
security_admin_email=root@localhost
security_admin_email_subject=Security alert from server
--
Gitblit v1.9.1