Überfliege ich die Logs meiner Server mit direkter Verbindung ins Internet, dann sehe ich unzählige, protokollierte Angriffe. Fast stündlich gibt es fehlgeschlagene Login-Versuche und ab und an versucht sich sogar jemand an einer DDOS-Attacke. Meine Loadbalancer, Proxies und Webserver sind ganz gut mit der Abwehr dieser mal besser und schlechter ausgeführten Angriffe ausgelastet.
Damit ich nachts ruhig schlafen kann, härte ich meine Systeme so gut es geht. Ich bin zwar kein Ethical-Hacker, aber ein paar sinnvolle Tricks & Kniffe kenne ich schon. Aufgrund dessen habe ich mich dazu entschieden, einen sehr umfangreichen Beitrag zu verfassen, wie ich meine Apache2-Webserver gegen bekannte Angriffe absichere. Das Lesen lohnt sich also!
Wie laufen Attacken auf Webserver eigentlich ab?
Wenn es um die Härtung von Systemen geht, muss man deren Funktionsweise genau verstehen. Auch in puncto Webserver gilt dies Grundsatz. Heutzutage besteht ein Setup schließlich nicht mehr aus dem Apache-Daemon und ein bisschen HTML und CSS für die Gestaltung des Inhalts. Moderne Websites oder genauer gesagt deren Content-Management-Systeme wie WordPress oder Joomla setzen auf Datenbanken.
Angreifer können sich also über diverse Wege Zugang zu den Ressourcen verschaffen. Jede Schicht muss dabei anders geschützt werden. Grob lässt sich mein Vorgehen dabei in 2 Bereiche unterteilen: Der Schutz des zugrundeliegenden Betriebssystems sowie die Härtung der installierten Dienste. Und Letzteres spielt eine große Rolle. Vielleicht hast du schon mal den Begriff LAMP gehört.
Hierbei handelt es sich um ein Akronym für die Begriffe: Linux Apache MySQL PHP. Um den heutigen Webhosting-Anforderungen gerecht werden zu können, muss auf der Maschine eine ganze Menge an Software laufen:
- Das zugrundeliegende Linux-Betriebssystem, wie zum Beispiel Debian, Ubuntu, Suse oder RHEL.
- Die Webserver-Software in Form von Apache2 oder Nginx. Bei der Verwendung von Letzterem spricht man von LEMP.
- In puncto Datenbank wird häufig auf MySQL oder dessen freies Pendant MariaDB zurückgegriffen.
- Ohne das installierte PHP-Modul bringt eine Datenbank wenig. Irgendwie müssen die Daten nämlich ausgelesen werden.
Ein Webserver ist heutzutage gar nicht mehr so trivial in der Administration. Und wenn man sich dann noch mit Loadbalancern und Datenbankclustern beschäftigt, wird das ganze nochmal spaßiger. Aber keine Sorge, soweit werde ich es hier nicht treiben. In diesem Artikel gehe ich nämlich vom einfachsten Anwendungsfall aus. Die Rede ist natürlich von einer Single-Installation mit Ubuntu als Grundlage.
Wogegen sollte man sich denn nun schützen?
Nachdem wir jetzt ein paar grundlegende Dinge für den Beitrag geklärt haben, möchte ich nun erläutern, mit welchen Attacken ich so im Alltag konfrontiert werde. Natürlich sind meine Logeinträge und die gemachten Erfahrungen der letzten Jahre nicht repräsentativ für den deutschsprachigen Raum. Mit großem Abstand führen aber Brute-Force-Angriffe mein kleines Ranking an.
Es handelt sich hier, um ganz plumpe Versuche das Passwort zu knacken. Im Prinzip wird hier einfach wild drauflos geraten. Nicht selten werden dabei auch noch Benutzernamen verwendet, die gar nicht existieren. Als Passwortquelle wird nicht selten auf ein ganzes Wörterbuch gesetzt. Auch Listen mit beliebten Passwörtern werden stur durchprobiert.
Ebenfalls beliebt ist das Ausnutzen von Sicherheitslücken. Werden Server lange nicht gepatcht, haben Angreifer hier meist leichtes Spiel. Wer also eher unregelmäßig Aktualisierungen einspielt, sollte zumindest die Security-Updates automatisch durch die Paketverwaltung installieren lassen. Aber dazu später noch mehr. Diese Art von Attacke lässt sich nämlich noch deutlich eleganter ausführen.
So kann man mithilfe von einfachen Portscannern wie Nmap gezielt Sicherheitslücken aufspüren. Schlecht aufgesetzte Apache-Server liefern im Header nämlich gleich alle nötigen Informationen frei Haus. Zumindest fehlt hier noch das verwendete Betriebssystem. Aber keine Sorge! Wer den SSH-Port scannt, kann hier nicht selten binnen weniger Sekunden das eingesetzte Linux auslesen.
Und als wäre der Versuch des Eindringens in fremde Systeme nicht schon schlimm genug, kann man diese immer noch recht einfach lahmlegen, wenn das neue Skript aus dem Darknet doch nicht so gut in puncto Hacking funktioniert. Viele Webserver haben nämlich nicht mal ein Modul installiert, das simple Distributed Denial oft Service Attacken von ein paar Bots abwehrt.
Wie kann man einen Webserver gegen Angriffe absichern?
Kommen wir nun endlich zum Kernaspekt dieses Ratgebers. Der erste Punkt auf meiner Checkliste ist hier immer das installierte Betriebssystem. Eigentlich muss man es auf diesem Blog gar nicht erwähnen, aber es wird nur zu gerne vergessen oder einfach verdrängt. Ein Webserver ist im Prinzip nichts anderes als ein Computer, der für jeden frei verfügbar im großen WWW steht.
Updates, Updates und nochmal Updates:
Daher ist die erste Anlaufstelle bei der Härtung immer die installierte Linux-Distribution. Ich setze hier meist auf Ubuntu oder Debian. Selbstredend sollte man hier immer zeitnah alle Patches einspielen. Nur ist das häufig leichter gesagt als getan. Wer seine Umgebung nämlich noch nicht mit Tools wie Ansible oder Puppet automatisiert hat, dem geht häufig die Zeit aus.
In so einem Fall würde ich die Installation der Sicherheitsaktualisierungen automatisieren. Das geht recht einfach und vor allem schnell von der Hand. Man muss lediglich das Paket unattended-upgrades installieren und noch ein paar wenige Einstellungen vornehmen. Zu Beginn erstellst du unter Ubuntu die Datei /etc/apt/apt.conf.d/50unattended-upgrades.
Inspirieren lassen, kannst du dich dabei von der Vorlage im selben Verzeichnis mit dem wunderschönen Namen 50unattended-upgrades.ucf-dist Am Ende könnte deine Konfiguration dann so aussehen:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::DevRelease "auto";
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::MailReport "on-change";
Nur mit der obigen Datei ist es nicht geschafft. Aber keine Sorge. Lediglich eine weitere Datei will noch mit Inhalten befüllt werden. Die Rede ist von /etc/apt/apt.conf.d/20auto-upgrades Die Konfiguration könnte dabei wie folgt lauten:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
Wenn du meinen Code 1 zu 1 in die beiden Dateien kopierst, werden in Zukunft alle notwendigen Security Updates von alleine installiert. Trotzdem rate ich dir dazu, regelmäßig Patches bei deinen Webservern einzuspielen. Ich selbst kümmere mich um diesen wichtigen und leider viel zu häufig sträflich vernachlässigten Punkt einmal pro Woche.
Ohne eine portbasierte Firewall geht bei mir nichts:
In der Praxis gilt vor allem eins: Nur die benötigten Ports sind offen, der Rest bleibt einfach zu. Wie du siehst, mache ich es mir in diesem Abschnitt nicht zu kompliziert. Was liegt da näher, als dir die Uncomplicated Firewall (ufw) zu empfehlen. Sie lässt sich binnen einer Minute einrichten und scharf schalten. Welche Befehle du dafür brauchst, habe ich dir natürlich aufgelistet:
# Installation der Firewall:
sudo apt install ufw
# Eingehenden Verkehr Erstmal blocken & ausgehenden Traffic gewähren:
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Anlegen der grundlegenden Regeln:
sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
# Konfigurierte Regeln anzeigen lassen:
sudo ufw status verbose
# Firewall scharf schalten:
sudo ufw enable
# Firewall Status prüfen:
sudo ufw status
Eigentlich muss ich es gar nicht erwähnen, denn meine Leser sind erfahrene Admins. Aber im Rahmen des Kopierens & Einfügens passieren halt gerne mal Fehler. Prüfe daher die 3 Regeln gründlich. Sollte dein SSH-Dienst nämlich auf einen anderen Port lauschen oder du benutzt eine Kombination aus Reverse-Proxy mit Docker-Containern, dann brauchst du angepasste Rules.
Und wenn du gar keine Lösung wie ufw oder Firewalld in Betrieb nehmen möchtest, dann prüfe doch mal, ob dein Hoster eine kostenlose, portbasierte Firewall anbietet. Das tun inzwischen nämlich die meisten und man belastet die Ressourcen seines eigenen Servers nicht. Selbstredend kann man auch in gängigen Hypervisoren solche einfachen Rules anlegen:
Und wer jetzt Blut geleckt hat, der kann sich auf die weiteren Abschnitte dieses XXL-Beitrags freuen. Ich werde nämlich noch die Installation und Einrichtung einer Web-Application-Firewall behandeln. Dazu aber später mehr. Hier sei stattdessen noch gesagt, dass man hinter einer Next-Generation-Firewall, wie der kostenlosen Sophos XG Home eine sehr potente DMZ einrichten kann.
Und der Clou an der Sache ist der, dass man dafür keine dedizierte Hardware braucht. Es gibt nämlich fertige Images für alle gängigen Virtualisierungslösungen wie Proxmox VE oder VMware ESXI. Und warum die DMZ damit so leistungsfähig wird? Weil man den eingehenden Traffic nach Herzenslust auf den Layern 4 bis 7 filtern kann. Sogar HTTPS-Verkehr kann damit untersucht werden.
SSH ist nicht automatisch sicher:
Häufig wird dieser Punkt bei der Serverhärtung recht stiefmütterlich behandelt. Aber gerade hierüber kann man schnell einen vollständigen, administrativen Zugang erlangen. Und genau das sollte man zu verhindern wissen. Wie ich dabei vorgehe, verrate ich dir in den folgenden Zeilen.
Wenn man mit Passwörtern arbeiten möchte, sollten diese mindestens 20 Zeichen lang sein. Empfehlenswerter ist aber der Einsatz von einem Public- sowie einem dazu gehörenden Private-Key. Hier empfehle ich die Verwendung des Algorithmus Ed25519, welcher seit OpenSSH Version 6.5 unterstützt wird. Ebenfalls noch nutzbar wäre der altbewährte Klassiker RSA mit einer Mindestlänge von 4096 Bit.
Der private Schlüssel sollte darüber hinaus mit einem Passwort gesichert sein. Sollte der Key nämlich in fremde Hände gelangen, muss vor der böswilligen Nutzung, die Passphrase geknackt werden. Auch hier gilt wieder die Faustformel, umso länger das Passwort, desto schwerer macht man es dem Hacker. Und da ich in diesem Artikel alles erklären will, gehe ich noch kurz auf die Erstellung ein:
# Schlüsselpaar für die Anmeldung via SSH unter Linux erstellen:
ssh-keygen -t rsa -b 4096
# Den öffentlichen Schlüssel auf den Server kopieren:
ssh-copy-id -i ~/Pfad/zur/öffentlichenSchlüsseldatei benutzer@server
# Anmeldung mit dem Private Key testen:
ssh -i ~/Pfad/zur/privatenSchlüsseldatei benutzer@server
Die Verwendung der Public-Key-Authentifizierung macht unseren Webserver auf alle Fälle deutlich resistenter gegen SSH-Brut-Force-Angriffe. Ich gehe an diesem Punkt aber sogar noch einen Schritt weiter. Ich lege einen User an, der mir nur zur Anmeldung am System dient. Der Benutzer ist also kein Mitglied in der Gruppe Sudo und hat zudem als einziger die Berechtigung sich via SSH zu verbinden.
Warum dieses Vorgehen weiteren Schutz bietet, liegt auf der Hand. Hat man es geschafft den Zugang über den SSH-User zu erlangen, kann man trotzdem keinerlei administrative Tätigkeiten am System ausführen. Man muss nämlich erst zu root werden und dafür braucht man ein weiteres Passwort. Wie man das konkret umsetzt, willst du wissen? Hier steht es geschrieben:
# Root unter Ubuntu aktivieren:
sudo passwd root
# Zu root werden:
su root
# Den vorhandenen Sudo-fähigen Benutzer löschen:
deluser Benutzer
# Gruppe für SSH-Zugang anlegen:
addgroup sshers
# Unprivilegierten User sammy anlegen:
adduser sammy
# sammy soll nun Teil der SSH-Zugangsberechtigten werden:
usermod -aG sshers sammy
# Den Pub-Key bei sammy zur Anmeldung hinterlegen
ssh-copy-id -i ~/Pfad/zur/öffentlichenSchlüsseldatei sammy@server
# Die SSH-Konfig unter /etc/ssh/sshd_config anpassen:
AllowGroups sshers
PasswordAuthentication no
PubkeyAuthentication yes
# Den SSH-Daemon neustarten:
systemctl restart ssh oder service ssh restart
# Anmeldung mit dem Private Key testen:
ssh -i ~/Pfad/zur/privatenSchlüsseldatei sammy@server
SSH lässt sich noch weit granularer härten. Beispielsweise kann man den Standard-Port 22 gegen Port 5930 tauschen. Ebenfalls sinnvoll ist es, nur sichere Cipher wie chacha20-poly1305@openssh.com, aes256-gcm@openssh.com, aes256-ctr zuzulassen. Darüber hinaus sollte man die maximal möglichen Anmeldeversuche auf 3 begrenzen und nur das SSH-Protokoll 2 erlauben.
Wer hier noch tiefer in die Materie einsteigen möchte, sollte sich am besten unter man.openbsd.org/sshd_config weiter informieren. Ich belasse es hier erstmal bei den vorgestellten Basics. Aber ein Ass habe ich noch im Ärmel. Schließlich soll die Praxis bei all der Theorie nicht zu kurz kommen.
Zum Abschluss der grundlegenden Härtung des Betriebssystems testen wir mal die korrekte Funktionsweise unserer Einstellungen. Dafür greifen wir auf den bekannten Portscanner Network Mapper (Nmap) zurück. Er lässt sich unter Debian und dessen Derivaten mittels apt install nmap installieren. Wir nutzen als Befehl einfach nmap -A webseite.tld
Mithilfe der Option -A wird ein sehr umfangreicher Scan am Webserver durchgeführt. Konkret bedeutet das, dass Nmap hier nicht nur nach offenen Ports sucht, sondern auch gleich den dahinter lauschenden Dienst identifizieren möchte. Weiterhin wird versucht das eingesetzte OS zu ermitteln und das gelingt uns im Test auch. Man muss sich nur mal die Ausgabe des SSH-Ports ansehen.
Hier gilt es also schleunigst nachzubessern. Zum Glück reicht es in der SSH-Konfiguration, die Angabe DebianBanner no am Schluss zu ergänzen. Nach einem Restart des SSH-Daemons, ist die Sicherheitslücke geschlossen. Doch was lernen wir aus dieser Situation? Server müssen regelmäßig gescannt werden. Aber nicht mit nmap, sondern mit Tools wie Lynis.
Teil 1 dieser Serie findet nun sein Ende:
Das war Part 1 meiner Artikelserie zur Härtung von LAMP-Stacks auf Basis von Ubuntu als Betriebssystem. Wie du bereits gemerkt hast, ist dieses Thema sehr umfangreich und daher werde ich immer mal wieder einen neuen Teil mit weiteren, sehr spannenden Aspekten der Webserver-Härtung herausbringen.
Du darfst dich dabei auf vieles freuen: Die Einrichtung einer Web-Application-Firewall, mithilfe des Apache-Moduls Evasive DDOS-Attacken abwehren und das System mit nmap scannen und die Findings beheben. Außerdem will auch die PHP-Integration und der Datenbankserver gehärtet werden. Und Software wie WordPress oder Nextcloud braucht auch noch mal einiges an Zuwendung.
2 Antworten auf „Part I: Wie ich meine Apache-Webserver härte!“
Super erklärt! Kommt noch der Part 2?
Hallo Christian,
vielen Dank für deinen lieben Kommentar. Ich kann natürlich nichts garantieren, aber ich habe den fehlenden zweiten Teil natürlich noch auf dem Schirm.