Linux Hardening - Die eigene Medizin nehmen

Linux Hardening

Die eigene Medizin nehmen

Michael Schneider
von Michael Schneider
Lesezeit: 11 Minuten

Keypoints

Darum ist Hardening nicht einfach

  • Hardening-Massnahmen in der Praxis angewandt
  • Linux-Hardening auf Basis von CIS Benchmarks und Audit mit Lynis
  • Zugriff auf administrative Schnittstellen nur über Jumphost
  • Restriktive Firewall-Regelwerke für ein- und ausgehende Verbindungen auf jedem Host
  • Interne Kommunikation verschlüsseln am Beispiel von rsyslog

Für unsere Dienstleistungen wie Web Application Penetration Test oder Adversary Simulation benötigen wir eine stabile und jederzeit verfügbare Infrastruktur. So betreiben wir unter anderem eine eigene Instanz des Burp Collaborators. Wir haben kürzlich beschlossen die Infrastruktur zu erneuern und dabei all das umzusetzen, was wir in Linux-Hardening-Assessments unseren Kunden empfehlen. In diesem Beitrag beschreiben wir mögliche Hardening-Massnahmen und wie wir diese in unserer Infrastruktur umgesetzt haben.

Für das Hardening von Linux-Systemen verwenden wir eigene Checklisten, die auf CIS Benchmarks basieren. Es gibt einen distributionsunabhängigen Benchmark und weitere für verbreitete Linux-Distributionen wie Red Hat, Fedora, CentOS, Debian, Ubuntu und SUSE Linux. Die Benchmarks sind zudem nützlich für die Definition von eigenen Hardening-Vorgaben.

Um ein gehärtetes Linux-System zu auditieren, setzten wir das Tool Lynis ein. Lynis führt sowohl Prüfungen der Betriebssystemkonfiguration als auch Kontrollen installierter Dienste wie SSH, Apache oder Samba durch. Der Report des Lynis-Scans listet Resultate auf und gibt zu jedem Punkt Verbesserungsvorschläge und Gegenmassnahmen an.

Daniel Aleksandersen stellt in seinem Artikel systemd service sandboxing and security hardening 101 das systemd-Audit-Tool vor. Damit können alle systemd-Dienste auf deren Konfiguration und Nutzung von Sicherheitsdirektiven überprüft werden. Diese Prüfung sollte vor allem bei Diensten durchgeführt werden, die gegenüber dem Internet exponiert sind oder Benutzer-Eingabedaten verarbeiten. Es gibt unter anderem diese Direktiven:

Ein Audit der systemd-Dienste kann mittels systemd-analyze security gestartet werden. Durch Angabe des Dienstnamens kann der Dienst auf dessen Direktiven untersucht werden. Das Analyse-Tool setzt als eines der ersten, mir bekannten, Kommandozeilenprogramme auf Emojis:

[user@host ~] systemd-analyze security
UNIT                                  EXPOSURE PREDICATE HAPPY
NetworkManager.service                     7.7 EXPOSED   🙁
auditd.service                             8.7 EXPOSED   🙁
crond.service                              9.6 UNSAFE    😨
dbus-broker.service                        8.6 EXPOSED   🙁
...
sshd.service                               9.6 UNSAFE    😨
...
systemd-coredump@0.service                 3.4 OK        🙂
systemd-initctl.service                    9.5 UNSAFE    😨
systemd-journald.service                   4.4 OK        🙂
systemd-logind.service                     3.0 OK        🙂

Durch die Verwendung dieser Direktiven kann die Systemsicherheit mit einfachen Mitteln verbessert werden. Das Verhalten des Dienstes mit den neu gesetzten Direktiven sollte jedoch vorab ausgiebig getestet werden.

Praktische Beispiele

Anhand von drei Beispielen demonstrieren wir, wie Sicherheitskonzepte in der Praxis umgesetzt werden können und worauf bei der Umsetzung geachtet werden sollte.

Zugriff auf administrative Schnittstellen

Der Zugriff auf administrative Schnittstellen wie SSH sollte nicht direkt aus dem Internet oder aus nicht-vertrauenswürdigen Netzwerken wie beispielsweise einem Client-Netzwerk erfolgen. Zudem sollten die Administrationen zwei Benutzeraccounts verwenden, einen zur Administration und einen für die tägliche Arbeit. Idealerweise wird zudem eine Mehr-Faktor-Authentisierung eingesetzt.

