Den Webserver absichern

Den Webserver absichern

Du hast einen Webserver installiert? Nein? Dann lies noch dieses Tutorial hier. Einfacher als die dort beschriebene Anwendug geht gar nicht. Wenn der Webserver läuft, musst du diesen Server absichern, wo immer es dir möglich ist.

Apache: Verzeichnisbrowser

Hinweis: Bevor du deinen Apache neu startest, prüfe jede Änderung der .conf-Dateien mit dem Shell-Befehl sudo apachectl configtest

Apache2.x erlaubt per Standard, dass du dich durch Verzeichnisse klicken kannst. Üblicherweise wird das für File-Download-Seiten gemacht, bei denen man nicht wirklich eine schöne Oberfläche braucht. Oft wird das zum Beispiel bei Spiegelservern von Linuxdistributionen gemacht. Siehe auch hier: Debian

Die Sicherheitslücke besteht darin, dass man theoretisch alle PHP-Skripte aufgelistet bekommt und aufgrund dessen explizit bestimmte Files aufrufen könnte. Daher ist es wichtig, das sogenannte Directory-Indexing zu verbieten. Das ist allerdings sehr einfach zu realisieren. Die einfache Methode ist es in der Datei /etc/apache2/apache2.conf im Verzeichnis /var/www/ die Zeile Options -Indexes zu hinterlegen.

Deaktiviere Module

Die brachialere Methode, die Indexing generell unterbindet besteht darin, das Index-Modul komplett zu deaktivieren.

sudo a2dismod -f autoindex

Das -f steht hier auch wirklich für force, denn wenn man das nicht tut, warnt Apache2 einen, dass dieses Modul wichtig ist.

Je mächtiger ein Server ist, desto schwerer ist der Server zu warten. Apache2 liefert in der Standard-Installation viele, viele Module mit. Welche Module das sind, kannst du dir anzeigen lassen. Der Befehl sudo apache2ctl -M listet dir alle aktuell installierten Module auf.

Man kann aber nicht sagen, welche Module du zwingend benötigst und welche nicht.

Das ist immer abhängig von deinem Projekt, aber es gibt tatsächlich Module, die man auf Liveservern nicht unbedingt benötigt, bzw. die man wirklich zwingend abschalten sollte:

mod_status: Mod_status ist dazu da, den Status des Servers anzuzeigen. Die Anzahl der Threads wird ebenso aufgelistet, wie die Anzahl von Aufrufen und so weiter. Diese Informationen sind in Testumgebungen wichtig, auf einem Liveserver sind solche Informationen eher kritisch, da man als potentieller Hacker direkt sehen kann, wieviel Speicher beispielsweise belegt wird. Solche Lücken kann man ausnutzen. Auf einem Liveserver würde ich diese Mod deaktivieren und deinstallieren. sudo a2dismod mod_status

mod_autoindex: Wie oben bereits erwähnt, sollte man überlegen, ob man das Browsen durch Verzeichnisse generell nicht lieber abschalten sollte: sudo a2dismod -f autoindex

Mach es den bösen schwerer

Apache Version nicht mehr anzeigen: Webserver sind unfassbar mächtige Programme und müssen alles mögliche an Anfragen und Antworten verarbeiten. Natürlich gibt es deshalb immer wieder kleine oder auch größere Sicherheitslücken, die in Version 2.4.x da sind, in 2.4.y aber nicht mehr. Um es den Angreifern nicht zu einfach zu machen, sollte man den Usern gar nicht erst anzeigen, welche Apache-Version verwendet wird. Das ist zwar irgendwo security trough obscurity, dennoch hilft es.

Schreibe in die Datei /etc/apache2/conf-available/security.conf also folgende Zeilen noch rein: Beachte, dass ServerTokens eventuell schon an anderer Stelle hinterlegt wurde. ServerSignature sollte auch auf off gestellt werden.

ServerTokens Prod
ServerSignature Off

Bevor du deinen Webserver neu startest, prüfe, ob die Konfiguration noch immer gültig ist. Fehler werden dir mit diesem Befehl direkt angezeigt. Du kannst diese Fehler beheben, bevor du versehentlich deinen Server abschaltest.

sudo apache2ctl configtest

Es gibt ein spezielles Modul zum Absichern des Apachen. Dieses Modul nennt sich mod_security. Eine sehr umfassende Beschreibung dieses Moduls gibt es hier: https://wiki.ubuntuusers.de/Apache/mod_security/ und eine umfangreiche Anleitung mit Konfigurationstipps kannst du dir hier anschauen: https://www.howtoforge.de/anleitung/sichere-dein-apache-mit-mod_security/

