Sicherer Apache mit ModSecurity


- Veröffentlicht in freeX 03/06 -



Ende 2003 verglich Ivan Ristic das Betreiben eines Webservers mit »Russisch Roulette« (vgl. Introducing mod_security). Gleichzeitig machte er auch auf eine - von ihm - entwickelte Lösung zur Schadensbegrenzung aufmerksam. Das Programm mod_security bietet verschiedene Mechanismen zur Erkennung, Abwehr und Protokollierung von Angriffen auf Webserver.

Genau genommen handelt es sich bei mod_security um ein Modul zur »Feststellung und Verhinderung von Einbrüchen in Webserver« (Web Intrusion Detection and Prevention). Die Funktionsweise orientiert sich im wesentlichen an seinem »großen Bruder«, snort. Analog zu diesem IDS (Intrusion Detection System) wird der ein- und ausgehende Datenverkehr auf bestimmte Merkmale (»Signaturen«) untersucht, die für einen »Angriff typisch sind«. Wird eines dieser festgelegten Angriffs-Muster erkannt, wird eine vorherher definierte Aktion ausgeführt.




Während ein IDS normalerweise den gesamten Datenverkehr an der Netzwerkschnittstelle analysiert, ist mod_security auf ein einziges Protokoll zugeschnitten, HTTP.

Dabei werden unter anderem die folgenden Funktionen angeboten:

Die Datenanalyse erfolgt über reguläre Ausdrücke und kann somit sehr individuell angepasst werden.

Die folgenden Beispiele beziehen sich auf Konfiguration von mod_security mit Apache 2.0 unter NetBSD 3.0. Wer bereits Apache nutzt, sollte die Beispiele jedoch leicht auf Apache 1.3 oder »sein Betriebssystem« übertragen können.




Installation und Konfiguration

Unter NetBSD läßt sich mod_security über pkgsrc problemlos installieren. Dazu ist zunächst in das Verzeichnis /usr/pkg/pkgsrc/security/ap-modsecurity/ zu wechseln und dort der Aufruf make install zu tätigen.

Nach der Installation ist noch die Konfigurationsdatei von Apache (httpd.conf) um den Eintrag

LoadModule security_module lib/httpd/mod_security.so

zu ergänzen. Nachdem der Server neu gestartet wurde sollte das Modul installiert sein.

Weitere Hinweise zur Installation, auch auf anderen Systemen können der Dokumentation auf der Seite

http://www.modsecurity.org/

entnommen werden. Hier ist auch die jeweils aktuelle Version von mod_security sowie verschiedene Beispielkonfigurationen verfügbar (unter NetBSD finden diese sich auch unter /usr/pkg/share/examples/ap-security/).

Eine einfache Grundkonfiguration sieht beispielsweise wie folgt aus:

<IfModule mod_security.c>

    # Aktiviert oder deaktiviert das Modul 'mod_security'
    SecFilterEngine On 
 
    # Standard-Aktion wenn Anfrage mit einem Filter uebereinstimmt 
    SecFilterDefaultAction "deny,log,status:403" 
 
    # POST-Daten analysieren
    SecFilterScanPOST On
 
    # Sonderzeichen (z.B. '%20' fuer Leerzeichen) in der URL 
    # pruefen
    SecFilterCheckURLEncoding On 
 
    # URL im Unicode-Format pruefen
    SecFilterCheckUnicodeEncoding On 
 
    # Bereich von ASCII-Zeichen, der von einer Anfrage akzeptiert
    # wird
    SecFilterForceByteRange 1 255

    # Umfang der protokollierten Anfragen
    # - On: alle Anfragen werden protokolliert, was in der Regel 
    #       zu einem zu hohem Datenvolumen fuehren wird 
    # - Off: keine Protokollierung
    # - RelevantOnly: Anfragen die mit einem Filter 
    #                 uebereinstimmen
    # - DynamicOrRelevant: wie vor., zusaetzlich Anfragen nach 
    #                      'dynamischen Inhalten'
    SecAuditEngine RelevantOnly 
 
    # Name und Verzeichnis der Datei, in der die ueberprueften
    # Anfragen protokolliert werden  
    SecAuditLog /var/log/httpd/audit_log
 
    # Angabe wie detailliert protokolliert werden soll, wobei ein 
    # Wert von 0 (keine) bis 3 (sehr detailliert) anzugeben ist 
    SecFilterDebugLevel 3 
 
    # Name und Verzeichnis der 'Protokollierungs-Datei'
    SecFilterDebugLog /var/log/httpd/modsec_debug_log
 
    # Regelwerk
    ....


