Das Apache-Modul Mod_security legt sich als Web Application Level Firewall zwischen Webserver und Browser, sodass es Angriffe frühzeitig erkennen und abwehren kann.
Miniserie: Apache-Module
| URLs umschreiben mit Mod_rewrite | LU 07/2011, S. 76 | https://www.linux-community.de/22935 |
| SSL-Authentifizierung mit Mod_ssl | LU 08/2011, S. 42 | https://www.linux-community.de/22936 |
| Apache absichern mit Mod_security | LU 09/2011, S. 70 | https://www.linux-community.de/22937 |
Jeder, der heutzutage Dienste im Internet anbietet, stellt ein potenzielles Angriffsopfer dar. Neben gezielten Attacken geraten auch Würmer und automatisierte Angriffe immer mehr zum Risiko. Untersuchen Sie ruhig einmal die SSH-Protokolle des Webservers auf ungültige Anmeldungen – Sie werden Augen machen. Doch wie sichern Sie sich am besten ab? Bei Applikationen von Drittherstellern oder Projekten besteht noch die Hoffnung, dass der Anbieter Fehler rechtzeitig im Vorfeld bemerkt und behebt, doch auch hier gehen schnell mehrere Tage ins Land, bis die Distributoren neue Pakete bereitstellen. Und auch einige der bekanntesten Anwendungen geraten regelmäßig wegen neuer Sicherheitslücken in die Schlagzeilen – ein gewisses Restrisiko besteht daher immer.
Wesentlich mehr Kopfzerbrechen bereiten da selbst geschriebene Applikationen. Selbst wenn Sie ein umfangreiches Security-Auditing vornehmen, können Sie bei hausinternen Tools eher selten auf die “Weisheit der Vielen” zählen, wie sie Open-Source-Projekte auszeichnet. Die Sicherheit Ihrer Applikation gewährleisten Sie deshalb in mehreren Schritten.
Das Fundament sollte immer eine aktuelle und gewartete Distribution bilden, die automatisch – beispielsweise mittels des Ubuntu-Tools unattended-upgrades [1] – sicherheitskritische Aktualisierungen einspielt. Darauf installieren Sie eine Firewall wie ufw [2], mit der Sie alle unbenutzten Ports schließen. Zusätzliche Sicherheit erhalten Sie mit fail2ban [3], mit dem Sie die gängigsten Dienste überwachen und potenzielle Angriffswege verriegeln – etwa durch automatisches Aussperren von IP-Adressen, von denen in kurzen Abständen ungültige Anmeldungen kommen. Weitere Hinweise zu der Materie hält übrigens auch das Securing Debian Howto bereit [4].
Sicherheit im Modul
So gerüstet, machen Sie sich nun ans Absichern des Webservers selbst. Mit Mod_security steht dazu ein Modul für den beliebten Apache-Webserver bereit, das Sie bei dieser Aufgabe unterstützt. Einen rudimentären Schutz erreichen Sie auch mit anderen Modulen, wie dem Rewrite-Modul [5], oder aber mit IP-basierten Firewalls wie Iptables. Der entscheidende Unterschied: Mod_security versteht sich als sogenannte Application Level Firewall auf die Feinheiten des verwendeten Protokolls und lässt sich daher viel gezielter anpassen – es versteht die entsprechenden HTTP-Befehle versteht.
Anderen Apache-Modulen stehen in der Regel nur die Kopfzeilen der Anfrage zur Verfügung – also etwa Domain, Browser, Referer und angefragte Datei sowie der GET-Parameter – nicht aber der Inhalt des Datenpakets selbst. Ähnlich verhält es sich mit Iptables: Damit filtern Sie zwar IP-Adressen heraus und limitieren die Anzahl erlaubter Verbindungen pro Minute, aber tiefergehende HTTP-Filtermöglichkeiten bietet es nicht. Unter anderem haben Sie keinen Zugriff auf den POST-Parameter, den sich heutzutage viele Applikationen unter anderem für Datei-Uploads zunutze machen, was POST zum beliebten Einfallstor für Angriffe macht.
Mod_security bietet zur Absicherung mehrere Komponenten, die Sie einzeln oder zusammen nutzen:
- die Protokollierung ein- und ausgehender Verbindungen samt dazugehöriger Nutzdaten,
- die Überwachung dieses Datenverkehrs auf Anomalien und deren Protokollierung, sowie
- die automatische Abwehr von dabei entdeckten Angriffen.
In Verbindung mit dem Apache-Proxy-Modul stellen Sie die Funktionalität sogar ganzen Webclustern zur Verfügung, indem Sie Mod_security auf dem Gateway installieren und sämtlichen Verkehr darüber leiten. Dabei muss Mod_security nicht zwingend für alle Seiten aktiv sein, denn viele Optionen konfigurieren Sie auch bequem pro virtuellem Host oder gar pro Verzeichnis.
Datenschutz
Das umfangreiche Protokollieren und Auswerten von Zugriffsdaten kann datenschutzrechtliche Probleme aufwerfen. Bereits die Standardeinstellung von Apache bewegt sich rechtlich mindestens im Graubereich. Für die umfassende Analyse auch von Paketinhalten durch Mod_security sollten Sie sich, insbesondere bei kommerziellem Einsatz, vorher juristisch absichern.
Die Testumgebung
Unser Testsystem besteht aus einem aktuellen Ubuntu 11.04 “Natty Narwhal” mit funktionsfähigem Apache samt PHP-Modul. Zur Demonstration von Mod_security legen Sie bereits vor dessen Installation eine einfache PHP-Datei an, die beispielsweise nur folgenden Code enthält:
<?php phpinfo(); ?>
Rufen Sie die Datei im Browser nun mit dem Parameter ?file=/etc/shadow auf, passiert nichts Spektakuläres: Sie sehen wie erwartet die PHP-Infoseite (Abbildung 1), der unnütze Parameter wird schlichtweg ignoriert. Wir kommen aber gleich noch einmal darauf zurück.
Mod_security steht als vorcompiliertes Paket zur Verfügung, das Sie als Root mittels
# apt-get install libapache-mod-security
installieren. Die Installation überprüfen Sie anschließend über den Aufruf apachectl -M, der alle geladenen Module anzeigt. Enthält die Liste den Eintrag security2_module, hat alles geklappt, und Sie müssen nur noch die benötigten Datenverzeichnisse anlegen. Das erledigen Sie mittels folgender zwei Befehle:
# mkdir -p /var/log/apache2/modsecurity-data # chown www-data: /var/log/apache2/modsecurity-data
Das geladene Modul allein nützt jedoch noch nichts: Ohne Konfiguration wird Mod_security ebenso wenig aktiv wie ein Iptables ohne keine Regeln, das dann alle Pakete durchlässt.
Ein erster Test
Sie schalten Mod_security scharf, indem Sie die gewünschten Regeln in die Apache-Konfiguration einbinden und gegebenenfalls weitere Direktiven setzen. Glücklicherweise müssen Sie das Rad dabei nicht neu erfinden, denn das Paket enthält bereits eine Vielzahl fertiger Regeln. Dieses CRS (“Core Rule Set”) müssen Sie nur noch aktivieren. Dazu legen Sie die Datei /etc/apache2/conf.d/modsecurity mit dem Inhalt aus Listing 1 an und starten Apache anschließend per /etc/init.d/apache2 restart neu.
Listing 1
<IfModule security2_module>
Include /usr/share/doc/mod-security-common/examples/rules/*.conf
Include /usr/share/doc/mod-security-common/examples/rules/base_rules/*.conf
SecAuditLog ${APACHE_LOG_DIR}/modsecurity_audit.log
SecAuditEngine RelevantOnly
SecAuditLogType Serial
SecDataDir /var/log/apache2/modsecurity-data
SecRequestBodyAccess on
</IfModule>
Diese Konfiguration lädt aufgrund der IfModule-Anweisung nur dann, wenn das Modul auch aktiviert ist – das vermeidet unnötige Fehler und Probleme beim Apache-Neustart, sollten Sie das Modul vorübergehend deaktivieren. Die mitgelieferten Regeln befinden sich unter Ubuntu – etwas ungewöhnlich – im Verzeichnis /usr/share/doc/mod-security-common/examples/rules und tragen die Endung .conf, daher binden Sie sie durch die entsprechenden Include-Anweisungen ein. Auf unserem Testsystem werden grundlegende Einstellungen beispielsweise in der Datei /usr/share/doc/mod-security-common/examples/rules/modsecurity_crs_10_config.conf mitgeliefert, wogegen die einzelnen Suchmuster in /usr/share/doc/mod-security-common/examples/rules/base_rules/*.conf liegen.
Um zu sehen, was Mod_security so alles anstellt, konfigurieren Sie die Protokollierung mit den drei SecAudit-Direktiven. Immer dann, wenn das Modul ein Angriff erkennt (SecAuditEngine RelevantOnly), schreibt es einen Eintrag in /var/log/apache2/modsecurity_audit.log. Die Option SecAuditLogType Serial besagt, dass Mod_security nur einzige Logdatei führt, die Einträge sequenziell aufnimmt. Nun binden Sie noch das vorhin erstellte Datenverzeichnis mittels SecDataDir /var/log/apache2/modsecurity-data ein – dort legt Mod_security Sitzungsdaten ab. Zum Schluss erlauben Sie dem Modul noch über SecRequestBodyAccess on, auch auf die Inhalte von POST-Befehlen zuzugreifen.
Jetzt kommen wir endlich auf die eingangs erstellte PHP-Datei zurück. Nachdem Sie Apache neu gestartet haben, laden Sie – gegebenenfalls nach Leeren des Browser-Caches – die Seite nochmals neu: Anstatt der PHP-Infoseite von vorhin erscheint jetzt nur eine Fehlermeldung (Abbildung 2), das Skript selbst ruft Apache überhaupt nicht mehr auf.
Doch was genau läuft hier eigentlich ab? Ein Blick in die Datei /var/log/apache2/modsecurity_audit.log verrät es Ihnen (Abbildung 3). Mod_security hat einen Angriff erkannt und aus diesem Grund den Zugriff gesperrt. Die in der URL angegebene Datei /etc/shadow enthält die verschlüsselten Kennwörter sowie weitere Daten aller lokalen Benutzer. Würde sie ein Angreifer in die Hände bekommen, erhielte er unter Umständen binnen kürzester Zeit vollen Zugang zum System – ein erhebliches Sicherheitsrisiko also.

Abbildung 3: Mit aktiviertem Audit-Log sehen Sie, aufgrund welcher Informationen Mod_security eine Abfrage blockiert hat.
Das Skript selbst enthält nur eine Zeile, die weder Dateien öffnet noch welche versendet. Mod_security hat also nicht das Skript selbst analysiert, was viel zu lange dauern würde, sondern es identifiziert theoretische Angriffsmöglichkeiten – erkennt also sozusagen schon die abstrakte Gefahr eines möglichen Angriffs.
Würde es sich bei dem aufgerufenen Skript beispielsweise um ein CMS, ein Wiki oder eine Galerie handeln – Applikationen also, die mit lokalen Dateien arbeiten – wäre das Risiko einer Kompromittierung ungleich höher. Ähnliches gilt für sogenannte SQL-Injection-Attacken, mit denen ein Angreifer sich Zugriff auf lokale Datenbanken verschafft. Kurz gesagt: Bevor es überhaupt zum Ernstfall kommt, hat Mod_security die Gefahr als so groß eingeschätzt, dass es den Zugriff zum Skript komplett verbietet.
Das Audit-Log können Sie im Produktivbetrieb übrigens ausschalten, da Mod_security alle Informationen zu gesperrten Abrufen in Kurzform auch in /var/log/apache2/error.log hinterlegt.
Regelkonform
Es bleibt die Frage, wie das Modul überhaupt mögliche Angriffe identifiziert. Ähnlich wie bei IP-basierten Firewalls legen Sie auch hier Regeln fest, die entsprechende Aktionen auslösen. Als Dreh- und Angelpunkt des Ganzen fungiert die Direktive SecRule, mit der Sie das Auftreten bestimmter Suchmuster im HTTP-Verkehr an bestimmte Ereignisse knüpfen. Sie fragen damit Variablen aus dem System oder aus Skripten genauso wie Kopfzeilen oder Cookies ab. Die allgemeine Syntax lautet dabei:
SecRule Element Suchmuster Aktion
Das Beispiel in Listing 2 verdeutlicht das.
Listing 2
SecRule "REQUEST_URI" "^/verwaltung$" "log,deny,status:500" SecRule "REQUEST_URI" "^/config" "deny,status:403" SecRule "REQUEST_URI" "setup$" "log"
Die erste Regel besagt, dass alle aufgerufenen Adressen (REQUEST_URI) die exakt /verwaltung lauten, sowohl protokolliert als auch direkt sperrt (log,deny) und der Besucher die Fehlermeldung 500 (status:500) sieht. Die zweite Regel umfasst alle Adressen, die mit /config anfangen, und blockt sie mit einem Fehler 403. Da es sich bei den Mustern um reguläre Ausdrücke [6] handelt und config nicht durch das Dollarzeichen ($) abgeschlossen ist, greift die Regel beispielsweise auch bei /configtest.
Zu guter Letzt führt die dritte Regel dazu, dass Mod_security alle Adressen, die auf setup enden, zwar protokolliert, aber nicht sperrt. Da das Muster nicht durch ein ^ eingeleitet, aber durch ein Dollarzeichen abgeschlossen wird, greift es zwar für websetup, nicht jedoch für setupdatei. Neben der Adresse fragen Sie ganz einfach auch andere Parameter ab oder kombinieren Abfragen.
In Listing 3 etwa fragt die erste Zeile den verwendeten Browser (User-Agent) ab. Handelt es sich um Safari, führt dies zu einem Fehler 403. Die zweite Zeile hingegen prüft, ob entweder der Browser oder aber das Accept Language-Feld der Anfrage die deutsche Sprache angeben, und quittiert dies dann mit einem internen Serverfehler 500. Die beiden Abfragen verknüpfen Sie einfach durch die Pipe (|) zu einer gemeinsamen Regel.
Listing 3
SecRule "REQUEST_HEADERS:User-Agent" "Safari" "deny,status:403" SecRule "REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Accept-Language" "de-de" "deny,status:500"
Untereinanderstehende Regeln arbeitet Mod_security sequenziell ab – für Safari-Browser ist nach der ersten Regel Schluss, Besucher sehen einen Fehler 403, unabhängig davon, welches Accept-Language-Feld gesetzt ist.
Auch eine Verneinung der Regeln ist natürlich möglich. So sperren Sie mittels der Regel
SecRule "REQUEST_HEADERS:User-Agent" "!Lynx" "deny,status:403"
sämtliche Browser außer Lynx aus. Neben deny gibt es natürlich noch mehr Aktionen, wie das Beispiel in Listing 4 zeigt. Die einleitende allow-Regel sorgt dafür, dass sämtliche folgenden Regeln umgangen werden und Mod_security die Anfrage direkt durchstellt – Firefox-Nutzer dürfen also auf alle Verzeichnisse zugreifen. Anwender von Lynx dürfen hingegen gelangen nirgendwo hin, sondern erhalten grundsätzlich einen Fehler 500. Safari-Anwendern indes legt das redirect in Zeile 3 nahe, doch bitte Firefox herunterzuladen. Benutzer von anderen Browsern wie Chrome oder Opera – beide in den Regeln nicht explizit genannt – dürfen zwar auf den Server zugreifen, erhalten aber aufgrund von Zeile 4 beim Webmail-Verzeichnis den Fehlercode 403.
Listing 4
SecRule "REQUEST_HEADERS:User-Agent" "Firefox" "allow" SecRule "REQUEST_HEADERS:User-Agent" "Lynx" "deny,status:500" SecRule "REQUEST_HEADERS:User-Agent" "Safari" "redirect:http://www.getfirefox.com" SecRule "REQUEST_URI" "^/webmail" "deny,status:403"
Regeln lassen sich übrigens auch kombinieren: Aufgrund der Anweisungen aus Listing 5 lässt sich das Webmail-Verzeichnis nur von Firefox unter Linux aus nicht erreichen.
Listing 5
SecRule "REQUEST_HEADERS:User-Agent" "Firefox" "chain,deny,status:500" SecRule "REQUEST_HEADERS:User-Agent" "Linux" "chain" SecRule "REQUEST_URI" "^/webmail"
Alle genannten Beispiele sind noch sehr einfach gelagert – die ganze Mächtigkeit von Mod_security sehen Sie in den mitgelieferten Regelwerken in /usr/share/doc/mod-security-common/examples/rules/base_rules. So unterstützt das Modul unter anderem Vererbungen, verschiedene Verbindungsphasen, verknüpfte Regeln, Gewichtungen, das Filtern von Parametern sowie das Hinzuziehen externer Programme, um damit beispielsweise Iptables zu konfigurieren oder eine automatisierte Meldung an den Netzbetreiber abzusetzen.
Das mitgelieferte Regelwerk bietet zwar einen guten Schutz, aber es besteht andererseits eine gewisse Wahrscheinlichkeit, dass auch legitime Anfragen nicht mehr funktionieren und somit bestehende Applikationen ihren Dienst versagen. Um auf Nummer sicher zu gehen, fügen Sie daher anfangs in der Apache-Konfiguration noch folgende Zeile hinzu:
SecRuleEngine DetectionOnly
Damit protokolliert Mod_security die Regeln lediglich, unterbindet aber keine Zugriffe. Werten Sie die Logdatei nach einer Weile aus, um mögliche Beeinträchtigungen vor dem Scharfschalten des Moduls zu identifizieren.
Fazit
Die hier gezeigten Möglichkeiten stellen nur die Spitze des Eisbergs dar. Bei Mod_security handelt es sich um ein äußerst mächtiges Modul zum Absichern des Webservers, das bereits eine Vielzahl guter Regeln mitbringt. Je komplexer die eigenen Webapplikationen, desto aufwändiger gestalten sich Pflege und Wartung – doch gerade für exponierte Seiten kann sich ein Blick durchaus lohnen. Um die Lektüre der ausführlichen Dokumentation zu Mod_security ([7],[8]) kommt der geneigte Administrator jedoch nicht herum.
Infos
[1] Unattended-upgrades: https://help.ubuntu.com/community/AutomaticSecurityUpdates
[2] Uncomplicated Firewall: http://wiki.ubuntuusers.de/UFW
[3] Fail2ban: https://help.ubuntu.com/community/Fail2ban
[4] Securing Debian Howto: http://www.debian.org/doc/manuals/securing-debian-howto/index.de.html
[5] Apache Mod_rewrite: Florian Effenberger, “Umgeschrieben”, LU 07/2011, S. 76, https://www.linux-community.de/22935
[6] Reguläre Ausdrücke: Frank Hofmann, “Schnipseljagd”, LU 09/2011, S. 84, https://www.linux-community.de/24901
[7] Mod_security-Handbuch zur Version 2.5.12: http://www.modsecurity.org/documentation/modsecurity-apache/2.5.12/
[8] Mod_security-Referenz im Wiki: http://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual







