ZIDS
Zend Framework Intruder Detection System
Requirements: Zend Framework (tested with version 1.10)
PHP-IDS (tested with version 0.6.4)


Copyright (c) 2010
by Christian KONCILIA
admin@web-punk.com

http://www.web-punk.com

LICENSE

See \library\zids\Plugin\Ids.php for license information.

VERSION

This is ZIDS Version 0.6.1

WHAT IS ZIDS

"Never ever trust user input!" - ZIDS helps you follow this golden rule of programming web applications. ZIDS uses PHP-IDS to analyze user inputs. The impact of a request is an integer value returned by PHP-IDS that indicates the severity of the attack. The higher the impact, the more likely the request was an attack!

ZIDS enables you to easily integrate PHP-IDS in your Zend Framework project. It allows you to define any number of levels of attack: e.g., 'unlikely', 'likely', 'very likely' and 'attack'.

For each level you may define:

Furthermore, ZIDS enables you to aggregate all impacts in your session. This is useful as usually an attacker will start to analyze your website with a series of "small" attacks, i.e. attacks with an impact below 15. If you enable aggregation, four attacks with an impact of 5 will aggregate to an attack with an impact of 20 (5 + 5 + 5 + 5).

ZIDS is open source! In case you are using ZIDS, I would appreciate if you could send a short email to admin@web-punk.com.
Follow me on twitter to keep up to date.