PHP absichern

Die PHP-Konfigurationsdatei nennt sich php.ini und befindet sich bei Ubuntu normalerweise unter /etc/php/7.x/apache2/php.ini

Zuerst mal sollte keiner mitbekommen, dass du PHP verwendest. Das erreichst du indem über die php.ini den Switch expose_php auf off setzt.

Anschließend kannst du noch festlegen, dass PHP-Scripts nur aus bestimmten Verzeichnissen gelesen werden. Innerhalb der php.ini gibt es den open_basedir-Parameter. Das legt fest, dass PHP-Skripte ausschließlich aus diesem Pfad (und denen darunter) aufgerufen werden dürfen.

open_basedir = /var/www/ legt fest, dass Skripte vom Webserver ausschließlich aus diesem Verzeichnis geladen werden dürfen. Ein Include aus einem Verzeichnis darüber wäre nicht mehr möglich, PHP bricht dann mit einer Fehlermeldung ab.

Du solltest auch prüfen, ob es notwendig ist, Remote-Dateien per fopen öffnen zu können. Setze allow_url_fopen daher auf 0

allow_url_fopen=0

Gobale Variablen werden mit register_globals=off deaktiviert. Ich erwähne das nur, weil dieser Switch einen der größten Design-Fails in PHP darstellt. Damals ging so etwas wie ?index=12345 und in PHP stand dann automatisch die Variable $index zur Verfügung. Falls diese Variable innerhalb der Programmierung auf nicht gesetzt geprüft wurde und abhängig davon eine Funktion ausgeführt wurde, war das Skript damit schon komprimittiert.

memory_limit = xyz MB legt fest, wie viel Speicher dein Skript zur Laufzeit belegen darf. Höhere Memory-Limits sorgen dafür, dass du mit PHP auch größere Datenmengen verarbeiten kannst, gleichzeitig ist es aber auch so, dass kleinere Memory-Limits (angepasst an die jeweilige Anwendung), sicherstellen, dass dein Skript auch nur Dateigrößen verarbeitet, die du auch erwarten würdest. So was wie Drupal oder Wordpress braucht hier 16 MB, ich habe durchaus aber auch mal mit sehr großen Datenbank-Mengen zu arbeiten, leider ist der Wert entsprechend höher gestellt.

Der Parameter max_input_time = 60 legt fest, wie lange PHP für die Verarbeitung von Eingabewerten brauchen darf. Angenommen, du legst fest, dass eine Datei mit 500 MB über POST gesendet wirst, die Leitung ist aber sehr langsam, dann bricht dein Skript ab. Kurze Input-Zeiten sichern ein wenig vor DDOS-Angriffen ab. Die 60 Sekunden finde ich persönlich ausreichend.

max_execution_time = 60 - wie lange darf ein Skript laufen, bevor es als fehlerhaft abgebrochen wird? Es gibt durchaus Skripte, die wirklich langwierige Operationen durchführen, allerdings wartet im Web eh keiner länger als 10 Sekunden auf sein Ergebnis. Hier solltest du prüfen, welche Programmteile echt lange brauchen und zuerst die Laufzeit dieser Skripte durch Refactoring/Optimierung so sehr verkürzen, wie möglich. Falls das immer noch nicht reicht, taste dich an einen guten Wert ran. Oder nimm halt die 60 Sekunden ­čśë

session_save_path = /var/tmp/sessions/ - Normalerweise ist der Pfad für Sessions in PHP nicht gesetzt. Es greift also der Standardpfad für temporäre Dateien. Es ist ja schön, dass das läuft. Böse Menschen könnten allerdings diesen Pfad erraten, also solltest du einen Pfad nehmen, der eben nicht sofort erraten wird. Stelle sicher, dass das Verzeichnis auch wirklich existiert.

MySQL sichern

Die Datenbank MySQL (ich springe immer zwischen verschiedenen Schreibweisen hin- und her, gemeint ist immer Oracles Open Source Datenbank) ist in der Standard-Installation schon ziemlich sicher. Ein paar Kleinigkeiten kann man zur Verbesserung der Sicherheit noch machen.

Erstelle dir einen User für Webanwendungen, der nur so viele Rechte hat, wie für den Betrieb der Webanwendung notwendig sind. 99,99 % aller Webanwendungen müssen nicht zwangsläufig das Recht haben, eine Datenbank zu erstellen oder gar Datenbanken zu löschen. Im Idealfall baust du dir pro Projekt einen User auf, der ausschließlich Rechte in der Projekt-Datenbank hat und sonst nichts weiter darf. Angenommen, du hast ein Wordpress und die Datenbank heißt Wordpress, dann sollte dein User Blogger auch nur Rechte für die Datenbank haben.

