Die meisten Webapplikationen sind schnell installiert und betriebsbereit. Nur wie sichere ich die Installation ab, damit man auch vor möglichen Angreifern geschützt ist? Leider stellen sich nur sehr wenige diese Frage und werden meist erst mit dem Thema konfrontiert, nachdem Ihr Projekt gehackt wurde.

Gleich vorab möchte ich darauf hinweisen, dass eine 100% Sicherheit nie existieren wird. Der Boardhersteller kann nur Sicherheitslücken stopfen, die ihm bekannt sind. Doch was ist mit den Sicherheitslücken, die ihm unbekannt sind? Es gibt dafür zwar Präventivmaßnahmen, aber ein gewisses Sicherheitsrisiko bleibt immer bestehen. Man sollte sich immer vor Augen halten, dass die Sicherheit nur soviel Wert ist, wie das schwächste Glied in der Kette.

Sicherheit hat auch Ihren Preis:

  • hoher Zeitaufwand (Updates einspielen, Recherchen anstellen, u.s.w.)
  • oft wird dadurch auch die Performance beeinträchtigt (mehr Datenbankabfragen oder durch PHP Module wie modsecurity oder Suhosin)

Egal wie viele Sicherheitsvorkehrungen man vor möglichen Angreifern getroffen hat, das Wichtigste ist immer, dass man für den Notfall ein aktuelles Backup zur Hand hat. Es gibt viele Backup-Lösungen, man sollte aber darauf Wert legen, dass die Sicherung automatisiert stattfinden (wer macht schon manuell regelmäßig Backups? Vor allem in Stress-Situationen wird man sich nicht die Zeit nehmen.)

Falsche Betrachtungsweise

Viele Webmaster gehen immer noch nach der Devise “Never change a running system”. Wenn man nach diese Einstellung seinen Server/Projekt betreibt, wird man früher oder später einem Hacker zum Opfer fallen. Desweiteren ist es auch ein Fehler, sich auf Techniken nach dem Motto Security through obscurity zu verlassen. Hierzu zählt z.B. dass man die Versionsnummer der Software versteckt oder dass man Verzeichnisse oder Dateien umbenennt, damit Sie nicht gefunden werden. Diese Taktiken tragen nicht wirklich zur Sicherheit bei, sondern Sie erschweren dem Angreifer nur das Auskundschaften des anzugreifenden Rechners. Werden zusätzlich richtige Sicherheitsmaßnahmen ergriffen, kann man allerdings gegen diese Maßnahmen nichts einwenden.

Ok, die nachfolgenden Hinweise beziehen sich auf Projekte, die mit PHP umgesetzt wurden. Daher sind diese Tipps auf sehr viele Anwendungen anzuwenden, wie z.B. vBulletin, Drupal, phpBB, OSCommerce und wie sie alle heißen. Anschließend werde ich noch für bestimmte Anwendungen weiterführende Empfehlungen geben.

Firewall

Aus irgendeinem Grund denken auch erfahrene Administratoren, dass eine Firewall überflüssig ist. Deren Begründung liegt meist darin, dass man nur die Diensten laufen lassen soll, die man auch benötigt und deshalb sowieso andere Ports geschlossen sind. Soweit stimmt das schon, aber eine Firewall bietet wesentlich mehr Möglichkeiten, als einfach nur einen Port zu schließen. Zum Beispiel kann man zwischen einer ICMP, UDP oder TCP Anfrage unterscheiden, man kann auch ausgehende Verbindung einschränken, oder bestimmte Regelwerke für genau definierte Anwendungszwecke definieren. Ein weitere Vorteil beim Einsatz einer Firewall ist die Protokollierung. Es ist sehr wichtig, dass man Nachvollziehen kann, was überhaupt auf dem Server vor sich geht. Zum einen können diese Protokolldateien für weitere Präventiv-Maßnahmen diesen, zum Anderen können Sie sehr hilfreich sein, wenn man herausfinden will, wie ein Eindringling ins System gekommen ist. Es gibt keine wirklichen Grund, dass man keine Firewall einsetzt (außer vielleicht Faulheit ;)).

Portscan eines Rechners