INSTALLING ZIDS

  1. Download latest version of ZIDS from http://code.google.com/p/zids/downloads/list
  2. Download PHP-IDS (http://php-ids.org/). ZIDS has been tested with PHP-IDS 0.6.4
  3. Extract and copy the PHP-IDS code to your project's \library folder, e.g. \library\phpids-0.6.4
  4. Open \library\phpids-0.6.4\lib\IDS\Config\Config.ini.php! Set base_path to your IDS folder and enable use_base_path, e.g.
    base_path       = "C:/myproject/library/phpids-0.6.4/lib/IDS/"
    use_base_path   = true
    
  5. Extract and copy the ZIDS code to your project's \library folder, e.g. \library\zids\Plugin\Ids.php
  6. Adopt your application.ini file (see \zids\application\config\application.ini in the ZIDS package for a sample configuration).
    ZIDS also supports application.xml files. The only difference to using an INI file is that you have to use the <all> tag instead of an asterisk. Please, have a look at Specific and Global Options for more information.
  7. Adopt your bootstrap.php file (see next chapter)

REGISTER THE ZIDS PLUGIN

Copy and paste the following source into your bootstrap.php file:
protected function _initZIDS() {
    // Setup autoloader with namespace
    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->registerNamespace('ZIDS');
        
    // Ensure the front controller is initialized
    $this->bootstrap('FrontController');

    // Retrieve the front controller from the bootstrap registry
    $front = $this->getResource('FrontController');

    // Only enable zfdebug if options have been specified for it
    if ($this->hasOption('zids'))
    {
        // Create ZIDS instance
        $zids = new ZIDS_Plugin_Ids($this->getOption('zids'));

        // create a logger (ADOPT THIS TO YOUR NEEDS!)
        $logger = new Zend_Log ();
        $filter = new Zend_Log_Filter_Priority(Zend_Log::ERR);
        $writer = new Zend_Log_Writer_Stream ("../data/logs/log.txt");
        $logger->addWriter ( $writer );

        // register all plugins that you need
        $zids->registerPlugin(new ZIDS_Plugin_ActionPlugin_Ignore());
        $zids->registerPlugin(new ZIDS_Plugin_ActionPlugin_Email());
        $zids->registerPlugin(new ZIDS_Plugin_ActionPlugin_Log($logger));
        $zids->registerPlugin(new ZIDS_Plugin_ActionPlugin_Redirect());

        // Register ZIDS with the front controller
        $front->registerPlugin($zids);
    }
}
This code will register all standard ZIDS plugins. In case you don't need all ZIDS plugin, simply remove the corresponding registerPlugin lines.

IMPACT LEVELS

In order to deal with the impact of a request as returned by PHP_IDS you have to define so called impact levels. Basically, an impact level corresponds to an interval. You define these intervals using the upto option.

For each impact level you have to define an action or a sequence of actions using the action option.

ZIDS will iterate through all defined impact levels (in the order as they are defined in application.ini). The first level where the condition impact <= level.upto returns true is the level which will fire. 'fireing' in this context means that all actions defined for this level will fire.

Have a look at the following example:
zids.level.unlikely.upto = 5
zids.level.unlikely.action.0 = ignore

zids.level.likely.upto = 25
zids.level.likely.action.0 = log

zids.level.attack.action.0 = log
zids.level.attack.action.1 = email

In this example, we define a set of three impact levels: 'unlikely', 'likely' and 'attack'. The unlikely impact level will fire if an impact between 0 and 5 occurs. The likely impact level will fire, if an impact between 6 and 25 occurs. For all impacts greater than 25, the attack impact level will fire.

Furthermore we defined, that we are going to ignore all possible attacks categorized as 'unlikely'. For the 'likely' impact level we are going to write a log entry. If the 'attack' impact level fires we are going to write a log entry and send an email.

ZIDS PLUGINS

Specific and Global Options

Options for all ZIDS plugins may be set in two different ways: specific or general. In the following example, we define the loglevel option for the log plugin:
zids.level.unlikely.option.log.loglevel = 6
zids.level.*.option.log.loglevel = 3
The first definition is a specific definition as it specifically sets the loglevel for the impact level 'unlikely' to 6. The second definition is a general definition as uses the asterisk (*).

If you don't use an 'ini'-file for your application configuration but prefer xml, please use the <all> tag instead of the asterisk (*). Hence, your application.xml could look like this:

<zids>
    ...
	<level>
		<all>
			<option>
				<log>
					<loglevel>3</loglevel>
				</log>
			</option>
		</all>
	</level>
    ...	
</zids>

A general definition sets an option for all impact levels. A specific definition sets an option only for the specified level.

Specific options always override general options!

This is especially useful, if you have multiple options and only want to change some of them for specific impact levels. The following example defines how to send emails in case of an attack. Furthermore, it defines that all emails will be sent to webadmin@yourhost.com except for the impact level 'verylikely'. In this case we directly want to send the email to the ceo@yourhost.com!

zids.level.*.option.email.smtp.auth = "login"
zids.level.*.option.email.smtp.port = "465"
zids.level.*.option.email.smtp.ssl = "SSL"
zids.level.*.option.email.smtp.username = "username"
zids.level.*.option.email.smtp.password = "password"
zids.level.*.option.email.smtp.host = "mail.yourhost.com"
zids.level.*.option.email.from = "zids@yourhost.com"
zids.level.*.option.email.to = "webadmin@yourhost.com"
zids.level.verylikely.option.email.to = "ceo@yourhost.com"

Standard Plugins

ZIDS comes with the following standard plugins.

Ignore

Nomen est omen: this plugin basically does nothing - it simply ignores the attack.

ATTENTION! Do not mistake the Ignore plugin for the Ignore option (see "ZIDS configuration". The ignore plugin will fire, after a possible attack has been detected, and - if you set the aggregate_in_session to true - after the impact has been aggregated in the session. In contrast, ignoring a request using the ignore option means that PHP_IDS doesn't even start! Please, have a look at the "ZIDS configuration" chapter for more details.

Log

This plugin logs the attack into the Zend_Log defined. You may set the log that ZIDS should use as parameter of the constructor or with the setLog() Method.

application.ini options (example & description)

zids.level.LEVELNAME.option.log.loglevel = 3
zids.level.LEVELNAME.option.log.items = ip, impact, tags, variables

loglevel defines the Zend_Log level to use, e.g. ALERT, EMERG, etc. The example given above logs all attacks that fall into the LEVELNAME impact level at Zend_Log level 3 (= Zend_Log::ERR)

items is a list of all items that should be written to the log. Currently, this plugin supports four items:

As all ZIDS plugin options, these options may be defined for a specific impact level or general for all impact levels (see Specific and Global Options)

Email

This plugin uses Zend_Mail to send an email via SMTP if a possible attack has been detected. You may specify the Zend_Mail instance to use as option in the constructor of the plugin, with the setEmail() Method, or in the application.ini!

application.ini options (example & description)

zids.level.LEVELNAME.option.email.smtp.auth = "login"
zids.level.LEVELNAME.option.email.smtp.port = "465"
zids.level.LEVELNAME.option.email.smtp.ssl = "SSL"
zids.level.LEVELNAME.option.email.smtp.username = "username"
zids.level.LEVELNAME.option.email.smtp.password = "password"
zids.level.LEVELNAME.option.email.smtp.host = "mail.yourhost.com"
zids.level.LEVELNAME.option.email.from = "zids@yourhost.com"
zids.level.LEVELNAME.option.email.to = "webadmin@yourhost.com"
zids.level.LEVELNAME.option.email.subject = "ZIDS: attack detected"
zids.level.LEVELNAME.option.email.items = ip, impact, tags, variables

auth, port, ssl, username, password, host, from, to and subject are options that will be simply passed to Zend_Mail. Have a look at the Zend_Mail manual in case of any questions regarding these parameters.

items is a list of all items that should be part of the email. Currently, this plugin supports four items:

As all ZIDS plugin options, these options may be defined for a specific impact level or general for all impact levels (see Specific and Global Options)

Redirect

This plugin redirects the user to a special website, e.g. a page that will inform the user that his/her request could not be processed due to security reasons. You may specify the target for the redirect as option (array) in the constructor of the plugin, with the setTarget() Method, or in the application.ini!

application.ini options (example & description)

zids.level.LEVELNAME.option.redirect.module = default
zids.level.LEVELNAME.option.redirect.controller = index
zids.level.LEVELNAME.option.redirect.action = attack

module, controller and action are used to define the target for the redirect plugin. Hence, in this example the user would be redirected to \index\attack in the default module.

As all ZIDS plugin options, these options may be defined for a specific impact level or general for all impact levels (see Specific and Global Options)

Writing your own Plugin

You may define your own plugins by extending ZIDS_Plugin_ActionPlugin_Action. All you have to do is to implement the following two methods (see ZIDS_Plugin_ActionPlugin_Interface):
/**
 * If an impact triggers this action, this method will be called. 
 *
 * @param IDS_Report $ids_result The result of the PHP IDS scan
 * @param int $impact The impact. If zids.aggregate_in_session = true, 
 *            $impact consists of the aggregated impact 
 *            otherwise $impact is the non aggregated impact
 * @param string $levelname Name of the impact level that fires the action
 * @return void
 */
public function fires(IDS_Report $ids_result, $impact, $levelname);

/**
 * Each plugin has to return a unique identifier / name
 *
 * @return string
 */
public function getIdentifier();

ZIDS CONFIGURATION (application.ini)

Beside the options defined for the ZIDS plugins, ZIDS uses the following options in the application.ini:

application.ini options (example & description)

zids.aggregate_in_session = true
zids.ignore.requests.module.0 = default
zids.ignore.requests.controller.0 = index
zids.ignore.requests.action.0 = sidebar
zids.phpids.config = APPLICATION_PATH "/library/phpids-0.6.4/lib/IDS/Config/Config.ini.php"

aggregate_in_session if set to true, ZIDS will aggregate the impact of each attack in the session. For instance, if the attacker submits a request with an impact of 5, and later on submits a request with an impact of 10, the second request will be treated as a request with an impact of 15 (=5 + 10)

ignore.request.module, ignore.request.controller, ignore.request.action. Use these options to define which requests should be completely ignored by ZIDS!

Please note that you don't have to specify all three options: If all three options are set, ZIDS will ignore all requests where all three parameters match. If only the module and controller have been specified, both parameters have to match (action is being ignored). If only module has been specified, the module has to match (controller & action are being ignored).

phpids.config defines where to find the PHP_IDS configuration file.

QUESTIONS?

Got questions? Please, send an email to admin@web-punk.com

CHANGE LOG