</IfModule>

Damit ist die Konfiguration zunächst abgeschlossen, was noch fehlt ist das Regelwerk. Hier werden zwei Arten von Filterregeln unterschieden, SecFilter und SecFilterSelective.

Die »einfacheren SecFilter« sind wie folgt aufgebaut:

SecFilter [regulaerer Ausdruck] [Aktion]

Die Regel wird über SecFilter eingeleitet und prüft den angegebenen regulären Ausdruck auf den ein- und ausgehenden HTTP(S)-Verkehr. Trifft der Ausdruck zu, wird anschliessend die angegebene Aktion ausgeführt.

Mittels SecFilterSelective lässt sich genauer angeben, welcher Bereich der Anfrage untersucht werden soll. Der Aufbau dieser Regeln sieht folgendermaßen aus:

SecFilterSelective [Bereich_der_Anfrage] [regulaerer Ausdruck] [Aktion]

Bei beiden Filtern gilt, ist die Aktion nicht gesetzt wird die unter SecFilterDefaultAction angegebene ausgeführt.




Aktionen

mod_security läßt verschiedene Aktionen zu, die wie folgt unterschieden werden:

Primäraktion
Müssen angegeben sein und legen fest wie die Anfrage weiter bearbeitet werden soll. Dabei kann die Bearbeitung abgebrochen (deny), erlaubt (allow, keine Folgeaktion möglich), fortgesetzt (pass, Folgeaktion möglich) oder auf eine beliebige URL umgeleitet werden (redirect).

Sekundäraktion
Zusätzlich von der festgelegten Primäraktion lassen sich zusätzlich beliebige Sekundäraktionen ausführen. Dazu gehören beispielsweise Protokollierung in die Protokolldatei von Apache (log) oder das Ausführen eines Programmes (exec).

Durchlaufaktion
Beeinflussen die Reihenfolge bzw. das Verhalten der Regeln. So kann eine Anzahl von n Regeln übersprungen (skip) oder einzelne Regeln miteinander verknüpft (logisches UND) werden (chain).

Parameter
Sind keine Aktionen im eigentlichen Sinne, sondern nehmen nur Einfluß auf diese. Die Rückgabe eines beliebigen HTTP-Statuscodes an den Client (beispielsweise status:403) ist ein derartiger Parameter.

Eine vollständige Aufzählung aller Aktionen und Parameter findet sich auf der Seite http://www.modsecurity.org/documentation/index.html.




Einfache Filter

Mit »einfachen Filterregeln« (SecFilter-Anweisungen) lassen sich HTTP-Anfragen nach einem bestimmten Muster durchsuchen und optional eine bestimmte Aktion ausführen. Als Muster kann dabei eine bestimmte Zeichenkette

SecFilter /etc/passwd

oder auch ein regulärer Ausdruck

SecFilter /bin/rm(dir)?

dienen. Nachdem die Konfigurationsdatei von Apache httpd.conf geändert wurde, ist der Server neu zu starten.

Die Funktionsweise der Regel kann mit dem folgenden Skript überprüft werden (ein Aufruf in einem beliebigen Browser sollte das gleiche Ergebnis liefern):

#!/usr/pkg/bin/perl -w
#

use LWP::UserAgent;

use strict;