Allgemeine Ratschläge für die Server-Konfiguration

  • Die aktuellste PHP Version Besonders wichtig ist, dass man die aktuellste PHP Version verwendet, da bisher schon in allen PHP Version Sicherheitslücken geschlossen wurden. Vorher sollte man allerdings sicherstellen, dass auch alle Anwendungen noch fehlerfrei laufen.
  • Die aktuellste MySQL Version Auch bei der Datenbank gilt, dass man die aktuellste Version verwenden sollte.
  • Betriebssystem Updates durchführen Der sicherste Webserver/Datenbank nutzt nichts, wenn das darunter liegende System Sicherheitslücken beinhaltet. Normalerweise bietet jede Linux Distribution mehr oder weniger komfortable Aktualisierungs-Mechanismen an, wie z.B. Yast, apt oder emerge. Es sollte ich regelmäßigen Abständen überprüft werden, ob Betriebssystem-Updates vorhanden sind und diese dann auch aufgespielt werden.
  • Multi-Hosting Systeme meiden, immer einen dedicated Server (oder wenn Du kein Linux Experte bist, einen Managed Server) vorziehen. Der Grund liegt ganz einfach darin, dass andere Benutzer auf dem Server auch potentielle Angreifer sein können und dass man auf einen Multi-Hosting System die Sicherheitseinstellungen lockerer einstellen muss, da man gewährleisten muss, dass möglichst viele unterschiedliche Anwendungen damit zurechtkommen sollen. Wenn man einen Server speziell für einen bestimmten Einsatzzweck verwendet, kann man diesen speziell auf diese Anforderungen optimieren - dies bezieht sich sowohl auf sicherheitsspezifische als auch auf performanceauswirkende Einstellungen.
  • Verbesserung der PHP Core Sicherheit durch Suhosin. Suhosin wurde entworfen, um den Server und die Benutzer vor bekannten und unbekannten Fehlern in PHP Anwendungen und im PHP Kern zu schützen.
  • Verstärkung der PHP Sicherheit zur Vorbeuge fehlerhafter oder schlecht programmierter Programme durch modsecurity (weniger geeignet für Multi-Hosting Systeme). Desweiteren hat man durch modsecurity exzellente Protokollierungsmöglichkeiten. Der Einsatz von modsecurity wird die Performance des Servers beeinträchtigen, weshalb ein Einsatz eines Caching-Systems wie mit APC oder eAccelerator anzuraten ist.
  • Unnötige Dienste deaktivieren Alle Dienste (Daemons), die auf dem Server laufen und nicht gebraucht werden, sollten deaktiviert werden. Wenn es möglich ist, sollte man diese auch gleich deinstallieren. Jeder weitere Dienst der auf dem Server läuft, ist ein weiterer Angriffspunkt (unnötige offene Ports!).

MySQL Datenbankserver absichern