In unserer Infrastruktur setzen wir für den Zugriff auf administrative Dienste einen Jumphost ein. Jeder Administrator meldet sich über SSH und Public-Key-Verfahren auf dem Jumphost an. Die Systeme der Infrastruktur sind nur von diesem Jumphost aus per SSH erreichbar. Auf dem Jumphost hat jeder Administrator ein zweites SSH-Schlüsselpaar, das für die Authentisierung für den Zugriff auf Infrastruktur-Systeme verwendet wird. Alle SSH-Schlüsselpaare müssen mit einer Passphrase gesichert sein. Da wir aufgrund der Grösse der Infrastruktur keine zentrale Benutzerverwaltung einsetzen, existieren auf jedem System lokale Benutzer. Bei einem Wachstum der Infrastruktur wird die Einführung einer zentralen Verwaltung jedoch unabdingbar, da sonst der Aufwand der Benutzerverwaltung ins unermessliche steigt.

Der Jumphost ist aus unserem internen, vertrauenswürdigen Netzwerk direkt erreichbar. Aus dem Internet ist ein Port-Knocking-Verfahren notwendig, um den SSH-Zugang freizuschalten. Im Wiki von Arch Linux sind mehrere Port-Knocking-Lösungen beschrieben. Da auf unseren Systemen iptables als Firewall genutzt wird, haben wir uns für eine reine Lösung mit iptables entschieden:

#
# Port Knocking for SSH
# Sequence: 12345/tcp, 54321/tcp, 4242/tcp
# For each of the ports to knock, one rule checks for the correct port in sequence.
# If the sequence is met, a jump occurs to where the IP address is added to the list for the next knock in sequence.
#

# Opens the SSH port for 30 seconds, if the connecting IP address is on the list SSH2
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp -d 192.0.2.1 --dport 20022 -m recent --rcheck --seconds 30 --name SSH2 -j ACCEPT
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp -m recent --name SSH2 --remove -j DROP
# Third Knock
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp --dport 4242 -m recent --rcheck --name SSH1 -j SSH-INPUTTWO
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP
# Second Knock
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp --dport 54321 -m recent --rcheck --name SSH0 -j SSH-INPUT
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP
# First Knock
-A INPUT -i eth1 -m state --state NEW -m tcp -p tcp --dport 12345 -m recent --name SSH0 --set -j DROP
-A SSH-INPUT -m recent --name SSH1 --set -j DROP
-A SSH-INPUTTWO -m recent --name SSH2 --set -j DROP

Nachdem drei zufällig ausgewählte Ports in der richtigen Reihenfolge kontaktiert wurden, wird der Port des SSH-Daemon für die anfragende IP-Adresse für 30s freigegeben. Danach ist eine Authentisierung mittels Public-Key-Verfahren erforderlich. Durch den Einsatz von Port-Knocking ist der SSH-Daemon nicht direkt aus dem Internet erreichbar und somit nicht automatisierten Scans und Brute-Force-Angriffen ausgesetzt.

Host-Firewall mit iptables

Im Beitrag Zero Trust Modell schreibt Tomaso Vasella, dass die klassischen Ansätze auf Basis der Perimetersicherheit überholt sind und nicht mehr ausreichen. Wenn es Angreifern gelingt den Perimeterschutz zu überwinden können sie sich oftmals innerhalb von Zonen lateral von System zu System bewegen. Wir empfehlen den Einsatz von Host-Firewalls auf Client- und Server-Systemen, um die Resilienz einzelner Systeme gegen Lateral-Movement-Angriffe zu erhöhen. Zusätzlich bietet eine restriktive konfigurierte Host-Firewall einen Schutz während der Ausnutzung einer Schwachstelle, sodass nach dem Exploit keine zusätzliche Schadsoftware von extern nachgeladen werden kann.

In unserer Infrastruktur setzen wir iptables als Host-Firewall ein. Dabei haben wir ein Template-Regelwerk erstellt, das für alle Systeme gilt. Grundsätzlich sind ein- und ausgehende Verbindungen nicht erlaubt. Alle ausgehenden Verbindungen sind eingeschränkt auf die Source-Adresse, die Destination-Adresse(n) sowie die zu verwendende Protokolle. Dabei werden die Input-/Output-Regeln sowohl auf der Host-Firewall als auch auf der Perimeter-Firewall gepflegt. Im Vorfeld der Einführung eines neuen Dienstes oder Applikation muss abgeklärt werden, welche Protokolle eingesetzt werden, um welche Ziele zu erreichen. Danach können die benötigten Regeln festgelegt werden. In der Praxis funktioniert dies leider nicht jedes Mal so einfach wie man es sich vorstellt.

Als Beispiel dient unser Monitoring-System, das auf dem sogenannten ELK-Stack basiert. ELK steht für die Komponenten Elasticsearch, Logstash und Kibana. Für die Installation der Komponenten steht ein RPM-Repository zur Verfügung. Die Definition der Firewall-Regeln für dieses Repo war beschwerlicher als erwartet und begann mit der Analyse: Der Domainname des Repositories artifacts.elastic.co ist ein Alias (CNAME) für dualstack.elastic.map.fastly.net. Fastly ist ein Cloud-Service-Provider und vergibt unter anderem als Dienstleistung dynamische IP-Adressen. Die Aufnahme einer einzelnen IP-Adresse aus der ersten DNS-Anfrage ins Regelwerk schlug also fehl, da bereits zwischen dem ersten DNS-Aufruf und dem Versuch das Repo zu aktualisieren, eine anderen IP-Adresse aufgelöst wurde. Der nächste Workaround, mittels eines globalen DNS-Tools wie dnschecker.org eine Liste von IP-Adressen zu sammeln, schlug ebenfalls fehl. Fastly stellt jedoch ein Supportdokument und eine API zur Verfügung, um eine Liste von IP-Adressbereichen zu generieren. Somit wurde auf dem ELK-System die untenstehende Regel aufgenommen, die den Zugriff auf den Adressbereich von Fastly erlaubt. Auf der Perimeter-Firewall wurde ebenfalls eine Regel hinzugefügt, die dem ELK-System den Zugriff auf diese Bereiche erlaubt.

#
# General Settings
#
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]

...

#
# Outgoing Connections
#

# Elasticsearch Repo - artifacts.elastic.co - dualstack.elastic.map.fastly.net
# List of Fastly's assigned IP ranges: https://api.fastly.com/public-ip-list - Last update 23.01.2020
-A OUTPUT -m state --state NEW -m tcp -p tcp -m multiport --dports 80,443 -d 23.235.32.0/20,43.249.72.0/22,103.244.50.0/24,103.245.222.0/23,103.245.224.0/24,104.156.80.0/20,151.101.0.0/16,157.52.64.0/18,167.82.0.0/17,167.82.128.0/20,167.82.160.0/20,167.82.224.0/20,172.111.64.0/18,185.31.16.0/22,199.27.72.0/21,199.232.0.0/16 -j ACCEPT

Bei der Erstellung von Firewall-Regeln für Cloud-Service-Provider ist ein Kompromiss zwischen Sicherheit und Betrieb notwendig. Die Destination kann nicht auf ein einzelnes Ziel eingeschränkt werden. Dabei entsteht das Risiko, dass Angreifer, die den gleichen Provider verwenden, auch Zugriff auf ihre Systeme erhalten. Da auf der Perimeter-Firewall die Freigabe jedoch auf einzelne Systeme eingeschränkt wird, kann dieses Risiko reduziert werden.

Gelingt es Angreifern ein System zu kompromittieren, wird das Lateral Movement durch Host-Firewalls jedoch eingeschränkt, da dieses System mit anderen Systemen im ganzen Netzwerk sowie in der gleichen Zone nur in erlaubten Ausnahmefällen kommunizieren kann. Dieser Schutz rechtfertigt für uns den Aufwand zur Pflege von ein- und ausgehenden Verbindungen.

Verschlüsselte Kommunikation mit rsyslog

Sämtliche Kommunikation zwischen Systemen sollte verschlüsselt stattfinden. Viele Dienste bieten beispielsweise eine Verschlüsselung per Transport Layer Security (TLS) an. Dabei sollten Zertifikate einer vertrauenswürdigen Zertifizierungsstelle (CA) eingesetzt werden.