my $url = shift or die "Aufruf: $0 <url>\n";

my $ua = LWP::UserAgent->new();                 # User Agent erzeugen
my $request = HTTP::Request->new('GET', $url);  # Request erzeugen
my $response = $ua->request($request);          # .... und ausfuehren

if ($response->is_success) {                    # Daten ausgeben
    print $response->content(), "\n";
}

else {                                          # Fehlermeldung ausgeben
    print "Fehler : ", $response->code(), "\n";
    print "Meldung: ", $response->message(), "\n";
}

Dem Skript ist bei Aufruf die entsprechende URL zu übergeben, also beispielsweise:

$ ./lwp_get.pl http://192.168.1.8/cgi-bin/welcome.pl?name=fred%3b/bin/cat%20/etc/passwd
Fehler : 403
Meldung: Forbidden
$

Die HTTP-Anfrage wurde entsprechend der Angabe zu SecFilterDefaultAction zurückgewiesen und die Fehlermeldung entsprechend ausgegeben. Außerdem wurde der Sachverhalt in audit_log wie folgt protokolliert:

========================================
UNIQUE_ID: YRyZF8CoAQgAAANqElwAAAAE
Request: 192.168.1.8 - - [04/Mar/2006:16:59:32 +0100] "GET /cgi-bin/welcome.pl?name=fred%3b/bin/cat%20/etc/passwd HTTP/1.1" 403 331
Handler: cgi-script
----------------------------------------
GET /cgi-bin/welcome.pl?name=fred%3b/bin/cat%20/etc/passwd HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: 192.168.1.8
User-Agent: libwww-perl/5.803
mod_security-message: Access denied with code 403. Pattern match "/etc/passwd" at THE_REQUEST
mod_security-action: 403

HTTP/1.1 403 Forbidden
Content-Length: 331
Connection: close
Content-Type: text/html; charset=iso-8859-1

Die nächsten Regeln sprechen auf viele Cross-Site-Skripting Angriffe an, bei denen oftmals script-Tags in HTTP-Anfragen untergebracht werden. In verschiedenen Webanwendungen wie beispielsweise Foren oder Wiki ist es über Eingabefelder möglich HTML-Tags zu übergeben. Erfolgt hier keinerlei Einschränkung können auch script-Tags eingeschleust werden. Diese Tags werden bei der Anzeige im Browser als Skript gewertet und ausgeführt, beispielsweise

<script>alert("Auftrag ausgefuehrt")</script>

Der folgende Filter verhindert script-Tags:

SecFilter "<[:space:]*script"

Ein weiteres Ärgernis sind SQL-Injection Angriffe. Im Gegensatz zum Cross-Site-Skripting geht es hierbei darum, einen Datenbankserver hinter dem Webserver anzugreifen. Es ist so unter Umständen möglich Daten zu manipulieren oder auch Zugriff auf sensible Daten zu erlangen.

Auch hier sind Eingabefelder die Einstiegsmöglichkeit. Statt eines Skriptes werden an dieser Stelle »passende SQL-Anweisungen« eingeschleust. So könnte aus einer harmlosen Anfrage nach Auswertung durch den Webserver die folgende Anweisung stehen:

DROP TABLE kunden

Die folgenden Filter verhindern viele dieser Angriffe:

SecFilter "delete[[:space:]]+from"
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"



Selektive Suche

SecFilter untersucht stets die vollständige Client-Anfrage. Oftmals treten bestimmte Muster jedoch nur in bestimmten Bereichen eines Requests auf. Mit dem Filter SecFilterSelective kann zusätzlich ein Bereich angegeben werden, auf den sich der Filter beschränken soll. Die Abarbeitung der Regeln wird somit effektiver was die Dauer sowie die Speicherauslastung betrifft.

Zu den Bereichen zählen unter anderem alle in CGI-Skripten verfügbaren Variablen wie beispielsweise REMOTE_ADDR oder REMOTE_HOST.

