PHPIDS (und Joomla)
PHPIDS Installation und Konfiguration

Das PHP Intrusion Detection System (PHPIDS) ist ein sehr leitsungsfähiges Werkzeug für die Erkennung von Angriffen auf Webapplikationen.
In diesem Tutorial wollen wir Ihnen die Installation und Konfiguration näherbringen und dabei auf die einzelnen Stolperfallen hinweisen.
Let's Start
Wir beginnen mit der Einrichtung von PHPIDS in einer unabhängigen Umgebung, lösgelöst von einer reinen Joomla-Implementierung. Dazu laden wir uns PHPIDS in der aktuellen Version herunter --> download
In dem Installationspaket befinden sich mehrere Ordner (docs, lib, nbproject und tests). Die reinen Projektdateien befinden sich im Ordner /phpids-[Versionsnummer]/lib/IDS. Wir erstellen nun einen Ordner namens "phpids" auf unseren Webserver und kopieren die Dateien von /phpids-[Versionsnummer]/lib/IDS in diesen Ordner hinein.
Sollten Sie über Ihren eigenen Server verfügen und keine shared-webhosting Umgebung benutzen, so bietet es sich an PHPIDS außerhalb des document roots zu legen. Dabei gilt es allerdings darauf zu achten, das "tmp"-Verzeichnis für den Apache-Webserver beschreibbar zu machen.
In dem Beispiel-Fall ist "www-data" der Benutzer, der Schreibrechte besitzt und "/path/to/phpids/tmp" ist der "tmp"-Ordner von phpids. Konkret könnte dies auch wie folgt aussehen:
Wie schon erwähnt ist dies nur für Anwender ohne shred-webhosting möglich. Sollten Sie ein shared-webhsoting-Paket (wie beispielsweise das Paket GN-Professional --> 250MB Webspace und unlimited Traffic für 4€/Monat) benutzen, so entfallen diese Schritte.
Konfiguration
Als nächstes begeben wir uns an die Konfiguration von PHPIDS. Die Konfigurationsdatei ist unter folgendem Ordner zu finden:
Dort öffnen Sie die Datei "Config.ini.php" und setzen den absoluten Pfad, wo es nötig ist. Wichtig ist noch, dass sämtliche Logmechanismen, die nicht benutzt werden auch entsprechend ausdokumentiert werden. Für unser Beispiel benutzen wir ein File-Logging und ein E-Mail-Logging. Dadurch wird jeder Angriffsversuch in einer Datei gespeichert und uns via E-Mail zugesandt.
Bitte fragen Sie Ihren Webhoster nach den absoluten Pfadangaben oder erstellen Sie eine Datei mit dem Namen info.php und folgen Inhalt:
Wenn Sie diese Datei aufrufen erhalten Sie ebenfalls den absoluten Pfad, in dem sich Ihre Webhosting-Umgebung befindet.
Nach erfolgreicher Recherche Ihres absoluten Pfades sind Sie nun in der Lage die Datei "Config.ini.php" zu bearbeiten. Diese besitzt in unserem Beispiel ungefähr folgendes Format:
; PHPIDS Config.ini
; General configuration settings
; !!!DO NOT PLACE THIS FILE INSIDE THE WEB-ROOT IF DATABASE CONNECTION DATA WAS ADDED!!!
[General]
; basic settings - customize to make the PHPIDS work at all
filter_type = xml
base_path = /var/www/webuser/phpids/
use_base_path = false
filter_path = /var/www/webuser/phpids/default_filter.xml
tmp_path = /var/www/webuser/phpids/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_Path = /var/www/webuser/vendors/htmlpurifier/HTMLPurifier.auto.php
HTML_Purifier_Cache = /var/www/webuser/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
; PHPIDS should run with PHP 5.1.2 but this is untested - set
; this value to force compatibilty with minor versions
min_php_version = 5.1.6
; If you use the PHPIDS logger you can define specific configuration here
[Logging]
; file logging
path = /var/www/webuser/tmp/phpids_log.txt
; email logging
; note that enabling safemode you can prevent spam attempts,
; see documentation
recipients[] = Diese E-Mail-Adresse ist gegen Spambots geschützt! JavaScript muss aktiviert werden, damit sie angezeigt werden kann.
subject = "PHPIDS detected an intrusion attempt!"
header = "From: <PHPIDS> Diese E-Mail-Adresse ist gegen Spambots geschützt! JavaScript muss aktiviert werden, damit sie angezeigt werden kann. "
envelope = ""
safemode = true
urlencode = true
allowed_rate = 15
; database logging
;wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
;user = phpids_user
;password = 123456
;table = intrusions
; If you would like to use other methods than file caching you can configure them here
[Caching]
; caching: session|file|database|memcached|none
caching = file
expiration_time = 600
; file cache
path = /var/www/webuser/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
An dieser Stelle sei nochmal darauf hingewiesen, dass es wichtig ist, sämtliche nicht genutzte Logmechanismen auszukommentieren. Dies erreichen Sie durch ein vorangestelltes Semikolon. Des Weiteren benötigt das "tmp"-Verzeichnis Schreibrechte. Werden diese Punkte nicht beachtet, so wird Ihre Seite später nicht geladen werden. Sie erhalten keine Fehlermeldung von PHPIDS, dass eine Logdatei nicht angelegt werden konnte.
In unserem Beispiel gehen wir davon aus, dass wir uns im Pfad "var/www/webuser" (shared-webhosting-Umgebung) befinden. Dort haben wir einen Ordner "phpids" erstellt und die Dateien aus dem Ziparchiv (/phpids-[Versionsnummer]/lib/IDS) entpackt. Diese Pfade gilt es in der gesamten Konfigurationsdatei anzupassen. Ebenso, wie der Empfänger der E-Mail.
Sobald Sie dies erledigt haben, ist die Konfiguration von PHPIDS abgeschlossen.
Integration von PHPIDS
Zum Einbinden des Systems gibt es verschiedene Möglichkeiten. Entweder via .htaccess-Datei oder mittels einer php.ini. Durch eine dieser Methoden stellen wir sicher, dass PHPIDS vor jedem Aufruf einer PHP-Datei aufgerufen wird. Sämtliche Requests an unsere Webapplikation werden dadurch gefiltert und im schlimmsten Falle (Angriff) geblockt. Für welche Methode Sie sich entscheiden hängt von Ihrer Webhosting-Umgebung ab. Die php.ini ist bei den Webhosting-Angeboten von GN-Webdesign beispielsweise eine benutzerspezifische Datei. Somit haben Sie die volle Kontrolle. Prinzipiell spielt es aber keine Rolle, für welche Methode Sie sich entscheiden. Die meisten Benutzer werden vermutlich die .htaccess-Variante bevorzugen. Sie führen allerdings beide zum Ziel.
.htaccess-Datei
.htaccess-Dateien sind den meisten eventuell unter zusätzliche Verzeichnisschutzmaßnahme bekannt. Allerdings lassen sich damit auch Werte des Apache-vHost überschreiben. Wenn Sie Zugriff auf Ihre Apache Konfiguration besitzen, so stellen Sie sicher, dass Ihr vHost folgenden Eintrag besitzt:
Stnadardmäßig sollte dieser Wert auf "None" stehen. Wir empfehlen bei Verwendung der .htaccess-Variante den Wert "Options" und nicht "All", da Sie so nicht sämtliche Restriktiven aufheben.
Begeben Sie sich anschließend in das Verzeichnis Ihrer Webapplikation und erstellen Sie eine .htaccess-Datei mit folgendem Inhalt:
An dieser Stelle ist es noch nicht wichtig zu wissen, was in der Datei "phpids.php" drin steht. Dazu kommen wir im nächsten Schritt. Wichtig ist aber diese Datei an dieser Stelle einzubinden.
Sollte die beschriebene Methode nicht gelingen, so probieren Sie die php.ini-Methode oder kontaktieren Sie Ihren Webhoster für weitere Hilfe.
php.ini
Nachdem Sie im vorigen Beispiel die Datei info.php erstellt haben, können Sie nun mit Hilfe dieser Datei nun auch den Pfad zu Ihrer php.ini auslesen. Danach können Sie die Datei info.php löschen.
Öffnen Sie die Datei php.ini und ändern Sie den ausdokumentierten Eintrag "auto_prepend_file" in folgenden Eintrag um:
Diese Änderung wird normalerweise erst nach einem Restart Ihres Apache-Webservers möglich (nicht in shared-webhosting-Umgebungen möglich).
Integrationsskript
An dieser Stelle erstellen wir das Einsprungskript für PHPIDS. Dies wird vor jedem Aufruf einer PHP-Datei aufgerufen und filtert ungewünschte Aktionen. In shared-webhosting-Umgebungen fügen wir die Datei ins Verzeichnis "/var/www/webuser/" ein (Pfad entsprechend anpassen). Andernfalls fügen wir die Datei unter "/var/www/" ein (außerhalb document-root). Erstellen Sie in Ihrem jeweiligen Verzeichnis eine Datei namens "phpids.php" und fügen folgenden Code ein:
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/webuser/phpids'
);
if(!session_id()){
session_start();
session_regenerate_id(true);
}
require_once 'Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
//extra check for phpmyadmin
if ( isset($_SERVER['SCRIPT_FILENAME']) && !preg_match("/phpmyadmin/i",$_SERVER['SCRIPT_FILENAME'])) {
$init = IDS_Init::init('/var/www/webuser/phpids/Config/Config.ini.php');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();
$_SESSION['impact']=$_SESSION['impact']+$result->getImpact();
if (!$result->isEmpty()) {
// Take a look at the result object
require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Email.php';
require_once 'IDS/Log/Composite.php';
$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init),
IDS_Log_Email::getInstance($init));
$compositeLog->execute($result);
if($_SESSION['impact']>=55){
die('<h1>Possible malicious attack logged!</h1>');
}
}
}
?>
Was macht dieses Skript nun? Als erstes setzen wir in Zeile 5 unseren Pfad zu PHPIDS. Zeile 9 startet unsere Session. Die Zeilen 13-19 geben die Methode an, die von PHPIDS gefiltert werden soll. In unserem Fall sind dies alle wichtigen Methoden, die PHP zur Informationsübergabe von einem Client an den Server verwendet. Zeile 23 ist nun eine speziell für Webhoster ausgelegte Zeile, die Probleme damit haben phpmyadmin in Ihrer Webhosting-Umgebung mit PHPIDS schützen zu wollen. phpMyAdmin führt in PHPIDS zu zahlreichen Problemen, da sämtliche SQL-Befehle von PHPIDS als SQL-Injection erkannt werden. Wir haben bisher noch keine andere Möglichkeit gesehen, als phpMyAdmin auszuschließen.
Im Anschluss daran teilen wir PHPIDS die Logmechanismen mit, die wir zuvor in der "Config.ini.php" eingestellt haben. In unseren Fall sind dies Datei und E-Mail. Wichtig dabei ist nun auch den zweiten Parameter an die Mehtode "addLogger()" zu übergeben, so wie in Zeile 39 geschehen.
Erkennt PHPIDS nun einen Angriff, so weisen wir in Zeile 43 Apache an das Skript zu beenden. Somit wird der schadhafte Code niemals ihre Webapplikation erreichen. In mehreren praktischen Tests hat sich herauskristallisiert, dass es durchaus sinnvoll ist nicht bei jedem Impact sofort auf einen Angriff schließen zu lassen. Die false positive Rate (Wert, der angibt, wie oft eine authentische Anfrage als bösartiger Angriff gewertet wurde) des PHPIDS ist bei manchen Webapplikationen recht hoch, weshalb es sinnvoll ist den Impact in einer Session zu speichern und erst bei Überschreitung eines definierten Wertes (in unserem Fall 55) erst das Skript zu sperren. Ein Angreifer versucht nicht nur einen Angriff, insofern wird sich automatisch der Impact bei einem realen Angriff erhöhen. Dies machen wir in Zeile 28 und Überprüfen es wieder in Zeile 42.
Befinden Sie sich in einer shared-webhosting-Umgebung so ist die Zeile 23 für Sie uninteressant. Löschen Sie die Zeile 23 und 46 bzw. benutzen Sie folgenden Inhalt für Ihre phpids.php-Datei:
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/phpids/lib'
);
if(!session_id()){
session_start();
session_regenerate_id(true);
}
require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/phpids/lib/IDS/Config/Config.ini.php');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();
$_SESSION['impact']=$_SESSION['impact']+$result->getImpact();
if (!$result->isEmpty()) {
// Take a look at the result object
require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Email.php';
require_once 'IDS/Log/Composite.php';
$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init),
IDS_Log_Email::getInstance($init));
$compositeLog->execute($result);
if($_SESSION['impact']>=55){
die('<h1>Possible malicious attack logged!</h1>');
}
}
?>
Abschlußtests
Nach Abschluss der Arbeiten können Sie Ihre Webapplikation beispielsweise mit einem XSS-Angriff von dieser Seite testen --> klick.
Sollten Sie alle Pfade richtig gesetzt haben und die Konfiguration ebenfalls korrekt gemacht haben, sollten Sie beim Versuch einen Angriff zu starten drei Dinge sehen:
- Das Skript wird nicht ausgeführt und es erscheint: "Possible malicious attack logged!" in Ihrem Browser.
- In Ihrem Logfile "path/to/phpids/tmp/phpids.log" sollte ein Eintrag verzeichnet sein und
- Sie sollten eine E-Mail erhalten haben, die in etwa so aussieht:
The following attack has been detected by PHPIDS
IP: 123.123.123.123
Date: 2010-01-05T20:27:50+00:00
Impact: 30
Affected tags: xss csrf id rfe lfi
Affected parameters: REQUEST.loginname=%5C%27%3Balert%28String.fromCharCode%2888%2C83%2C83%29%29%2F%2F%5C%5C%5C%27%3Balert%28S, POST.loginname=%5C%27%3Balert%28String.fromCharCode%2888%2C83%2C83%29%29%2F%2F%5C%5C%5C%27%3Balert%28S,
Request URI: %2Findex.php
Origin: [IP Ihres Servers]
Sollten diese drei Dinge funhktioniert haben, haben Sie PHPIDS erfolgreich installiert und konfiguriert. Herzlichen Glückwunsch.
Bleibt hingegen die Seite weiß und sie erhalten weder die Fehlermeldung, noch einen Logeintrag und ihre Webapplikation startet nicht, dann haben Sie entweder keine Schreibrechte auf den in der Konfiguration definierten "tmp"-Ordner oder Sie haben vergessen eine Logging-Methode in der Konfigurationsdatei auszukommentieren.
Sollten Sie darüber hinaus Fragen haben, scheuen Sie sich nicht diese hier zu posten.
Sind Sie darüber hinaus an Webhosting-Paketen interessiert, die speziell auf Sie zugeschnitten sind und zu 100% mit PHPIDS und Joomla funktionieren, dann sprechen Sie uns an. Über unser Kontaktformular sind wir jederzeit erreichbar.
Ihr Team von GN-Webdesign

