Practical Kohana Hooks Example: PHPIDS

Published on:
Tags: Kohana, PHP

PHPIDS Logo

So further to Dlibs tutorial on hooks, I thought I would help to demonstrate the power of this with a practical example of their usage: whilst reading this entry on PHPIDS I thought that seemed like a prime candidate for an example and so by following along below you should have a nice example of integrating a third party app into Kohana using the hooks/events system!

PHPIDS
From the site..

“PHPIDS (PHP-Intrusion Detection System) is a simple to use, well structured, fast and state-of-the-art security layer for your PHP based web application. The IDS neither strips, sanitizes nor filters any malicious input, it simply recognizes when an attacker tries to break your site and reacts in exactly the way you want it to.”

So we can simply insert PHPIDS into the Kohana system and have it silently monitor requests to our app/page informing us (if we wish) when it detects any potential attacks.

Third party apps in Kohana
Kohana loves third party applications, so much so that it makes it easy for us to integrate them . .meaning we have to write even less code. Kohana provides us with an area to centrally store any such applications (referred to as vendor apps) within the system folder. This folder can be found at <system_path>/vendor and is where any vendor apps we would like to use in our projects should be placed. If you look within that folder now you will see there are allready a number of such applications used within Kohana which you may or may not be familiar with.

If after reading this tutorial you would like more information on integrating other third party apps then you should definitely take a closer look at the email helper ( system/helpers/email.php ) which is a fantastic example of creating a helper to integrate a vendor app (in this case the Swift email library).

1 – Getting PHPIDS
The first step is to get yourself a copy of PHPIDS from here (the version I am working with is 0.5). After downloading this you can then extract the file into the system/vendor directory so that your vendor dir now contains a phpids folder aswell. Within the download we get three directories (tests, docs and lib) we are onlt really interested in lib although leaving the other two there for reference/testing is no bad idea.

We now have access to our third party app!

2 – Registering our hook
As I mentioned above one part of this tutorial was to demonstrate the power or hooks, allthough as a single feature they are actually very well documented within Kohana, for more information on them see the following pages:

  • Kohana hooks documentation
  • Kohana events documentation
  • Learn Kohana Blog on hooks/events In essence a hook is just a normal piece of code, nothing special at all. The power comes in when we are allowed to execute this piece of code at a number of pre-determined points through the execution process of the Kohana process (see the events docs), we can therefore deploy (in this case) PHPIDS at avery early point the in the page rendering process (prior to our controllers being executed for example), in many cases this is ideal in terms of security, efficiency, speed etc.

So to register our hook simply copy the config file (system/config/hooks.php) into our application config directory (resulting in application/config/hooks.php). We can then enable hooks by changing the contents of the hooks.php (within our application config dir) to:

$config['enable'] = TRUE;

Doing this means Kohana will now scan the application/hooks directory for any files and attempt to include and execute them.

3 – Creating our hook
The final step is creating our hook and configuring PHPIDS. Whilst doing this all code will be fairly PHPIDS specific, I was able to basically follow the included examples (and the examples in the blog posts above) in order to set it up (as I found documentation on their site fairly lacking), the code below represents a simple hook which will get your system running!

class Phpidsloader
{
   public static function load()
   {
      $path = get_include_path();
      set_include_path($path . ':' . SYSPATH .'vendor/phpids/lib');  
      require_once 'IDS/Init.php';  
      //Define constants for the ini file (they should be using a dynamic format!)
      define('IDS_FILTER_PATH', SYSPATH.'vendor/phpids/lib/IDS/default_filter.xml');
      define('IDS_TMP_PATH', SYSPATH.'vendor/phpids/lib/IDS/tmp');
      //this file must exist
      define('IDS_LOG_FILE', APPPATH.'logs/phpids_log.txt');    
      define('IDS_CACHE_FILE', SYSPATH.'vendor/phpids/lib/IDS/tmp/default_filter.cache');     
      //Run the monitor
      $init = IDS_Init::init(SYSPATH.'vendor/phpids/lib/IDS/Config/Config.ini');
      $ids = new IDS_Monitor($_REQUEST, $init);
      $result = $ids->run();  
      if (!$result->isEmpty()) {
         require_once 'IDS/Log/File.php';
         require_once 'IDS/Log/Composite.php';

     //Log all scores
     $compositeLog = new IDS_Log_Composite();
     $compositeLog->addLogger(IDS_Log_File::getInstance($init));
     $compositeLog->execute($result);
      }

      //reset the include path
      set_include_path($path);
   }
}
Event::add('system.ready', array('Phpidsloader', 'load'));
?>

The above is a simplified version of my final hook (which I will show later), but it demonstrates clearly the power or exactly what we are doing here.

The basic workflow is to set up the system in order that PHPIDS will run (so define include paths etc, define config path constants (for the PHPIDS config file)), run the application and finally return the system back to how we left it (as near as possible), so reset include paths etc . .that is all there is to it

You will need to then setup the PHPIDS config file which you will find in system/vendor/phpids/lib/IDS/Config/config.ini, I left the file as it was except for the paths in there which I ammended with the defined constants above (You can probably get away with using my config file below), another little gotcha is that in this case we will need to create the log file within application/logs (called phpids_log.txt) and make it writeable by the server as PHPIDS doesnt seem to automatically create this file

Additional Extras
So there we have an example of integrating a third party app (PHPIDS) into Kohana, the demonstration so far doesnt really do a great deal however so I went forward and added some extra logic into the hook which made use of some of the power of PHPIDS, using the attatched hook below we now

  • Track users actions accross the site, measing their threat level between pages
  • Enable actions to be taken at pre-defined threat levels (25 sends us a warning email, 50 kicks them off the site etc)
  • Record all registered warnings in the log file
  • Use the system to gather forensic evidence on the potential attack I have included my hook, along with the PHPIDS config file so that you can see exctly how I have them set up, as normal any questions or comments please do not hesitate to ask!

Download here

/Matt