In unserer Infrastruktur werden die Logs der Systeme an einen zentralen rsyslog-Server gesendet. Die Übermittlung der Logs wird mittels TLS verschlüsselt. Dazu muss auf dem Server ein TCP-Listener eingerichtet werden:

# load TCP listener
module(load="imtcp" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer="*.example.com")
input(type="imtcp" address="192.0.2.6" Port="10514")

# make gtls driver the default
$DefaultNetstreamDriver gtls

# TLS config - CA Honest Achmed's Used Cars and Certificates
$DefaultNetstreamDriverCAFile /etc/rsyslog.d/certs/example_ca_cert.pem
$DefaultNetstreamDriverCertFile /etc/rsyslog.d/certs/log.example.com.pem
$DefaultNetstreamDriverKeyFile /etc/rsyslog.d/certs/log.example.com.key.pem

Auf dem Client wird das verwendete Zertifikat hinterlegt und rsyslog so konfiguriert, dass die Logs über eine verschlüsselte Verbindung übermittelt werden:

# make gtls driver the default
$DefaultNetstreamDriver gtls

# TLS config - CA Honest Achmed's Used Cars and Certificates
$DefaultNetstreamDriverCAFile /etc/rsyslog.d/certs/example_ca_cert.pem
$DefaultNetstreamDriverCertFile /etc/rsyslog.d/certs/host1.example.com.pem
$DefaultNetstreamDriverKeyFile /etc/rsyslog.d/certs/host1.example.com.key.pem

...

# Action
$ActionSendStreamDriverAuthMode x509/name
$ActionSendStreamDriverPermittedPeer log.example.com
$ActionSendStreamDriverMode 1 # run driver in TLS-only mode

# Send everything to log.example.com
# @ for UDP, @@ for TCP
*.* @@log.example.com:10514

Die Verschlüsselung der Kommunikation sollte für alle weiteren Dienste innerhalb der Infrastruktur ebenfalls geprüft und falls möglich implementiert werden.

Fazit

Die drei Beispiele und weitere Erfahrungen beim Aktualisieren der Infrastruktur zeigten, dass das Umsetzen von Hardening-Massnahmen nicht einfach “per Knopfdruck” erledigt werden kann. Dies ist uns auch bewusst, wenn wir solche als Empfehlungen und Gegenmassnahmen bei Findings formulieren. Sicherheitsmassnahmen werden idealerweise bereits in der Konzept-/Planungsphase bei der Implementierung von neuen Diensten und Anwendungen miteinbezogen. Dadurch können auch Begleitprozesse gestaltet werden, welche die Administration erleichtern, wie zum Beispiel ein Formular zur Bestellung von Firewall-Regeln, das eine Kommunikationsmatrix enthält. Wir sind bei der Aktualisierung unserer Infrastruktur einige extra Schleifen gelaufen, anstelle die Default-Konfiguration zu verwenden und auf Defense-in-Depth-Konzepte zu verzichten. Wir sind überzeugt, dass sich der Zusatzaufwand lohnt und werden weiterhin unsere eigenen Hardening-Massnahmen in produktiven Umgebung einsetzen.

Über den Autor

Michael Schneider

Michael Schneider arbeitet seit dem Jahr 2000 in der IT. Im Jahr 2010 hat er sich auf die Informationssicherheit spezialisiert. Zu seinen Aufgaben gehören das Penetration Testing, Hardening und das Aufspüren von Schwachstellen in Betriebssystemen. Er ist bekannt für eine Vielzahl in PowerShell geschriebener Tools zum Finden, Ausnutzen und Beheben von Schwachstellen. (ORCID 0000-0003-0772-9761)

Links

Sie wollen die Sicherheit Ihrer Firewall prüfen?

Unsere Spezialisten kontaktieren Sie gern!

×
Bericht und Dokumentation

Bericht und Dokumentation

Michael Schneider

Einführung von CVSS v4.0

Einführung von CVSS v4.0

Michael Schneider

Rogue Device

Rogue Device

Michael Schneider

Windows LAPS

Windows LAPS

Michael Schneider

Sie wollen mehr?

Weitere Artikel im Archiv

Sie brauchen Unterstützung bei einem solchen Projekt?

Unsere Spezialisten kontaktieren Sie gern!

Sie wollen mehr?

Weitere Artikel im Archiv