MySQL wird standardmäßig mit dem Skript mysql_secure_installation ausgeliefert, mit dem man einige der nachfolgenden Einstellungen automatisch setzen kann.

  • Kennwort für root Benutzer festlegen MySQL wird mit dem Account root ausgeliefert, welcher ohne Kennwort verwendet werden kann. Diesen Account sollte man schnellstmöglichst ein Kennwort zuweisen. Das Kennwort kann man z.B. wie folgt zuweisen (man muss für dieses Beispiel als root angemeldet sein: ``` mysql mysql UPDATE `user` SET `Password`=PASSWORD('geheim') WHERE `User`='root'; FLUSH PRIVILEGES; quit ``` Es sollte natürlich für geheim ein anderen Kennwort verwendet werden ;)
  • Administratoren Accounts nur von localhost zulassen Alle Accounts, die Rechte auf mehrere oder alle Datenbanken haben (Admin-Accounts), sollten nur über den Host localhost verwendet werden können.
  • Datenbankzugriff von externe Rechnern unterbinden Wenn man keinen externen Zugriff auf die Datenbank benötigt und die Datenbank über Sockets ansprechen kann, kann man mit folgender Anweisung in der my.cnf Datei unter dem Abschnitt [mysqld] die komplette Netzwerkfunktionalität des MySQL Daemon abstellen: ``` skip-networking ``` Falls man einen externen Datenbankzugriff erlauben muss (was immer ein gewissen Risiko darstellt, da der Server z.B. über eine Brute Force Attacke angegriffen werden kann), sollte man mit folgender Anweisung den Server an eine feste IP Adresse binden (das kommt auch in den Abschnitt [mysqld] in der my.cnf): ``` bind-address = 192.168.0.1 ``` Hier musst Du natürlich eine IP Deines Server verwenden. Mit der Nutzung einer externen Datenbank empfehle ich eine SSL Verbindung, VPN oder einen SSH Tunnel zu benutzen, um die Daten verschlüsselt zu übertragen. Wenn als IP die 127.0.0.1 verwendet wird (also der Localhost), kann man noch mit folgender Anweisung die Namesauflösung deaktivieren: ``` skip-name-resolve ``` Anmerkung: Wenn skip-networking gesetzt wird, ist nur eine Socket Verbindung zum Server möglich. Wenn diese Option nicht gesetzt und die IP Adresse an 127.0.0.1 gebunden wird, ist eine TCP/IP und eine Socket Verbindung zum Datenbankserver möglich (aber nur von Localhost)
  • Fehlerhafte Queries begrenzen Wenn ein Fehler in der Programmierung eines PHP Skriptes vorliegt (z.B. falscher Join), kann die Datenbank bis zum Abwinken arbeiten, und wird mit der Anfrage doch nicht fertig. Um die Anzahl der Ergebnisse eines Join zu begrenzen, setzt man folgende Option: ``` max_join_size=20000000 ``` Dies bewirkt, dass nach 20 Millionen Zeilen MySQL die Anfrage abbricht, was verhindert, dass der Server unnötige Ressourcen verbraucht.

Apache Webserver absichern

  • Alle Module deaktivieren, die nicht gebraucht werden Jedes Apache Modul stellt einen weiteren Angriffspunkt dar. Deshalb es anzuraten, dass man alle Module, die man sowieso nicht benötigt, auch nicht lädt. Wenn der Server nur PHP Anwendungen hostet, dann braucht man beispielsweise kein Perl Modul laden. Module, die dem Angreifer Informationen liefern, sollte man generell deaktivieren - hierzu gehören beispielsweise das status und info Modul. Wenn nur PHP aus Modul zu Einsatz kommt, und auch kein Perl benötigt wird, kann man auch die Module cgi und perl aus der Konfiguration nehmen. Die Konfiguration weicht zwischen den verschiedenen Linux Distributionen stark von einander ab. Z.B. wird bei SuSE über die Datei /etc/sysconfig/apache2 die Apache Konfiguration geregelt. Innerhalb dieser Datei wird über die Variable APACHE_MODULES festgelegt, welche Apache Module geladen werden sollen.
  • Informationen über den Webserver verbergen Standardmäßig schickt der Webserver im Header jeder Ausgabeseite Informationen über die verwendete Software und die dazugehörigen Versionsnummer mit. Diese Information könnte beispielsweise wie folgt aussehen: ``` Server: Apache/1.3.37 (Unix) PHP/4.4.4 with Suhosin-Patch FrontPage/5.0.2.4803 mod_fastcgi/mod_fastcgi-SNAP-0404142202 mod_ssl/2.8.28 OpenSSL/0.9.6i ``` Um die Ausgabe auf "Server: Apache" zu begrenzen, setzt man in der httpd.conf folgende Anweisung: ``` ServerTokens Prod ``` Aber auch hierfür gibt es wieder verschiedene Möglichkeiten der Konfiguration. Bei SuSE sollte man z.B. dafür in der Datei /etc/sysconfig/apache folgende Einstellung setzen, anstatt manuell die httpd.conf zu bearbeiten. ``` APACHE_SERVERTOKENS="Prod" ```
  • Sicherheitsrelevante Einstellungen gehören nicht in die .htaccess Alle sicherheitsrelevanten Einstellung sollte man direkt in der httpd.conf integrieren. Die .htaccess Dateien sind zwar sehr beliebt, weil man ohne einen Webserver-Neustart die Einstellungen sofort aktiviert hat. Die Gefahr dabei ist aber, dass diese Datei auch von Angreifern manipuliert oder erzeugt/entfernt werden kann. Auf der anderen Seite kann die .htaccess Datei bei einen Projekt-Update fälschlicherweise leicht überschrieben werden - womöglich ohne dass es bemerkt wird.