Weitere Bereiche sind unter anderem:

POST_PAYLOAD
die durch eine POST-Anfrage übermittelten Daten

ARGS
alle durch eine POST-Anfrage übermittelten Argumente

ARGS_NAMES
nur die Namen der übermittelten Argumente

ARGS_VALUES
nur die Werte der übermittelten Argumente

COOKIES_NAMES
Name von Cookies

COOKIES_VALUES
Werte von Cookies

ARG_name
Variable oder Parameter mit der Bezeichnung name

COOKIE_name
Cookies mit der Bezeichnung name

Ein Beispiel für einen selektiven Filter könnte wie folgt aussehen:

SecFilterSelective ARG_user "!^[a-zA-Z]*$"

Diese Anweisung stellt sicher, daß bei der Eingabe von Formulardaten (beispielsweise ein Textfeld mit der Bezeichnung user) etwas anderes als Buchstaben an den Server weitergegeben werden.

Die folgende Regel zeigt ein Beispiel für eine Verkettung von zwei Regeln durch chain:

SecFilterSelective ARG_login "^admin$" chain
SecFilterSelective REMOTE_ADDR "^192.168.1.8$" nolog,allow

Zunächst wird der übergebene Wert der Variablen login überprüft. Trifft der reguläre Ausdruck auf einen Administrator admin zu, kommt die folgende Regel zur Auführung. Mit dieser wird sämtlicher Datenverkehr von und nach 192.168.1.8 erlaubt, außerdem wird auf eine Protokollierung verzichtet.

Das nächste Beispiel zielt auf das »Hochladen von Dateien« (File-Upload) ab. Hier wird ein externes Skript modsec_clamscan.pl aufgerufen, welches die Datei(en) auf Viren überprüft.

SecFilterSelective "HTTP_CONTENT_TYPE" multipart/form-data "log,pass,exec:/modsec_clamscan.pl"

Es lassen sich nicht nur HTTP-Anfragen auswerten, sondern auch Antworten die der Webserver dem Client übermitteln (will). Mit dem folgenden Filter erhält der Client eine Fehlermeldung, die auf einem »internen Serverfehler« beruht, wenn die Antwort des Servers die Zeichenkette »Index of /cgi-bin« enthält.

SecFilterSelective OUTPUT "Index of /cgi-bin" deny,status:500



weitere Funktionalitäten

Außer dem Erkennen von (Angriffs-) Mustern verfügt mod_security über weitere nützliche Eigenschaften, die noch kurz vorgestellt werden sollen.

Aus Sicherheitsgründen wird Apache oftmals in einer sogenannten Chroot-Umgebung eingerichtet. Vereinfacht gesagt handelt es sich hierbei um einen »geschlossenen Bereich« auf dem Rechner innerhalb dem der Webserver läuft. So sind beispielsweise sämtliche Server-Prozesse nur innerhalb dieser Umgebung aktiv und haben keinen Einfluß auf das »restliche System«.

Der Nachteil einer derartigen Lösung liegt in dem hohen Zeit- und administrativen Aufwand. So müssen beispielsweise sämtliche (System-) Bibliotheken und Programme, die für den Betrieb des Webservers benötigt werden, in die Chroot-Umgebung kopiert und dort gegebenenfalls noch angepasst werden.

mod_security bietet hierzu eine relativ einfache Lösung, durch die Direktive

SecChrootPath /var/chroot/apache

wird die Ausführung von Apache sowie allen zugehörigen Programmen und Skripten auf das angegebene Verzeichnis eingeschränkt. Auf der anderen Seite ist ein Zugriff auf Dateien innerhalb dieser Umgebung von außerhalb dieses Verzeichnisses auch nicht mehr möglich.

Die von mod_security angebotene Lösung zur Umsetzung einer Chroot-Umgebung ist (noch) in der Entwicklung. Einzelne Eigenschaften sind bereits umgesetzt, andere werden als »experimentell« bezeichnet und andere wiederum für kommende Versionen angekündigt. Der Ansatz sowie der bisherige Entwicklungsstand erscheint sehr vielverprechend, es bleibt abzuwarten was hier zukünftig geboten wird. Weitere Hinweise zur Chroot-Umgebung sowie eine »Schritt-für-Schritt-Anleitung« sind auf der Webseite von mod_security zu finden.

Verschiedene Angriffe zielen speziell auf die Schwächen oder Sicherheitslücken einer bestimmten Anwendung ab. Einen »gewissen Grundschutz« bietet hier das Vortäuschen einer falschen Identität, was mit mod_security über die folgenden Angaben erfolgen kann.

SecServerSignature "Microsoft-IIS/5.0"

Hierbei ist allerdings zu beachten, daß sich durch diese Maßnahme ein erfahrener Angreifer kaum in die Irre führen läßt, der die wahre Identität an dem »Verhalten des Servers« erkennen kann.




Performance

Die Filterung des HTTP-Verkehrs geht nicht spurlos an der Auslastung des Systems vorbei. Diese ist in erster Linie von dem eigenen Regelwerk abhängig, so dass hier keine konkrete Angaben geliefert werden können. Im Internet sind häufig Angaben von einer höheren Auslastung im Bereich von 10% zu lesen.

Positiv auf die Systemauslastung wirkt sich in der Regel aus, so oft es geht SecFilter zu umgehen und statt dessen SecFilterSelective zu nutzen. Ausserdem können statische Anfragen mit

SecFilterEngine DynamicOnly

ausgeschlossen werden. Durch diese Angabe werden nur noch dynamisch erzeugte Anfragen untersucht, was zu einer weiteren Verbesserung der Performance führen kann.

Gleiches gilt für den Umfang der Meldungen unter SecAuditEngine sowie SecFilterDebugLevel.




Fazit

Durch die Anwendung der regulären Ausdrücke als Suchmuster und die Möglichkeit nahezu beliebig viele Regeln miteinander zu verbinden läßt sich ein sehr komplexes Regelwerk erstellen. Somit lassen sich auch anspruchsvolle Sicherheitsrichtlinien direkt im Webserver umsetzen.

Die Komplexität der Filterregeln birgt aber auch Gefahren. Je umfangreicher diese sind, desto ausgiebiger sollten diese vorab getestet werden. Hierzu ist bei den entsprechenden »Aktionen« lediglich deny auf pass zu setzten (die Protokollierung mit log muss nach wie vor angegeben sein).

Auf der Spurensuche von Nebeneffekten helfen auch die Einstellungen zu SecAuditEngine und SecFilterDebugLevel weiter. Je gesprächiger diese sind, desto größer ist auch die Wahrscheinlichkeit, daß die betreffende Ursache protokolliert wurde.

Nachteilig wirkt sich auch hier aus, wie bei allen Systemen dieser Art, daß im Vorfeld bekannt sein muß wie der nächste Angriff erfolgen wird, um wirksame Schutzmechanismen zu ergreifen. Es versteht sich fast von selbst, daß das eigene Regelwerk stets aktualiert werden sollte. Hierzu können beispielsweise die snort-Regeln mit dem Tool snort2modsec.pl, welches dem Tar-Archiv von mod_security beiliegt, genutzt werden. Hierbei sollte jedoch beachtet werden, daß die Regeln nicht »blind übernommen«, sondern vorab geprüft und gegebenenfalls angepasst werden.

Insgesamt gesehen läßt sich mod_security zum einem umfangreichen System zur Abwehr diverser Angriffsarten ausbauen. Allerdings erfordern Konfiguration und Wartung eines bestehenden Systems etwas mehr Zeitaufwand als einen verregneten Nachmittag.




| Home | Artikel | Bücher | Touren | Photos | Impressum |
Rücksprachen, Anmerkungen, Anregungen, .... bitte an info@noatun.net