Diese Rechte sollten auf das nötigste beschränkt werden. DROP, CREATE, ALTER sind normalerweise für den Betrieb einer Websoftware nicht nötig, aus Bequemlichkeit räumt man diese Rechte aber oft dennoch ein.

Optional kannst du auch festlegen, dass MySQL ausschließlich über LAN zu erreichen ist. In der my.ini kannst du über den Parameter

bind-address=127.0.0.1

festlegen, dass ausschließlich vom Rechner selbst auf den Rechner zugegriffen werden soll. Falls deine Websoftware auf einem anderen Server, als die Datenbank läuft, würdest du die IP des Web-Servers hier angeben.

Viel schwerwiegender sind allerdings Angriffe über SQL-Injections. Diese Angriffe haben nicht zwangsläufig mit MySQL zu tun, sondern mit schlecht gemachten (PHP)-Skripten. Es würde zu weit führen, wenn ich dir jetzt erkläre, wie du SQL-Injections unterbindest. Es gilt immer die Regel, dass jeder Input validiert werden sollte. Ein gutes Tutorial zum Thema SQL-Injections findest du hier: https://www.w3schools.com/sql/sql_injection.asp

Let's Encrypt (SSL-Zertifikat für deinen Server)

Mittlerweile wird von Webseitenbetreibern erwartet, dass deren URLs nur noch über das verschlüsselte HTTPS ausgegben werden. Früher haben SSL-Zertifikate verhältnismäßig viel gekostet, dank Letsencrypt kann man sich ein solches Zertifikat kostenlos installieren.

Die Installation ist ziemlich einfach: Du musst das PPA von Letsencrypt einbinden und dann Certbot installieren. Der Certbot macht den Rest und auf meinem Server hatte das damals einfacher funktioniert, als die Einrichtung eines Webservers ­čśë

Let's Encrypt: Certbot installieren

sudo add-apt-repository ppa:certbot
sudo apt update
sudo apt install python-certbot-apache

Nachdem Certbot installiert ist, kannst du certbot --apache -d domain.tld ausführen. Anschließend verändert certbot deine Apache-Konfiguration und das Zertifikat wird eingebunden.

Certbot kümmert sich auch um die automatische Erneuerung deines SSL-Zertifikates. Der entsprechende cronjob befindet sich unter etc/cron.d/certbot

Let's Encrypt: Zertifikat prüfen

Du kannst unter SSL-Labs.com dein Zertifikat prüfen, einfach deine Domain dort eingeben

Bitte beachte, dass ich hier eine feste IP-Adresse voraussetze. Bei dynDNS-Servern ist die Vorgehensweise vielleicht anders, habe ich noch nicht ausprobiert

Weitere Sicherheitstipps

Das Tutorial könnte endlos weiter geführt werden, weil natürlich jedes Feature eines Servers immer gleichzeitig eine Sicherheitslücke darstellen kann. Ich fasse hier nun noch ein paar Tipps zusammen:

SSH Port ändern

Der Standard-Port für OpenSSH ist 21. Ändere den Zugriffsport für SSH-Verbindungen auf eine andere Zahl, z.B. 4711, um das Offensichtliche zu unterbinden. Öffne die Datei /etc/ssh/sshd_config und schreibe hinter PORT anstatt der aktuellen 22 eine Zahl, die idealerweise zwischen 30.000 und 65.535 liegt.

Fail2Ban

Fail2Ban ist ein Daemon/Service, der im Hintergrund prüft, wie oft jemand versucht hat, sich fehlerhaft einzuloggen. Bei mehrfachen Fehlern wird die IP-Adresse des Users für eine bestimmte Zeit gesperrt. https://www.thomas-krenn.com/de/wiki/SSH_Login_unter_Debian_mit_fail2ban_absichern

Fazit

Auch die Absicherung eines Webservers ist kein Hexenwerk. Wie gesagt, man kann unendliche viele weitere Dinge berücksichtigen und hinterlegen. Daher kann ich diese Reihe auch noch unendlich lange fortführen, was ich auch tun werde :)

Leider hat hier noch keiner seinen Senf zum Thema abgegeben. Sei du doch der erste. Oder die erste. Oder das letzte.

├ťber...

Diese Website nutzt Cookies. Wof├╝r genau, steht hier: Zum Thema Cookies und nat├╝rlich in der Datenschutzerkl├Ąrung. Hab ich verstanden