PHP absichern

In aktuellen PHP Versionen sind die Sicherheitseinstellungen schon relativ gut voreingestellt. Einstellungen wie Register_Globals=On oder ähnliches gehören schon lange nicht mehr zur Standardeinstellung. Vorsichtig muss man aber bei PHP Paketen sein, die mit den Linux Distributionen kommen. Hier sollte man auf jeden Fall die Einstellungen mit der original php.ini-production vergleichen.

Zusätzlich sollten noch folgende Änderungen in der php.ini durchgeführt werden:

  • expose_php = Off Dadurch wird im HTTP Header folgende Zeile nicht mitgeschickt: ``` X-Powered-By: PHP/5.1.6-pl8-gentoo ``` Dies ist zwar nicht wirklich eine Sicherheitseinstellung, aber man muss dem Angreifer ja nicht auf die Nase binden, welche PHP Version man benutzt. Wie man in diesem Beispiel sieht, kann man hieraus auch erkennen, welche Linux Distribution verwendet wird - Informationen, die für Angreifer sehr nützlich sind.
  • display_errors = Off Durch diese Einstellung werden keine Fehlermeldungen mehr über dem Webserver ausgegeben. Anstelle dessen kann man alle Fehlermeldungen in eine Log-Datei schreiben lassen und diese kann der Admin des Systems von Zeit zu Zeit durchsehen. Um die Fehlermeldungen in eine Datei zu protokollieren, müssen folgende zwei Anweisungen gesetzt werden: ``` log_errors = On error_log = /var/log/php_error ``` Die Fehlermeldung werden so in die Datei /var/log/php_error protokolliert. Wieso ist es ein Sicherheitsproblem, wenn man Fehlermeldungen über den Webserver ausgibt? Ganz einfach, diese Fehlermeldungen verraten dem Angreifer sehr viele Informationen über den Server und auch über die PHP Anwendung (z.B. den absoluten Pfad des PHP Skriptes, woraus man eventuell auch wieder schließen kann, wo andere Dateien auf dem Server zu finden sind)
  • enable_dl = Off Durch diese Einstellung unterbindet man, dass über PHP Skripte Module automatisch nachgeladen werden dürfen.
  • allow_url_include = Off Dadurch wird verboten, dass URLs (z.B. http:// oder ftp://) in Verbindung mit include oder required Anweisungen verwendet werden können.
  • disable_functions = system, shell_exec, popen, pclose, proc_open, proc_close, proc_get_status, proc_nice, proc_terminate, exec, passthru, show_source, readfile, escapeshellcmd, escapeshellarg Alle hier aufgeführten Funktion werden deaktiviert und können daher nicht mehr in PHP Skripten verwendet werden. Allerdings muss man hierbei aufpassen, da sehr viele Skripte einige dieser Funktionen benötigen. Man sollte also Tests durchführen, ob die PHP Anwendungen noch funktionieren, wenn man diese Funktionen ausschliesst. Wieso sollte man diese Funktionen ausschliessen? Weil dadurch die Einschränkung von open_basedir umgangen werden kann.
  • open_basedir = "/pfad/zu/meinem/php/projekt" Hier kann man festlegen, auf welche Verzeichnisse innerhalb eines PHP Skriptes zugegriffen werden darf. Vorsicht ist geboten, da bestimmte Funktionen diese Einschränkung nicht beachten (siehe disable_functions). Hierbei sei besonders die Erweiterung curl genannt! In zukünftigen PHP Versionen soll open_basedir und auch safe_mode komplett aus der Feature-Liste gestrichen werden, da diese nur eingeschränkt als Sicherheitsmaßnahmen eingesetzt werden können. PHP Sicherheitsparameter werden nie eine Webserver Jail-Root-Umgebung ersetzen können, diese sind/waren einfach nur komfortabler für den Webmaster umzusetzen.
  • PHP Erweiterungen deaktivieren In den meisten Linux Distributionen werden PHP Erweiterungen als zusätzliche Pakete angeboten, die jederzeit auch deinstalliert werden können (Shared Libraries). Leider sind aber meist mehr Modul installiert/aktiviert, als man benötigt. Auch hier gilt, dass jede unnötige Erweiterung ein unnötiges Sicherheitsrisiko darstellt. Man sollte also die Anzahl der benötigten PHP Erweiterungen auf ein Minimum begrenzen.

Allgemein Ratschläge für Anwendungen

  • Immer die aktuellste (stabile) Software vom Hersteller einsetzen. Fast mit jedem Update einer Software werden auch Sicherheitslöcher geschlossen. Für diese Sicherheitslöcher existieren sehr häufig auch Exploits, die es auch Nicht-Profis sehr einfach machen, Sicherheitslücken auszunutzen.
  • Aktuelle Erweiterungen verwenden. Vielen Leuten ist anscheinend nicht bewusst, dass wenn Sie eine Mod/Erweiterung z.B. in Ihr Board installieren, dass diese Erweiterung ein potentielle Sicherheitslücke darstellen kann. Es ist also genauso wichtig, wie die Basissoftware auch, jede einzelne Erweiterung aktuell zu halten!
  • Wenn der Adminbereich vom eigentlichen Ausgabebereich getrennt ist, sollte man den Adminbereich mit einen .htaccess Schutz belegen.
  • Backup Dateien gehören nicht ins DOCUMENT_ROOT Verzeichnis!! Die sicherste Konfiguration wird überflüssig, wenn man seine Backup-Dateien ins Webverzeichnis legt, über diesen theoretisch jeder User aus dem Internet diese Dateien herunterladen könnte. Da in den Backupdaten meist neben den wertvollen Daten auch die Quelldateien der Skripte vorhanden sind, hat der Hacker alles was er benötigt, um einen Angriff zu starten. Das Datenbank-Kennwort befindet sich ja bekanntlich in einer Konfigurationsdatei, die der Angreifer somit auch erhalten hat. Meist werden für die Backup-Dateien dann auch noch backup.sql oder backup.zip (oder ähnliche Namen) verwendet, was schon fast fahrlässig ist. Richtig macht man es, indem man die Backup Dateien auf einen anderen Server oder ein externes Backup-Medium ablegt. Viele Server-Hosting Anbieter haben ein externes Speichermedium schon im Paket-Bundle mit integriert. Falls man wirklich die Daten auf dem gleichen Server ablegen will, da müssen diese Daten ausserhalb des DOCUMENT_ROOT Verzeichnisses abgelegt werden. Also in ein Verzeichnis, welches über den Webserver nicht erreichbar ist.
  • phpMyAdmin mit Kennwortschutz verwenden Falls man phpMyAdmin für die Datenbankverwaltung einsetzt, sollte man darauf achten, dass man einen Kennwortschutz verwendet. phpMyAdmin bietet verschiedene Authentifizierungsmethoden an: config, http, HTTP, signon oder cookie.
  • Unterschiedliche Kennwörter verwenden Man sollte für jedes Projekt unterschiedliche Kennwörter verwenden, das ist besonders wichtig, wenn es sich um administrative Accounts handelt. Auch sollte man für den .htaccess Schutz ein anderes Kennwort wählen als für den normalen Login. Als Kennwort sollte man nur sichere Kennwörter verwenden, um Brute Force Attacken keine Change zu geben (zumindest kann man die Wahrscheinlichkeit des Erratens um ein Vielfaches verringern). Kennwörter wie die Telefonnummer, Wörterbuch-Einträge oder Geburtsdatum sollte man nicht benutzten - aber leider ist das immer noch Normalität bei vieler Benutzern.
  • Benutzerkreis für Administratoren-Zugang sehr klein halten Jeder Benutzer, der Zugang zum Administrationsbereich einer Anwendung hat, vergrößert das Sicherheitsrisiko. Das liegt nicht daran, dass man diesen Benutzern nicht vertraut, sondern daran, dass menschliche Fehler (z.B. durch Social Engineering) auftreten können. Da bei jedem Admin-Benutzer (wie auch bei allen anderen Benutzern) sich ein Trojaner auf den PC befinden könnte, der fleißig alles mitprotokolliert, was der Benutzer so eintippt, sollte man wirklich versuchen, den Personenkreis auf ein Minimum zu begrenzen.

Weiterführende Tipps zu folgender Software:

Aktualisiert: