Debian-Linux Server Sicherheit Kursnotizen August 2021

1 Tag 1

1.1 Einführung

te

1.2 Zufallszahlen und Linux

  • starte top in einem anderen Terminal-Fenster, beobachte dort die CPU Benutzung des ssh-keygen Prozesses
  • erstelle einen 10000 bit ssh RSA Schlüssel (hier nur zur Demo von Zufallszahlen und haveged oder rngd)
cat /dev/random # Abbrechen
ssh-keygen -b 10000 -t rsa -f /tmp/test
  • Die Erstellung des Schlüssels dauert extrem lange, da /dev/random benutzt wird.
  • Rngd als Hardware-Zufallszahlengenerator installieren
  • Haveged erzeugt Zufallswerte aus der verteilung von Prozessen auf Prozessorkerne. Homepage http://www.issihosts.com/haveged/ Auch geeignet für virtuelle Umgebungen
  • Haveged installieren
apt install haveged
systemctl status haveged
  • Der Schlüssel sollte nach dem Start von haveged in ein paar Sekunden erstellt sein!

1.2.1 Durchsatz des Zufallszahlengenerators messen

  • rngd installieren
apt install rng-tools5
systemctl status rngd
  • aus /dev/random lesen und der Durchsatz per pv anzeigen lassen
apt install pv
dd if=/dev/random | pv > /dev/null
  • haveged an-/ausschalten (in einem anderen Terminal, die Datenrate im pv betrachten)
  • Dasselbe mit rngd
  • Beide zusammen und keines von Beiden
systemctl stop haveged rngd
systemctl start rngd
systemctl stop rngd
systemctl start haveged
systemctl start rngd

1.3 Aufgabe: Hash und HMAC

  • Lade die Datei https://notes.defaultroutes.de/LinuxSecurityEinfuehrung.pdf
  • Welcher SHA256 Hash-Wert ist korrekt?
    1. 0245bcddf700ddfb4fd37c58bbfc67e19b9aa8827d0242fc9beb40078925f191
    2. f8eee6980c49d8020b10449a0fec6544e266af09
    3. 22833704a424725d5725d977cc733244afe0e38a6e2a987a560c95aa39da2d01
    4. AEGHHA91288ABCCVA005612991ZZ612566189811
openssl dgst -sha256 < LinuxSecurityEinfuehrung.pdf
  • Der folgende Wert sind die HMACs für die PDF-Datei. Welcher PSK (pre-shared-secret) wurde verwendet:
HMAC-SHA256 =
 3989780c03e83f553dca485c38a4d6239de58affbe27f0d7b572be00a5e512ee
  • Auswahl der PSKs:
    1. 'LinuxHotel'
    2. 'EssenHorst'
    3. 'vogelsang'
openssl sha256 -hmac "<psk>" < LinuxSecurityEinfuehrung.pdf

1.4 Symmetrische Verschlüsselung mit OpenSSL

# AES
% echo "mein geheimer text" | openssl enc -e -aes256 -a
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
<verschlüsselter text>

echo "<verschlüsselter text>" |  openssl enc -d -aes256 -a

1.5 Asymmetrische Verschlüsselung mit OpenSSL

# einen neuen privaten RSA Schlüssel erstellen
openssl genpkey -algorithm RSA -out key.pem

# den privaten Schlüssel mit AES 256bit verschlüsseln
openssl pkey -in key.pem -aes256 -out keyaes.pem
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

# Unverschlüsselten privaten Schlüssel löschen
rm key.pem

# den öffentlichen Schlüssel erzeugen (kann bei RSA aus dem privaten
# Schlüssel erzeugt werden)
openssl pkey -in keyaes.pem -pubout -out pubkey.pem

# Daten mit dem öffentlichen Schlüssel verschlüsseln
echo "Hallo LinuxHotel" > plain.txt
openssl pkeyutl -in plain.txt -out cipher.txt -encrypt -pubin -inkey pubkey.pem

# Verschlüsselten Text als Hex und ASCII anzeigen
cat cipher.txt | od -x -a

# Daten mit dem privaten Schlüssel entschlüsseln
openssl pkeyutl -in cipher.txt -out plain2.txt -decrypt -inkey keyaes.pem
Enter pass phrase for keyaes.pem:

# entschlüsselten Text wieder anzeigen
cat plain2.txt
Hallo LinuxHotel

1.6 Software Downloads prüfen

1.6.1 Debian CD/DVD Download

  • Prüfen, ob eine Debian Installations-CD/DVD "original" ist, d.h. vom Debian-Release Team stammt:
  • CD-Rom ISO Image laden
wget https://debian.inf.tu-dresden.de/debian-cd/11.0.0/amd64/iso-cd/debian-10.1.0-amd64-netinst.iso
  • SHA256 Fingerabdruck der Datei errechnen
openssl dgst -sha256 < debian-11.0.0-amd64-netinst.iso
  • Datei mit den Hash-Prüfsummen laden
wget https://debian.inf.tu-dresden.de/debian-cd/11.0.0/amd64/iso-cd/SHA256SUMS
  • Hash der ISO-Datei mit dem Hash in der Prüfsummendatei vergleichen
  • Nun prüfen wir, ob die Datei mit den Hash-Prüfsummen original ist. Dabei wird die digitale Signatur (mittels GNU-PG) über die Datei mit den SHA256-Hashes geprüft. Wir laden die Signatur der Hash-Prüfsummen vom Download-Server:
wget https://debian.inf.tu-dresden.de/debian-cd/11.0.0/amd64/iso-cd/SHA256SUMS.sign
  • Releases der Debian-Distribution werden mit extra Schlüsseln des Debian-Release-Teams signiert. Wenn wir direkt versuchen, die Signatur auf der Datei zu prüfen, so bekommen wir einen Fehler, da wir den öffentlichen Schlüssel (ID DF9B9C49EAA9298432589D76DA87E80D6294BE9B) des Debian-Release-Teams nicht in unserem GPG-Schlüsselbund haben:
debian$ gpg --verify SHA256SUMS.sign SHA256SUMS
gpg: Signature made Sun Sep  8 17:52:41 2019 CEST
gpg:                using RSA key DF9B9C49EAA9298432589D76DA87E80D6294BE9B

gpg: Can't check signature: No public key
  • Um die Signaturen prüfen zu können, importieren wir den Debian CD Signatur-Schlüssel in den eigenen GPG-Schlüsselring.
# su -
# apt -y install dirmngr
# exit
# gpg  --keyserver keyring.debian.org --recv-keys DF9B9C49EAA9298432589D76DA87E80D6294BE9B
gpg: key DA87E80D6294BE9B: public key "Debian CD signing key <debian-cd@lists.debian.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg --finger  DF9B9C49EAA9298432589D76DA87E80D6294BE9B
  • Signature auf der Prüfsummendatei prüfen
# gpg --verify SHA256SUMS.sign SHA256SUMS
gpg: Signature made Sun Sep  8 17:52:41 2019 CEST
gpg:                using RSA key DF9B9C49EAA9298432589D76DA87E80D6294BE9B
gpg: Good signature from "Debian CD signing key <debian-cd@lists.debian.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: DF9B 9C49 EAA9 2984 3258  9D76 DA87 E80D 6294 BE9B
  • Um dem CD-ROM Image vertrauen zu können, sollten alle Prüfsummen und Signaturen stimmen.

1.6.2 Debian Release/Repository Schlüssel

  • Die Debian-GPG Schlüssel zum verifizieren von Software-Paketen liegen im Verzeichnis /etc/apt/trusted.gpg.d/

1.6.4 die Authentizität und Integrität eines Debian Pakets manuell prüfen

  • Debian Pakete sind über eine Signatur-Kette geschützt (anders als RPM Pakete bei RedHat/CentOS/Fedora, welche direkt durch eine GPG-Signatur geschützt sind)
  • Die Hash-Prüfsummen der Debian-Pakete sind in den Paketlisten-Dateien hinterlegt (z.B. main/Contents-amd64). Die Hash-Prüfsummen der Paketlisten sind in der Release Datei hinterlegt, und diese Datei ist mit den GPG-Schlüssel des Debian-Release-Teams unterschrieben.
  • Um nun ein beliebiges Debian-Paket zu prüfen
    • errechne die SHA256 Prüfsumme des Pakets
    • vergleiche diese Prüfsumme mit der Prüfsumme in der Paketliste der Architektur
    • Errechne die SHA256-Prüfsumme der Paketlisten Datei.
    wget https://debian.inf.tu-dresden.de/debian/dists/Debian11.0/main/binary-amd64/Packages.gz
    openssl dgst -sha256 < Packages.gz
    zcat Packages.gz | less
    
    • Lade die aktuelle Release-Datei für die Debian-Version:
    $ wget https://debian.inf.tu-dresden.de/debian/dists/Debian11.0/Release
    $ wget https://debian.inf.tu-dresden.de/debian/dists/Debian11.0/Release.gpg
    
    • Importiere die (öffentlichen) GPG-Schlüssel des Debian-Release Teams. Hat man keine (vertrauenswürdige Debian-Installation), so findet man die Schlüssel unter https://ftp-master.debian.org/keys.html
    $ gpg --import /etc/apt/trusted.gpg.d/debian-archive-*
    
    • Als letzter Schritt werden die Signaturen auf der Release-Datei geprüft
    gpg --verify Release.gpg Release
    
    • Alle Schritte dieser Prüfung müssen erfolgreich abgeschlossen sein, um der Installationsdatei (DEB-Paket) vertrauen zu können. Diese Prüfung wird von den Debian-Paketmanager-Programmen (apt, apt-get, aptitude, debootstrap) automatisch durchgeführt.

1.7 TMUX - terminal multiplexer

apt install tmux
tmux
Aktion Tastaturkombination
Neues Terminal CTRL+B C
nächstes Terminal CTRL+B N
voheriges Terminal CTRL+B P
Screen Nr. x [0…9] CTRL+B 4
Terminal horizontal teilen CTRL+B "
Terminal vertikal teilen CTRL+B %
zwischen geteilten Terminals wechseln CTRL+B <cursor>
zwischen geteilten Terminals wechseln CTRL+B O
Größe ändern CTRL+B CTRL+<cursor>
  CTRL+B <ESC> <cursor>
Zoomen CTRL+B z
Terminal schliessen CTRL+B x
Tmux abhängen (detach) CTRL+B d
Grafisch Fenster wechseln CTRL+B w
Grafisch Sitzung wechseln CTRL+B s
Tmux anhängen tmux attach
Tmux Kommandozeile CTRL+B :
Tastenkommandos in alle Fenster (Kommandozeile) set synchronize-panes
   

1.8 Sicherheit bei der Unix-Benutzeranmeldung

  • Die Sicherheit der Unix-Benutzeranmeldung hängt u.a. an der Sicherheit der gespeicherten Passwörter. Passwörter werden in einem Linux-System als SHA512-Hash gespeichert. Dabei wird das Passwort 5.000 mal mit dem SHA512 Algorithmus gehashed bevor es in der Datei /etc/shadow gespeichert wird oder gegen den Hash in dieser Datei geprüft wird.
  • 5.000 Runden SHA512 lassen sich heute mit grossen Rechnern "brute-force" berechnen. Die Default-Einstellung von Linux istso gewählt, das es auch auf sehr schwachen Rechnern (z.B. Heim-Routern) noch funktioniert. Moderne Systeme können eine grössere Anzahl SHA512 Runden für die Passwort-Sicherheit verwenden. Nachfolgend stellen wir die SHA512-Runden auf 1.000.000 (1 Million) ein.

1.8.1 Sicherheit der Benutzerpasswörter

  • In der Datei /etc/pam.d/common-password wird die Stärke der Benutzer-Passwörter angepasst. Eine Änderung in dieser Datei wirkt sich nur auf alle neu gesetzten Passwörter aus, alle schon vorher vergebenen Passwörter bleiben mit der vorherigen Einstellung bestehen. D.h. nach einer Änderung dieses Parameters sollten wichtige Passwörter neu vergeben werden.
[...]
password    [success=1 default=ignore]    pam_unix.so obscure sha512 rounds=1000000
[...]

1.8.2 Yesycrypt in Debian 11

  • Yescrypt ist eine neue Schlüsselableitungsfunktion für Passwörter vom OpenWall Projekt. Es basiert auf scrypt (RFC 7914) von Colin Percival (früherer Sicherheitleiter des FreeBSD Projektes). Es schützt besser vor Brute-Force Angriffen als SHA512 und andere Schlüsselableitungsfunktionen.
    • Debian 11 setzt Yescrypt als Standard-Algorithmus für die Benutzerpasswörter ein
    • Bei einem Update von Debian 10 auf Debian 11 bleiben die Passwort-Hashes im SHA512 Format
      • erst bei einer Passwortänderung mittels passwd wir der neue Yescrypt-Hash erzeugt
    • Beispiel Debian 10 SHA512 Hash in der /etc/shadow
    nutzer:$6$NtILOHbh$SZ1pFZKkJj/xqtrxqtSBrkOgRWQmXfv4tJhwlCfNkL7V4ft8G6eyLkVhxmvAs6DQsPuAmRqB7WVfJHMB5w0340:16442:0:99999:7:::
    
    • Beispiel Debian 11 Yescrypt Hash in der /etc/shadow
    nutzer:$y$j9T$YhVeKuFhMSSA91rR4FhwT/$9YTuWLhjyf1oqcPMoEkJFqSL.6YMRMQVMGaIgWIJyq9:18868:0:99999:7:::
    

1.8.3 Gruppenpasswörter

  • Die Sicherheit der Gruppenpasswörter werden in der Datei /etc/login.defs festgelegt. Wenn Gruppenpasswörter benutzt werden, wird empfolen diese Werte mit der PAM-Konfiguration gleich zu halten.
ENCRYPT_METHOD SHA512
SHA_CRYPT_MIN_ROUNDS 1000000
SHA_CRYPT_MAX_ROUNDS 1000000

1.8.4 Benutzerdatenbank

  • Die Benutzerinformationen für die Passwortanmeldung unter Unix/Linux werden in der Datei /etc/shadow gespeichert
  1. Felder der Datei /etc/shadow:
    • Benutzername
    • Password-Hash
    • Datum des letzen Passwort-Wechsel
    • Mindestlebensdauer des Passworts
    • Max-Lebensdauer des Passwort
    • Passwort-Ablauf Warn-Zeitraum
    • Zeitdauer der Passwort-Inaktivität (Benutzer kann sich nach Ablauf des Passworts noch einloggen)
    • Ablaufdatum des Passworts
    • Reserviertes Feld
  2. Passwort-Hash-Methoden
    ID Methode
    1 MD5
    2a Blowfish (nicht in der Standard glibc; wurde einigen Distributionen hinzugefügt)
    5 SHA-256 (seit glibc 2.7)
    6 SHA-512 (seit glibc 2.7)

1.9 chage

useradd -m -N fritz
passwd fritz
chage -l fritz
  • Account abgelaufen
chage -E 0 fritz
  • Account ist ab einem bestimmten Datum nicht mehr gültig
chage -E 2019-03-01 fritz
  • Ablaufzeit zurücksetzen
chage -E -1 fritz
  • Passwort darf frühstens nach 3 und muss spätestens nach 9 Tagen geändert werden
chage -m 3 -M 9 -d "1 day ago" fritz
passwd fritz
  • Login innerhalb der Warn-Periode
chage -d "8 days ago" -W 3 fritz
su - fritz
  • Login außerhalb der Warn-Periode aber innerhalb der Gültigkeit
chage -d "12 days ago" -I 10 fritz
su - fritz
  • Login außerhalb der Gültigkeit
chage -d "21 days ago" -I 10 fritz
su - fritz
  • Benutzer muss sein Passwort einmalig beim ersten Login ändern
chage -E -1 -I -1 -m 0 -M 99999 fritz # alles zurücksetzen
passwd fritz                          # Ein Standardpasswort setzen
chage -d 0 fritz                      # Änderung erzwingen

1.10 PAM -Pluggable Authentication Modules

cat /etc/pam.d/common-auth | grep -v "#"

auth    [success=1 default=ignore]      pam_unix.so nullok_secure
auth    requisite                       pam_deny.so
auth    required                        pam_permit.so
auth    optional                        pam_cap.so
  • PAM Dienst-Typen
    • account: Prüfung Berechtigung
    • auth: Authentifizierung
    • password: Passwort-Änderung
    • session: Sitzungsverwaltung
  • PAM Control
    • requisite = muss erfolgreich sein, sonst Kette beenden (notwendige Vorbedingung)
    • required = muss am Ende erfolgreich sein (notwendige Bedingung)
    • sufficient = bei Erfolg wird die Kette beendet (hinreichende Bedingung)
    • optional = Returncode wird nicht verwendet
  • Linux-PAM erweiterte Controls
    • Syntax: [return-value=action …]
    • Actions:
      • OK = Zugriff erlauben
      • ignore = Ignorieren
      • bad = Zugriff verweigern
      • die = Zugriff verweigern und Kette abschliessen
      • done = Zugriff erlauben und Kette abschliessen
      • reset = PAM Variablen zurücksetzen/löschen und weitermachen
      • <n> = die folgenden <n> PAM-Regeln überspringen

1.10.1 Aufgabe: pam_warn.so für Login installieren

  • Installiere das Modul pam_warn.so fuer die Facility auth in PAM-Dienst login
  • Schalte auf einen der Konsolen-Bildschirme des Laptops um "STRG+ALT+F2 … F8"
  • Melde dort den Benutzer nutzerXX an
  • Prüfe die Syslog/Journal Ausgabe

1.10.2 Lösung

  • in Datei /etc/pam.d/login
auth       required   pam_warn.so
  • in Datei und /etc/pam.d/common-session
session       required   pam_warn.so
  • per STRG+ALT+F2 auf eine Text-Konsole wechseln
  • als nutzerXX einloggen
  • die neuen Log-Einträgen in /var/log/auth.log prüfen

1.10.3 Aufgabe: ein einfaches PAM-Modul aktivieren

  • Es gibt ein PAM-Modul, welches allen normalen Benutzern die Anmeldung am System verweigert. Nur der root Benutzer darf sich dann anmelden.
  • Dieses PAM-Modul ist schon für den Dienst login konfiguriert, aber nicht aktiv (Datei /etc/pam.d/login)
  • Lese die Man-Pages der PAM-Module für den Dienst login der auth-Funktionen, finde heraus, welches Modul das Login aller Nicht-Root-Benutzer verweigern kann, und wie es aktiviert wird.
  • Aktiviere diese Funktion und teste diese aus. Wechsle mit STRG+ALT+F2 auf die Text-Konsole und versuche Dich dort mit dem normalen Benutzer anzumelden. Alternativ: Anmeldung per SSH über das Loopback-Interface:
ssh nutzerXX@localhost
  • Wie kann einem normalen Benutzer der Grund für den Fehlschlag des Anmeldeversuches mitgeteilt werden?

1.10.4 Lösung:

  • Modul pam_nologin.so, aktiviert durch die Datei /etc/nologin:
echo 'Heute kein Login möglich! Wartungsarbeiten bis Dienstag!' > /etc/nologin

1.10.5 Aufgabe: 2-Faktor Authentisierung - OATH Open Authentication Event Token (HOTP)

  • RFC 4226 HOTP: An HMAC-Based One-Time Password Algorithm (https://tools.ietf.org/html/rfc4226)
  • Alternative: RFC 6238 "TOTP: Time-Based One-Time Password Algorithm"
  • Token-Software als App für viele Mobiltelefone verfügbar
  • Pakete installieren
apt install libpam-oath oathtool
  • pam_oath in die PAM Konfiguration aufnehmen (hier für den su Befehl). window=5 gibt ein Fenster von 5 Passwörtern aus der Liste an, welche akzeptiert werden.
$EDITOR /etc/pam.d/su
-----
#%PAM-1.0
auth            sufficient      pam_rootok.so
auth            requisite       pam_oath.so usersfile=/etc/oath/users.oath window=5
-----
  • OATH Benutzerdatei anlegen
mkdir /etc/oath
$EDITOR /etc/oath/users.oath
-----
HOTP nutzerXX - <hex-secret>
HOTP nutzerYY - 0102030405
  • Beispiel: Passwort in HEX-Zahl umrechnen:
echo "villa" | od -x
0000000 6976 6c6c 0a61
0000006
  • Benutzerrechte setzen
chmod 000 /etc/oath/users.oath
chown root: /etc/oath/users.oath
  • Eine Reihe (5 Stück) von Passwörter zum Test erstellen
oathtool -w 5 <hex-secret>
  • Anmeldung ausprobieren als "nutzerXX", eines der Passwörter aus der Liste probieren
su - nutzerXX
  • Wer ein Smart-Phone hat, mal im App-Store nach "OATH" suchen, eines OATH-Token Programm installieren und konfigurieren

1.10.6 Aufgabe: Einmal Passwörter mit OTPW

  • OTPW = One-Time-Password – ähnlich einer TAN-Liste
  • OTPW Pakete installieren
apt install libpam-otpw otpw-bin
  • das Modul pam_otpw in die PAM-Konfiguration vom su aufnehmen, die Konfiguration von OATH und common-auth auskommentieren
...
auth            required        pam_otpw.so
...
session         optional        pam_otpw.so
#@include common-auth
...
  • Das Programm otpw-gen benutzt die Ausgabe von netstat, um den eigenen Zufallszahlengenerator zu initialisieren (ist das sicher?). netstat ist jedoch auf modernen Linux-Systemen wie Debian 9 nicht vorhanden und muss manuell installiert werden:
apt install net-tools
  • Als Benutzer nutzerXX eine Passwortliste erstellen (dabei das Prefix-Passwort angeben) und ggf. ausdrucken. Ausdrucke finden sich im Kyocera-Drucker in der Vorhalle
su - nutzerXX
otpw-gen > otpwlist.txt
less otpwlist.txt
lp otpwlist.txt
  • OTPW legt Hashes der Einmalpasswörter in der Datei ~/.otpw ab
less ~/.otpw
  • OTPW ausprobieren (als NutzerXX nochmals per su anmelden). Das bei der Erstellung der Passwort-Liste angegebene Passwort muss vor dem Einmal-Passwort eingegeben werden
su - nutzerXX
  • das Passwort ist nun verbraucht und aus der Liste gestrichen
less ~/.otpw

1.10.7 PAM Duress

  • PAM Duress (https://github.com/nuvious/pam-duress) ist ein interessantes PM-Modul welches es dem Benutzer erlaubt, alternative Passwörter im PAM zu hinterlegen. Diese Passwörter sind jeweils mit einen Shell-Skript verbunden. Wird eines der "Duress" Passwörter statt dem "normalen" Benutzerpasswort eingegeben, so wird das dazugehörige Script ausgeführt.
  • Beschreibung der Einsatzszenatrien von der Projekt-Webseite

    Diese Funktion könnte genutzt werden, um jemandem, der unter [Zwang] zur Eingabe eines Kennworts gezwungen wird, die Möglichkeit zu geben, ein Kennwort einzugeben, das den Zugang gewährt, aber im Hintergrund Skripte ausführt, um sensible Daten zu bereinigen, Verbindungen zu anderen Netzwerken zu schließen, um lateral movement einzuschränken, und/oder eine Benachrichtigung oder einen Alarm zu senden (möglicherweise mit detaillierten Informationen wie Standort, sichtbaren WLAN-Hotspots, einem Bild von der Kamera, einem Link zu einem Stream vom Mikrofon usw.). Es kann sogar einen Prozess starten, um das Modul pam_duress zu entfernen, damit der Bedrohungsakteur nicht sehen kann, ob das PAM-Duress verfügbar war.

  • Weitere Einsatzgeniete:
    • Wegwerfbare Gast-Zugänge einrichten
    • Automatisches mit-protokollieren einer Sitzung per "sudo" beim Login einschalten
    • MacOS "Find-my-Mac" nachbauen (gestohlene Rechner orten)

1.11 su

  • mit dem Programm su (Switch User eigentlich Substitute User) kann ein Benutzer ein einen anderen Benutzerkontext wechseln
  • Unterschiede bei den Umgebungsvariablen zwischen su und su - oder su -l
    • bei su werden die Umgebung des aufrufenden Benutzer übernommen (kann Sicherheitsprobleme erzeugen)
    • die Variablen $IFS, $HOME, $SHELL, $USER, $LOGNAME, $PATH werden bei su - oder su -l zurückgesetzt
  • Such-Pfade für Benutzer und root werden in /etc/login.defs über die Optionen ENV_PATH und ENV_SUPATH konfiguriert

1.12 sudo

  • sudo ist ein moderner Ersatz für su. Gegenüber su hat sudo mehrere Vorteile:
    • es wird das eigene Benutzerpasswort abgefragt, nicht das Passwort dies Ziel-Benutzers
    • Das Ergebniss der Passwort-Prüfung des Benutzers kann für eine gewisse Zeit gespeichert werden, so das der Benutzer nicht für jeden Befehl das Passwort eingeben muss
    • Bessere Protokollierung
    • Umfangreiche Konfigurationsmöglichkeiten
  • sudo Installation
apt install sudo
  • sudo Basis-Konfiguration ausgeben
sudo -V
  • sudo Konfigurationsdatei sicher editieren (ggf. Variable $EDITOR setzen, sonst wird vi verwendet)
EDITOR=emacs visudo
  • aliase (host, user, command)
  • sudo und das Environment
  • sudo -i vs. sudo su -

1.12.1 Beispiel:

  • Befehl cat auf die Datei /var/log/apt/term.log für Benutzer nutzer02
visudo -f /etc/sudoers.d/apt-term-cat
----
nutzer02 ALL=(root) /bin/cat /var/log/apt/term.log
----
nutzerXX$ sudo -l
  • sudo -l Zeigt die sudo-Konfiguration und die erlaubten Befehle eines sudo-Benutzers an.

1.12.2 Aufgabe:

  • Erstelle eine sudo Konfiguration, um es dem Benutzer nutzerXX zu erlauben, die Logdateien /var/log/messages und /var/log/daemon.log unter den Benutzerberechtigungen des Benutzers root mit den Programmen more und less anzuschauen

1.12.3 Lösung

visudo -f /etc/sudoers.d/log-message-view
------
...
nutzerXX  ALL=(root) /usr/bin/more /var/log/messages
nutzerXX  ALL=(root) /usr/bin/more /var/log/daemon.log
nutzerXX  ALL=(root) /usr/bin/less /var/log/messages
nutzerXX  ALL=(root) /usr/bin/less /var/log/daemon.log
...
  • in einem anderen Terminal/Tmux-Fenster, teste sudo als nutzerXX
nutzerXX$ sudo more /var/log/messages
nutzerXX$ sudo less /var/log/daemon.log
nutzerXX$ sudo less /etc/shadow       # <--- darf nicht gehen
nutzerXX$ sudo more /var/log/auth.log # <--- darf nicht gehen

1.12.4 Frage:

  • gibt es mit dieser Konfiguration ein Sicherheitsproblem?

1.12.5 Antwort:

  • Ja - less und viele andere Programme können Unterprogramme aufrufen (z.B. eine Shell), welche dann mit root-Rechten läuft
  • Lösung: NOEXEC:
nutzerXX  ALL=(root) NOEXEC: /usr/bin/more /var/log/messages
nutzerXX  ALL=(root) NOEXEC: /usr/bin/more /var/log/boot.log

1.12.6 sudo Aliases

     # User alias specification
     User_Alias      FULLTIMERS = millert, mikef, dowdy
     User_Alias      PARTTIMERS = bostley, jwfox, crawl
     User_Alias      WEBMASTERS = will, wendy, wim

     # Runas alias specification
     Runas_Alias     OP = root, operator
     Runas_Alias     DB = oracle, sybase
     Runas_Alias     ADMINGRP = adm, oper

     # Host alias specification
     Host_Alias      SPARC = bigtime, eclipse, moet, anchor :\
                     LINUX = grolsch, dandelion, black :\
                     LINUX_ARM = widget, thalamus, foobar :\
                     LINUX_PPC64 = boa, nag, python
     Host_Alias      CUNETS = 128.138.0.0/255.255.0.0
     Host_Alias      CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
     Host_Alias      SERVERS = master, mail, www, ns
     Host_Alias      CDROM = orion, perseus, hercules

     # Cmnd alias specification
     Cmnd_Alias      KILL = /usr/bin/kill, /usr/bin/pkill
     Cmnd_Alias      PRINTING = /usr/sbin/lpc, /usr/bin/lprm
     Cmnd_Alias      SHUTDOWN = /usr/sbin/shutdown
     Cmnd_Alias      HALT = /usr/sbin/halt
     Cmnd_Alias      REBOOT = /usr/sbin/reboot
     Cmnd_Alias      SHELLS = /usr/bin/sh, /usr/bin/zsh, /bin/bash

FULLTIMERS  SPARC=(OP) KILL
WEBMASTERS  LINUX=(:ADMINGRP) SHELLS

1.12.7 sudoedit

  • Benutzer nutzerXX soll die Datei /etc/rsyslog.conf editieren dürfen
  • in der Datei /etc/sudoers
visudo
----
nutzerXX ALL= sudoedit /etc/rsyslog.conf
----
sudoedit /etc/rsyslog.conf

1.12.8 sudo replay

  • Füge die folgenden Konfigurationszeilen in die /etc/sudoers Datei ein
Defaults log_output
Defaults!/usr/bin/sudoreplay !log_output
Defaults!/sbin/reboot !log_output
  • nutzerXX darf root werden
nutzerXX ALL=(root) ALL
  • Benutze sudo als nutzerXX um eine interaktive Shell zu bekommen
nutzerXX$ sudo -s
  • ein paar Befehle ausführen, die Ausgaben produzieren
  • die sudo Root-Shell wieder verlassen
  • (im Terminal als Benutzer root) Aufgezeichnete Sitzungen auflisten
sudoreplay -l
  • aufgezeichnete sudo Sitzung abspielen
sudoreplay <TSID>
  • Verzeichnis der sudo Aufzeichnungen:
ls -l /var/log/sudo-io/

1.12.9 einfaches Intrusion Detection mit sudo (ab sudo 1.8.7)

openssl dgst -sha256 /usr/bin/passwd
SHA256(/usr/bin/passwd)= a92b1b6fb52549ed23b12b32356c6a424d77bcf21bfcfbd32d48e12615785270
visudo
----
nutzerXX ALL= sha256:a92b1b6fb52... /usr/bin/passwd
----

1.12.10 sudo Konfiguration (Passwort Cache Beispiele)

Defaults passwd_tries=5, passwd_timeout=2
Defaults timestamp_timeout=0 # Disable password caching
Defaults timestamp_timeout=5 # 5 Minuten password caching (default)

1.12.11 Befehle ohne Passwort

nutzer ALL=(dba) NOPASSWD: /opt/oracle/bin/befehl

1.12.12 Passwort des Zielaccount angeben (SUSE Linux Default)

Defaults targetpw

1.13 Auf dem SSH-Server: Passwort-Authentisierung abschalten

Die Benutzung von Passwörter für die SSH-Authentisierung ist einfach aber liefert nur eine minimale Sicherheit. Passwörter sind oft zu erraten oder per Brute-Force-Angriff ermittelbar. Besser sind kryptografische Schlüssel. SSH bietet die Authentisierung per Schlüssel, jedoch wird die Passwort-Anmeldung als Rückfall-Mechanismus benutzt. Um SSH richtig abzusichern sollte daher die Passwort-Anmeldung in der Konfiguration des SSH-Servers abgeschaltet werden.

$EDITOR /etc/ssh/sshd_config
----
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
----

2 Tag 2

2.1 Dateisystemberechtigungen

2.1.1 normale Unix-Rechte

  1. die klassischen Unix-Dateisystemberechtigungen (RWX)
  2. das sgid-bit
    chmod g+s <verzeichnis>
    

    neue Dateien bekommen die Gruppe des Verzeichnisses anstatt der (primäre) Gruppe des Benutzers. Beim anlegen von Unterverzeichnissen bekommen diese auch ein sgid bit gesetzt

  3. Unerwartet: Schreibrechte auf Verzeichnis vs. Schreibrechte auf Datei
    useradd nutzer1
    useradd nutzer2
    groupadd projekt
    usermod -a -G projekt nutzer1
    usermod -a -G projekt nutzer2
    mkdir /home/projekt
    chown :projekt /home/projekt
    chmod g+w /home/projekt
    ls -ld /home/projekt/
    su - nutzer1
    cd /home/projekt/
    cat > unveraenderbarer.txt
    Dies ist ein unveraenderbarer text
    CTRL+D
    chmod u=rw,g=r,o=r unveraenderbarer.txt
    chgrp projekt unveraenderbarer.txt
    ls -l unveraenderbarer.txt
    -rw-r--r--. 1 cas projekt 35 Nov 23 21:57 unveraenderbarer.txt
    logout
    su - nutzer2
    cd /home/projekt
    ls -l unveraenderbarer.txt
    vi unveraenderbarer.txt
    
  4. Frage:
    • kann nutzer2 mit diesen Berechtigungen die Datei verändern?
  5. Antwort:
    • ja, indirekt. Der Benutzer hat Schreibrechte auf dem Verzeichnis. Daher kann er neue Dateien anlegen und bestehende Löschen. Er kann auch Dateien löschen, auf denen er keine Schreibrechte besitzt! Der vi Editor legt bei Bearbeiten einer Datei eine lokale Kopie an, diese Kopie wird editiert und beim Speichern wird die Ausgangsdatei gelöscht und durch die temporäre Datei ersetzt.
  6. Sticky-Bit auf Verzeichnis - Nur der Besitzer der Datei darf die Datei löschen
    chmod o+t <verzeichnis>
    

2.1.2 Posix ACLs

  1. ACLs setzen (modify)
    setfacl -m u:<nutzer>:rwx file/dir # ACL setzen
    setfacl -x u:<nutzer>              # ACL löschen
    setfacl -d -m g:<gruppe>:rwx <dir> # Default ACL auf Verzeichnisse setzen
    setfacl -m "d:u::rwx,d::g:rwx,d:o::-" <dir> # alternative Syntax. Generic default mask
    
  2. ACLs auslesen
    getfacl <datei/verzeichnis>
    
  3. ACL mask
    • chmod gruppe ändert nur noch die Maske
    • die Maske filtert die ACLs
    • Berechtigungs-Änderungen können nur mit setfacl durchgeführt werden
    • setfacl -k – default ACLs löschen
    • setfacl -b – ACLs löschen

2.1.3 Erweiterte Attribute

  • Nicht alle Dateisysteme unterstützen alle erweiterten Attribute (EA). Unter Linux unterstützen die ext2/ext3/ext4-Dateisysteme und das XFS-Dateisystem einige der EAs. Die Man-Page zum Dateisystemformat gibt Auskunft über die EA Unterstützung (z.B. man ext4).
  • Anzeigen der erweiterten Attribute: lsattr
  • Ändern der erweiterten Attribute: chattr
  • Sicherheit von erweiterten Attribute (EA) unter Linux im Vergleich zu BSD: unter BSD können die Sicherheitsrelevanten EA (append, immutable) vom Benutzer root nur im Single-User Module (ohne Netzwerk) gelöscht werden. Unter Linux kann root die EA zu jedem Zeitpunkt entfernen!
  1. erweiterte Attribute vom Benutzer verwaltbar
    • d – Datei nicht bei "dump" mitsichern
    • s – Datei wird beim Loeschen mit Nullen ueberschrieben
    • A – bei der Datei wird atime nicht aktualisiert
  2. erweiterte Attribute welche nur vom Benutzer root verwaltet werden
    • a – append - Datei kann nur erweitert werden
    • i – immutable - Datei ist unveraenderbar
  3. Beispiele
    # Erweiterte Attribute Auslesen
    lsattr /pfad/zur/datei
    # Erweiterte Attribute setzen
    chattr +d /pfad/zur/datei
    # Erweiterte Attribute löschen
    chattr -d /pfad/zur/datei
    

2.2 Linux Capabilities

  • Linux Capabilities erlaubes es, Teile der Rechte des root Benutzers an Prozesse und Dateien zu binden
  • die verfügbaren Capabilities sind unter man capabilities nachlesbar
  • Installiere ein paar Zusatztools für Linux-Capabilities
apt install libcap-ng-utils libpam-cap

2.2.1 Beispiel: Als Ersatz für SUID

Als User

cat /usr/bin/ping > PING
chmod a+x PING
./PING 9.9.9.9
sudo -i
setcap cap_net_raw+p .../PING
^d
PING 9.9.9.9

Mit pstree und unter dem proc Dateisystem CapPrm prüfen

2.2.2 Beispiel: root CAP_CHOWN entziehen

capsh --drop=cap_chown --
chown fritz /home/prj

2.2.3 Beispiel: CAP_CHOWN an einen normalen Benutzer delegieren

  • wir möchten die Capabilities CAP_CHOWN (den Besitzer einer Datei/Verzeichnis ändern) und CAP_DAC_OVERRIDE (Dateiberechtigungen ignorieren) an einen normalen Benutzer delegieren
  • PAM Konfiguration prüfen
$EDITOR /etc/pam.d/common-auth
----
[...]
auth        optional      pam_cap.so
[...]
  • Die Capability Benutzerkonfiguration erstellen. der Befehl man capabilities listed die Namen und Beschreibungen der verfügbaren Capabilities.
$EDITOR /etc/security/capability.conf
----
cap_chown,cap_dac_override          nutzerXX
----
  • Welche Capabilities hat das chown Programm? (sollte derzeit keine haben)
getcap $(which chown)
  • Wir setzen die cap_chown Capability auf dem chown Programm
setcap cap_chown=ei $(which chown)
getcap $(which chown)
/bin/chown = cap_chown+ei
  • neu als Benutzer nutzerXX anmelden
su - nutzerXX
su - nutzerXX
  • nun sollte der aktuelle Prozess die Capability cap_chown besitzen
/sbin/getpcaps $$
Capabilities for `15412': = cap_chown+i
  • nun kann der Benutzer nutzerXX Rechte auf Dateien ändern, die ihm nicht gehören:
ls -ld /root
chown nutzerXX /root
  • Für alle Benutzer unabhängig von der PAM-Konfiguration
setcap cap_chown=pe $(which chown)

2.3 Zugriff auf Ressourcen beschränken

2.3.1 Resourcenbeschränkungen über PAM (Modul pam_limits)

  • Konfigurationsdatei der PAM-Limits ist /etc/security/limits.conf. Liste der Resourcen die kontrolliert werden können:
    core Grösse einer Core-Dump Datei (KB)
    data maximale Grösse des zu ladenen Programms (KB)
    fsize maximale Dateigrösse (KB)
    memlock maximale Grösse des Prozesspeichers, welcher nicht ausgelagert werden darf (KB)
    nofile maximale Anzahl der offenen Dateien
    rss maximale Grösse des "resident set size" (Speicherverbrauch eines Prozesses im Hauptspeicher) (KB)
    stack maximale Grösse des Stacks eines Prozesses (KB)
    cpu maximale CPU Zeit (MIN)
    nproc maximale Anzahl von Prozessen
    as Limit des Addressbereiches (KB)
    maxlogins maximale Anzahl der Logins pro Benutzername
    maxsyslogins maximale Anzahl der Logins am System (aller Benutzer)
    priority Priorität von Benutzerprozessen
    locks maximale Anzahl von Datei-Locks
    sigpending maximale Anzahl von wartenden Signalen für Prozesse
    msgqueue maximaler Speicherverbrauch von POSIX message queues (bytes)
    nice maximaler "nice" Wert: [-20, 19]
    rtprio maximale Echtzeit Priorität von Prozessen
    chroot Benutzer darf den "chroot" Syscall ausführen (Debian spezifisch)
  1. Format der limits.conf Datei
    # Benutzer/Gruppe  Type    Ressource       Wert
    *                  soft    core            0
    root               hard    core            100000
    *                  hard    rss             10000
    @student           hard    nproc           20
    @faculty           soft    nproc           20
    @faculty           hard    nproc           50
    ftp                hard    nproc           0
    ftp                -       chroot          /ftp
    @student           -       maxlogins       4
    
  2. Aktuelle Limits der aktuellen Session anzeigen
    ulimit -a
    
  3. limit setzen und testen
    ulimit -S -t 2
    dd if=/dev/urandom | gzip > /dev/null
    
    apt install stress
    ulimit -S -t 2
    prlimit --cpu=10:20 stress -c 1
    
  4. Anzahl Logins beschränken

    wir passen die Anzahl der erlaubten Logins pro Benutzer an

    nutzerXX             -       maxlogins       2
    
  5. testen der neuen Konfiguration
    ssh nutzerXX@localhost
    

    3 x wiederholen oder auf mehr als 3 Konsolen anmelden

  6. CPU Zeit, RAM und offene Dateien beschränken

    durch eine Forkbombe (oder durch einen Sicherheitsfehler in einem Programm) kann ein Benutzer ein Linux/Unix System zum erliegen bringen. Eine Forkbombe erzeugt exponential viele Prozesse. Wenn die Erzeugung von Prozessen nicht beschränkt wurde, kommt das System in einen Zustand in dem es nicht mehr produktiv benutzt werden kann:

    forkbomb(){ forkbomb | forkbomb & }; forkbomb
    
    • oder Kurzversion einer Forkbombe
    :(){ :|:& };:
    
    nutzerXX             -       cpu             1
    nutzerXX             soft    nproc           800
    nutzerXX             hard    nproc           1000
    nutzerXX             -       priority        5
    
  7. testen
    ps -p $$ -o pid,user,nice,cmd
    ulimit -a
    forkbomb(){ forkbomb | forkbomb & }; forkbomb
    

2.3.2 nice, renice und cpulimit

apt install cpulimit
stress -c 8 # CPU Kerne * 2
renice -n <nice-wert> <pid>
cpulimit -l 50 -p <pidid> # nicht mehr empfohlen

2.3.3 ionice

  1. Disk IO per ionice beschränken
    • per ionice kann die IO-Priorität eines Prozesses kontrolliert werden ( ab Kernel 2.6.13 mit CFQ I/O-Scheduler ). Dokumentation zu ionice findet sich in der Linux-Kernel Dokumentation /usr/src/linux/Documentation/block/ioprio.txt.
    1. ionice Klassen
      Nummer Klasse
      0 keine Klasse zugewiesen
      1 Realtime (RT)
      2 Best-Efford (BE)
      3 Idle
      • Die ionice Klassen Realtime und Best-Efford unterscheiden die Prioritätsstufen 0-7 (Default 4)
      • einen Prozess als in der Klasse Idle laufen lassen
      ionice -c 3 dd if=/dev/zero of=/tmp/ionice-test
      
      • Prozess in die Best Effort Klasse (mit Prio "0") hochstufen
      ionice -c 2 -n 0 -p <pid-des-prozesses>
      
  2. iotop

    iotop zeigt die IO-Auslastung des Systems nach Prozessen an. In der Spalte "PRIO" wird die ionice Klasse und die Priorität angezeigt.

    apt install iotop
    stress -d 2
    iotop
    

2.4 Linux CGroups (Controll-Groups)

  • CGroup Tools installieren
apt install libpam-cgroup cgroup-tools libcgroup1
  • CGroups Informationen anzeigen
cat /proc/cgroups
ps xawf -eo pid,user,cgroup,args
systemd-cgls
systemd-cgtop
  • Eine neue Controll-Group erzeugen
cgcreate -g cpu,memory,blkio,devices,freezer:/resourcebox
  • CPU Auslastung auf 10% pro CPU-Kern begrenzen
cgset -r cpu.cfs_period_us=100000 \
      -r cpu.cfs_quota_us=$[ 10000 * $(getconf _NPROCESSORS_ONLN) ] \
           resourcebox
  • Speicher in der Controll-Group auf 256 MB begrenzen
cgset -r memory.limit_in_bytes=256M resourcebox
  • Plattenzugriffe auf 1 MB/s beschraenken
for dev in 253:0 252:0 252:16 8:0 8:16 1:0; do
  cgset -r blkio.throttle.read_bps_device="${dev}  1048576" resourcebox
  cgset -r blkio.throttle.write_bps_device="${dev} 1048576" resourcebox
done
  • Zugriff auf Geraetedateien verbieten
cgset -r devices.deny=a resourcebox
  • Zugriff auf "console", "null", "zero", "random" und "urandom"
for d in "c 5:1" "c 1:3" "c 1:5" "c 1:8" "c 1:9"; do
  cgset -r devices.allow="$d rw" resourcebox
done
  • Programm (Bash Shell als Beispiel) in der CGroup ausführen
cgexec -g cpu,memory,blkio,devices,freezer:/resourcebox \
  prlimit --nofile=256 --nproc=512 --locks=32 /bin/bash
  • Programm (Bash Shell als Beispiel) in der CGroup ausführen
cgexec -g cpu,memory,blkio,devices,freezer:/resourcebox \
  prlimit --nofile=256 --nproc=512 --locks=32 /bin/bash
  • Controll-Group löschen
cgdelete -g cpu,memory,blkio,devices,freezer:/resourcebox

2.4.1 Systemresourcen beschränken mit systemd-run

systemd-run stress -c 3
systemd-run stress -c 3
systemctl show run-r<UUID>.service
systemctl set-property run-r<UUID>.service CPUShares=100
systemctl set-property run-r<UUID>.service CPUQuota=100
systemd-run --on-active=20 -p CPUQuota=50% stress-ng --cpu 4

2.4.2 systemctl accounting anschalten

$EDITOR /etc/systemd/system.conf
-----
DefaultCPUAccounting=yes
DefaultIOAccounting=yes
DefaultBlockIOAccounting=yes
DefaultMemoryAccounting=yes
DefaultTasksAccounting=yes

2.4.3 systemd

systemctl set-property --runtime cups.service CPUQuota=10%
systemctl cat cups.service

2.5 systemd Sicherheit

2.5.1 Einfache Direktiven

  • Units unter anderer uid/gid laufen lassen
  • Zugriff auf Verzeichnisse beschränken
  • Prozesslimits setzen
$EDITOR /etc/systemd/system/simplehttp.service

[Unit]
Description=HTTP Server

[Service]
Type=simple
Restart=on-failure

#User=karl
#Group=users

#WorkingDirectory=/usr/share/doc
#PrivateTmp=yes
#ReadOnlyDirectories=/var
#InaccessibleDirectories=/home /usr/share/doc
#LimitNPROC=1  #darf nicht forken
#LimitFSIZE=0  #darf keine Files schreiben

ExecStart=/bin/python -m SimpleHTTPServer 8000

2.5.2 weitere Directiven und Isolationstechniken

  • PrivateNetwork=yes
  • CapabilityBoundingSet=CAP_CHOWN CAP_KILL
  • CapabilityBoundingSet=~CAP_SYS_PTRACE
  • DeviceAllow=/dev/null rw
  • ProtectSystem={ full | strict }
  • ProtectHome=

2.6 SSH

2.6.1 SSH Known Hosts hashen

ssh-keygen -H -f .ssh/known_hosts
$EDITOR .ssh/config
----------
HashKnownHosts yes
----------
chmod -Rc go= .ssh

2.6.2 SSH Passphrase ändern

ssh-keygen -p -f .ssh/id_ed25519.pub

2.6.3 Übung: SSH mit Schlüsseln statt mit Passwort (ca. 20 Minuten)

  • in dieser Übung arbeiten wir als Benutzer und als Administrator. Lege mit dem Übungs-Partner die Rolle fest (Benutzer oder Administrator) und führe die Übung durch. Danach wechselt die Rolle.
  • Administrator: lege einen Benutzeraccount für den Kollegen/Kollegin vor/hinter Dir im Kurs an (Passwort und Benutzername absprechen)
  • Administrator: OpenSSH Server installieren (wenn nicht schon geschehen)
sudo apt install openssh-server
  • Benutzer: Teste aus, dass Du Dich auf dem System des Übungs-Partners einloggen kannst. Bei der ersten Kontaktaufnahme wird der Fingerprint des Servers angezeigt. Dieser Fingerprint kann über den Administrator des Servers angefragt werden.
nutzerXX: ssh nutzerXX@notebookYY
  • Benutzer: nach dem Test wieder aus dem fernen Rechner ausloggen
  • Benutzer: als normaler Benutzer (nutzerXX, nicht root) einen neuen SSH-Schlüssel erstellen (4096 RSA). Eine Passphrase vergeben.
nutzerXX$ ssh-keygen -b 4096
  • Benutzer: den öffentlichen Schlüssel per SSH auf den fernen Rechner übertragen:
nutzerXX$ ssh-copy-id nutzerXX@notebookYY
  • Benutzer: Alternativ die Datei ~/.ssh/id_rsa.pub vom eigenen Rechner auf den fernen Rechner übertragen (z.B. per E-Mail senden) und den Administrator bitten, den eigenen Schlüssel in die Datei .ssh/authoritzed_keys einzutragen.
  • Administrator: Nun sind die Schlüssel ausgetauscht, und wir können Anmeldung per Passwort auf dem Server-System abschalten. Als root Benutzer:
$EDITOR /etc/ssh/sshd_config
------
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
------
  • Administrator: SSH-Dienst neu starten
systemctl restart sshd
  • Benutzer: Anmeldung am fernen Rechner testen, dies sollte nun nach Eingabe der Passphrase funktionieren
nutzerXX$ ssh nutzerXX@notebookYY
  • Benutzer: Wenn ein Benutzer ohne Schlüssel versucht, sich am fernen Rechner anzumelden, wird er gleich abgewiesen
ssh root@notebookYY
  • Info Benutzer: die Fingerprints der Server werden beim Client unter ~/.ssh/known_hosts gespeichert
  • Info Administrator: die öffentlichen Schlüssel werden auf dem fernen Rechner in der Datei ~/.ssh/authorized_keys gespeichert

2.6.4 SSH RSA-SHA1 Schlüssel sind abgekündigt

  • OpenSSH hat in früherern Versionen standardmässig Schlüssel mit dem RSA-SHA1 Algorithmus erzeugt. Dieser Algorithmus gilt inzwischen als unsicher und werden bald mit einer neuen Version von OpenSSH nicht mehr unterstützt
    • Daher sollten Benutzer von OpenSSH testen, ob sie noch RSA-SHA1 Schlüssel benutzen und diese ggf. durch neue Schlüssel austauschen
    • Test mit RSA-SHA1 abgeschaltet. Klappt die Anmeldung, so wird ein anderer Schlüssel benutzt. Schlägt die Anmeldung fehlt, so sollte ein neuer Schlüssel für diesen Benutzer erstellt werden:
      ssh -oHostKeyAlgorithms=-ssh-rsa user@host
      
    • Gibt es die folgende Fehlermeldung, dann benutzt der Server noch alte RSA-SHA1 Schlüssel und diese Schlüssel sind in der lokalen known-hosts Datei eingetragen:
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
      Someone could be eavesdropping on you right now (man-in-the-middle attack)!
      It is also possible that a host key has just been changed.
      The fingerprint for the ECDSA key sent by the remote host is
      SHA256:/7MPZYXQhPQ0uwZaupxxUC0EDU7I2D+s8OQCLtN69rE.
      Please contact your system administrator.
      Add correct host key in /home/nutzer/.ssh/known_hosts to get rid of this message.
      Offending RSA key in /home/nutzer/.ssh/known_hosts:157
      ECDSA host key for ssh-host.example.com has changed and you have requested strict checking.
      Host key verification failed.
      
    • Der Server-Betreiber sollte den alten RSA-SHA1 Schlüssel vom Server entfernen
    • Der Benutzer sollte den Hash-Eintrag des RSA-SHA1 aus der Datei known-hosts entfernen und dann den Hash des neuen Schlüssels mit dem Betreiber des Servers (oder via DNS, siehe unten) abgleichen
  • Empfohlene SSH Schlüssel-Algorithmen
  • Informationen: OpenSSH 8.3 released (and ssh-rsa deprecation notice)

2.6.5 SSH-Agent

  • SSH-Agent starten (wird normalerweise in der Benutzer-Sitzung gestartet, z.B. über ".profile")
eval $(ssh-agent)
  • die privaten SSH-Schlüssel dem SSH-Agent hinzufügen
ssh-add
ssh-add <schlüssel>
  • Fingerprints aller Schlüssel im Agent anzeigen
ssh-add -l
  • alle Schlüssel im Agent anzeigen
ssh-add -L
  • Agent sperren/entsperren
ssh-add -x
ssh-add -X
  • Schlüssel im SSH-Agent löschen
ssh-agent -D

2.6.6 SSH Fingerprint eines Servers prüfen

  • SSH Fingerprint eines Schlüssels auf einem Server anzeigen (zur Prüfung eines ersten Logins)
ssh-keygen -l -f /etc/ssh/ssh_host_<algorithm>_key.pub

2.6.7 lokale SSH-Konfigurationsdatei

  • Bei komplexen SSH-Konfigurationen ist es hilfreich, die SSH-Parameter pro Ziel-System in der lokalen SSH-Konfigurationsdatei für den Benutzer abzulegen. Fast alle Kommandozeilen-Optionen des SSH-Clients können in dieser Konfigurationsdatei festgelegt werden (siehe man ssh).
  • Beispiel einer lokalen SSH-Konfigurationsdatei für einen Benutzer. Datei ~/.ssh/config
Host zielhost                                          # symbolischer Name
        Hostname zielhost.example.com                  # echter DNS-Name
	User nutzerXX                                  # Standard Benutzer
	Compression yes                                # gzip Kompression an
	VerifyHostKeyDNS yes                           # Host-Key per DNS prüfen
	Port 65123                                     # SSH läuft auf diesem Port
	ProxyJump jumphost.example.com                 # Verbindung über Jumphost
  1. Übung: lokale SSH-Client-Konfigurationsdatei
    • Zeit: 15 Minuten
    • erstelle eine lokale SSH-Konfigurationsdatei ~/.ssh/config für die Verbindung auf die IP-Adresse 192.168.1.241 (Laptop des Trainers)
      • vergebe den symbolischen Namen trainer für den Server
      • SSH-Server läuft auf Port 8422
      • Benutzername nutzer, Passwort villa
      • benutze die IP-Adresse des Servers als Hostnamen in der Konfiguraionsdatei
    • die SSH Konfigurationsdatei darf nun für den Benutzer lesbar sein (ggf. müssen die Dateiberechtigungen angepasst werden)
    • teste die Verbindung per symbolischen Namen
    ssh trainer
    
    • Beispiellösung
    Host trainer
      Hostname 192.168.1.241
      User nutzer
      Port 8422
    
  2. Weitere Informationen und Tipps: Simplify Your Life With an SSH Config File

2.6.8 Agent-Forwarding

  • Agent-Funktion an einem Jumphost weitergeben. Nun kann sich der Benutzer vom Jumphost mit Schlüssel an weiteren SSH-Servern anmelden
ssh -A <jumphost>
  1. Übung: SSH-Forwarding
    • der Nachbar sollte uns einen Benutzer auf seinem System mit Deinem Benutzernamen erstellen
    • Für diese Übung müssen wir unseren öffentlichen Schlüssel auf den Laptop eines Nachbarn installieren (dies wurde ggf. schon am Tag 2 gemacht: Übung Anmeldung am SSH mit Schlüssel
    ssh-copy-id nutzerXX@notebookYY
    
    • nachdem die Schlüssel kopiert wurden kann die Passwort-Authentisierung in der Datei /etc/ssh/sshd_config ausgeschaltet werden
    [...]
    PasswordAuthentication no
    [...]
    
    • und den SSH-Dienst neu starten
    systemctl restart sshd
    
    • nun sollte auf dem Laptop nur noch eine Anmeldung per Schlüssel möglich sein
    • stelle sicher, das der SSH-Agent für die aktuelle Shell-Sitzung aktiv ist und lade die eigenen Schlüssel in den SSH-Agent
    ssh-add -l
    
    • Teste die Anmeldung an den Trainer-Laptop (hier Anmeldung per Passwort villa)
    ssh trainer
    
    • Teste, das eine Anmeldung mit dem eigenen Benutzer (nutzerXX) von Laptop des Trainers auf den Laptop des Übungs-Partners (notebookYY) nicht möglich ist
    trainer-laptop$ ssh nutzerXX@notebookYY
    
    • den Laptop des Trainers wieder verlassen
    trainer-laptop$ exit
    
    • wir nehmen an, dass eine direkte Netzwerkverbindung zwischen dem eigenen Laptop und dem Laptop des benachbarten Teilnehmers nicht möglich ist, ein Login auf diesem Laptop muss über den Umweg des Trainer-Laptops geschehen (Jump-Host)
    • Teste die SSH-Agent-Forwarding Funktion mit einer Anmeldung an den Jump-Host (Trainer-Laptop per Passwort villa) und von dort aus einer Anmeldung an den Laptop des benachbarten Teilnehmers. Die zweite Anmeldung solle bei aktiven SSH-Agent ohne Passwortabfrage funktionieren
    notebookXX$ ssh -A trainer
    trainer-laptop$ ssh nutzerXX@notebookYY
    

2.6.9 SSH Agent-Forwarding vs. ProxyCommand

  1. AgentForwarding Alternative ProxyCommand
    • vor OpenSSH 7.3
    Host jumphost
     	User nutzer
     	Hostname 192.168.1.241 # Trainer Laptop
    	Port 8422
    
    Host internalserver
     	User nutzerXX
     	Hostname notebookYY # Laptop des anderen Teilnehmers
     	Port 22
     	ProxyCommand ssh -q -W %h:%p jumphost
    
    • seit OpenSSH 7.3
    Host jumphost
     	User nutzer
     	Hostname 192.168.1.241 # Trainer Laptop
    	Port 8422
    
    Host internalserver
     	User nutzerXX
     	Hostname notebookYY # Laptop des anderen Teilnehmers
     	Port 22
     	ProxyJump jumphost
    
    • ProxyJump auf der Kommandzeile (seit OpenSSH 7.3)
    ssh -J jumphost benutzer@internalserver
    
  2. Übung:
    • erstelle eine lokale Konfigurationsdatei ~/.ssh/config mit der ProxyCommand Konfiguration (siehe oben)
    • SSH-Verbindung durch den JumpHost (Trainer-Laptop) zum Laptop eines anderen Teilnehmers testen
    ssh internalserver
    

2.6.10 VisualHostKey

  • der Konfigurationsparameter VisualHostKey in der Datei /.ssh/config zeigt eine visuelle Darstellung des Schlüssel-Hash jedes Ziel- und Jump-Host Servers an
VisualHostKey yes

2.6.11 SSH Tunnel

  • Über SSH Tunnel können beliebige Ports über die SSH Verbindung geleitet werden
  • Tunnel von Port 80 auf dem Server zu Port 8080 auf dem Client
ssh -L 8080:notebookXX:80 nutzerXX@notebookXX
ssh -L 8080:datenbank:80 nutzerXX@notebookXX
  • Rückwärts-Tunnel: vom Ziel-System zurück auf den Client. Dieses Beispiel öffnet einen Tunnel von localhost:8000 auf dem Zielsystem auf Port 8000 des SSH-Clients
ssh -R 8000:notebookXX:8000 nutzerXX@notebookXX
  • Socks-Proxy Forwarding (Web-Browsen durch den Tunnel), im Browser die Socks-Proxy Konfiguration auf 127.0.0.1 Port 8080 setzen
ssh -CD 127.0.0.1:8080 nutzer@server
  1. Übung: SSH Tunnel
    • erstelle einen SSH-Tunnel von Port 8080 (lokal) auf die IPv4-Loopback-Adresse (127.0.0.XX; x=Teilnehmernummer, z.B. 42) des Trainer-Laptops, Port 8000:
    ssh -L 8080:127.0.0.XX:8000 trainer
    
    • auf dem Trainer-Laptop erstellen wir eine minimale HTML-Datei
    mkdir ~/webseiteXX
    cd ~/webseiteXX
    ~/webseiteXX% echo "dies ist der Webserver von NutzerXX" > index.html
    
    • auf dem Trainer-Laptop den Python3 Webserver auf der Loopback-Adresse, Port 8000, starten
    ~/webseiteXX% python3 -m http.server --bind 127.0.0.XX
    
    • Starte Firefox-Browser, verbinde Dich mit der eigenen Loopback-Adresse Port 8080 (URL http://127.0.0.1:8080/). Es sollte die minimale Webseite aus dem Heimverzeichnis auf dem Trainer-Laptop erscheinen

2.6.12 SSH-Escape

  • A tilde (~) after an Enter is the escape sequence of SSH
  • ~~ Tilde senden
  • ~. SSH-Verbindung sofort stoppen
  • ~<Ctrl-Z> SSH Sitzung in den Hintergrund senden (mit fg wieder in den Vordergrund holen)
  • ~& SSH als 'daemon' in den Hintergrund senden und vom Terminal ablösen
  • ~? Hilfe anzeigen.
  • ~R neuen Sitzungschlüssel aushandeln
  • ~C SSH Komandozeile anzeigen (kann benutzt werden um neue Tunnel in schon bestehende Verbindungen einzubauen)
  • ~# bestehende SSH-Tunnel anzeigen

3 Tag 3

3.1 SSH (Fortsetzung)

3.1.1 Socks-SSH-Proxy

  • Socks-Proxy Forwarding (Web-Browsen durch den Tunnel), im Browser die Socks-Proxy Konfiguration auf 127.0.0.1 Port 8080 setzen
    • Option -C schaltet Kompression der Daten im Tunnel ein
    • Option -D schaltet den Socks-Proxy für den SSH-Tunnel ein
ssh -C -D 127.0.0.1:8080 nutzer@server

3.1.2 Ausführbare Befehle über die authorized_keys beschränken

command="foobar" ssh-rsa AAAAB3Nza… calls "foobar" and only "foobar" upon every login with this key
from="computer" ssh-rsa AAAAB3Nza… allows access with this key only from the host "computer".

3.1.3 SSH-Schluessel Fingerprints in DNS

  • SSH Fingerprint im DNS hinterlegen (DNSSEC Absicherung empohlen!). SSHFP Records erstellen (auf dem Server, je ein Aufruf pro Schlüssel-Type (RSA, ECDSA, ED25519 …):
ssh-keygen -r <hostname> -f /etc/ssh/ssh_host_<algorithm>_key.pub
  • SSH mit Prüfung des SSH-Fingerabdrucks in DNS
ssh -o "VerifyHostKeyDNS ask" <hostname>
  • in SSH-Config Datei übernehmen
$EDITOR ~/.ssh/config
----
HOST *
  VerifyHostKeyDNS ask
  • Test
ssh host.example.com
The authenticity of host 'host.example.com (2001:db8:2b6:0:ba27:ebff:fe12:30db)' can't be established.
ECDSA key fingerprint is SHA256:ue1FlRUMmkPNhgFE55yqnnFl58FOlMnDGheCxQn2tWg.
Matching host key fingerprint found in DNS.
ECDSA key fingerprint is MD5:2e:a1:3c:94:d0:cb:ed:85:67:2e:7a:85:1c:bc:f3:70.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
  • mit VerifyHostKeyDNS yes
ssh -v <host>
[...]
debug1: found 4 secure fingerprints in DNS
debug1: matching host key fingerprint found in DNS
[...]
  • Wenn OpenSSH Probleme hat, die DNSSEC Authentizität der SSHFP zu prüfen, muss ggf. EDNS in der Resolver-Konfiguration des Linux eingeschaltet werden
$EDITOR /etc/resolv.conf
----
[...]
options edns0

3.1.4 Verwaltung von SSH authorized_keys auf dem Server

3.1.5 SSHign - Daten mit SSH-Schlüsseln signieren

3.1.6 Jass - Daten mit SSH-Schlüsseln verschlüsseln

3.1.7 Alerting or notifying on SSH logins / PAM

  • Original von Jan-Piet Mens mit Benachrichtigung via MQTT: https://jpmens.net/2018/03/25/alerting-on-ssh-logins/
  • zentralisierte Benachrichtigung bei SSH-Logins auf einem Rechner der eigenen IT-Infrastruktur. Kommunikation zwischen SSH-Server und zentraler Monitoring-Instatnz über leichtgewichtiges UDP, E-Mail Kommunikationsparameter werden zentral verwaltet.
  • Quellcode des hare Programms (PAM-Modul für die SSH-Server)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
#include <sys/socket.h>

/*
 * hare.c (C)2018 by Jan-Piet Mens <jp@mens.de>
 */

#define PORTNO  8035

#define env(K)  ( getenv(K) ? getenv(K) : "<unknown>" )

int main(int argc, char **argv)
{
        struct sockaddr_in servaddr;
        unsigned long addr;
        int sockfd;
        char *host = argv[1], buf[BUFSIZ], myhostname[BUFSIZ];
        char *pamtype = env("PAM_TYPE");        /* Linux */
        char *pamsm = env("PAM_SM_FUNC");       /* FreeBSD https://www.freebsd.org/cgi/man.cgi?query=pam_exec */

        if (strcmp(pamtype, "open_session") != 0 && strcmp(pamsm, "pam_sm_open_session") != 0) {
                fprintf(stderr, "Neither PAM open_session nor pam_sm_open_session detected\n");
                return 0;
        }

        if (argc != 2) {
                fprintf(stderr, "Usage: %s address\n", *argv);
                exit(2);
        }

        if (gethostname(myhostname, sizeof(myhostname)) != 0)
                strcpy(myhostname, "?");

        snprintf(buf, sizeof(buf), "%s login to %s from %s via %s",
                env("PAM_USER"),
                myhostname,
                env("PAM_RHOST"),
                env("PAM_SERVICE"));

        addr = inet_addr(host);

        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(PORTNO);
        memcpy((void *)&servaddr.sin_addr, (void *)&addr, sizeof(addr));

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);

        if (sendto(sockfd, (void *)buf, strlen(buf), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
                perror("sendto");
        }
        return (0);
}
  • Übersetzen und Installieren des hare Programms (ggf. das Paket gcc installieren)
gcc -O2 -o hare hare.c
sudo cp hare /usr/local/sbin
  • das hare Programm in die PAM-Konfiguration /etc/pam.d/sshd eintragen. Ziel-IP ist der Laptop des Trainers (192.168.1.241)
[...]
session    optional     pam_exec.so /usr/local/sbin/hare <ip-des-hare-servers>
[...]
  • der zentrale Python-Server /usr/local/bin/hared.py, mit der Funktion pro SSH-Login eine Benachrichtigungs-Mail zu versenden (läuft auf dem Laptop des Trainers)
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import json
import smtplib, ssl
import random
import string
import datetime

__author__    = 'Jan-Piet Mens <jp()mens.de> / Carsten Strotmann <carsten()strotmann.de>'

myhostname     = "debian.example.com" # Domain-Name des E-Mail Senders (diese Maschine)
smtp_server    = "mail.example.com" # Name of the Mail-Server
smtp_port      = "587"  # SMTP with STARTTLS
sender_email   = "servernotification@example.com"
receiver_email = "admin@example.com"
smtp_user      = "admin"
smtp_password  = "secret"

server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 8035))

while True:
    message, address = server_socket.recvfrom(1024)
    host, port = address

    data = {
        'host' : host,
        'msg'  : message,
    }

    js = json.dumps(str(data))
    # print(js)


    message = "To: <{}>\n".format(receiver_email)
    message = message + "From: <{}>\n".format(sender_email)
    message = message + "Message-Id: <{}@example.com>\n".format(''.join(random.choices(string.ascii_uppercase + string.digits, k=10)))
    time = datetime.datetime.now()
    message = message + "Date: {} \n".format(time.strftime('%d %b %Y  %H:%M:%S %z'))
    message = message + "Subject: SSH Login to {}\n\n".format(data["host"])
    message = message + "SSH Login into {} detected, Message: {}".format(data["host"], data["msg"])

    # Create a secure SSL context
    context = ssl.create_default_context()
    # if the TLS certificate of the mail server does not match
    # the mail servers hostname or domain-name, disable hostname checking
    # context.check_hostname = False
    server = smtplib.SMTP()
    # Try to log in to server and send email
    try:
        server.connect(smtp_server,smtp_port)      # Connect to the server
        server.ehlo(myhostname)                    # Send EHLO
        server.starttls(context=context)           # TLS Secure the connection
        server.ehlo(myhostname)                    # Another EHLO, now TLS secured
        server.login(smtp_user, smtp_password)     # Login to the server

        server.sendmail(sender_email, receiver_email, message) # send the mail
    except Exception as e:
        # Print any error messages to stdout
        print("Error: ", e)
    finally:
        if (server):
            server.quit()

3.1.8 eine sichere SSH-Server Konfiguration

$EDITOR /etc/ssh/sshd_config
  • Nur Protokoll Version 2 erlauben
Protocol 2
  • Sichere Schlüssel-Austausch-Verfahren
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
  • neue DH Moduli für "diffie-hellman-group-exchange-sha256" (Achtung, dauert lange!) Hintergründe unter http://weakdh.org
ssh-keygen -G /etc/ssh/moduli.all -b 4096
ssh-keygen -T /etc/ssh/moduli.safe -f /etc/ssh/moduli.all
mv /etc/ssh/moduli.safe /etc/ssh/moduli
rm /etc/ssh/moduli.all
chcon -v --type=etc_t /etc/ssh/moduli
  • EC-ED25519-Kurve Schlüssel bevorzugen
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
  • Sichere symmetrische Verschlüsselungs-Algorithmen
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
  • Sichere Message-Authenication-Codes (MAC)
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
  • Host-Keys neu erzeugen (Achtung: Clients werden Warnungen bekommen, Kunden und Kollegen informieren!)
cd /etc/ssh
rm ssh_host_*key*
ssh-keygen -t ed25519 -f ssh_host_ed25519_key < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null
  • SSH Server neu starten
systemctl restart sshd
  • SSH Client Parameter testen
ssh -Q cipher
ssh -Q cipher-auth
ssh -Q mac
ssh -Q kex
ssh -Q key
  • Jetzt nochmal per SSH auf dem fernen Rechner einloggen, -v Zeigt die Kommunikationsparameter an
nutzerXX$ ssh -v nutzer@notebookYY
  • Hier sollte jetzt eine Warnung ausgegeben worden sein, da die Host-Schlüssel nicht mehr mit den Fingerprints in der known_hosts Datei übereinstimmen. Den Admin des fernen Servers fragen, ob er die Schlüssel auf dem Rechner neu erstellt hat. Wenn der Admin dies bestätigt, dann er Texteditor den alten Fingerprint aus der ~/.ssh/known_hosts Datei löschen.
  • SSH Client ~/.ssh/config
VerifyHostKeyDNS yes
VisualHostKey yes

3.2 Linux-Distributionen (Sicherheitsbewertung)

3.3 Software-Sicherheitsfunktionen unter Linux

3.3.1 Kernel-Konfigurationsoptionen

Der Linux-Kernel bietet einige Sicherheitfunktionen, welche zur Zeit der Übersetzung des Kernels aus den Quellen angeschaltet werden können. Einige dieser Funktionen haben negative Auswirkungen auf die Ausführungsgeschwindigkeit des Systems, so das diese Funktionen nicht in allen Distributionen gesetzt sind. In den Klammern sind die jeweiligen Konfigurationsnamen aufgeführt. In einem Linux-System können diese Namen in der Kernel-Konfigurationsdatei geprüft werden. Beispiel:

zcat /proc/config.gz | grep CONFIG_SECURITY_DMESG_RESTRICT

oder, wenn /proc/config.gz nicht vorhanden.

cat  /boot/config-$(uname -r) | grep CONFIG_SECURITY_DMESG_RESTRICT
  1. Die Funktionen (Kernel 4.15+):
    • Zugriff auf Kernel-Syslogmeldungen via dmesg unterbinden (CONFIG_SECURITY_DMESG_RESTRICT)
    • Speicher-Kopierroutinen zwischen Kernel- und Userspace härten (CONFIG_HARDEN_USERCOPY)
    • String- und Speicher-Funktionen gegen Buffer-Overflows härten (CONFIG_FORTIFY_SOURCE)
    • Lade alle Kernel-Dateien aus einem (nur-lese) Dateisystem (Module, Firmware, LSM-Dateien) (CONFIG_SECURITY_LOADPIN)
  2. Kernel-Schnittstelle für Hardware- und CPU Sicherheitsprobleme
    • Seit Kernel 4.15 besitzt der Linux-Kernel eine Schnittstelle zum Abfragen von bekannten Hardware- und CPU-Sicherheitsproblemen, und Informationen ob der laufende Linux-Kernel gegen die Sicherheitsprobleme schützt.
    grep . /sys/devices/system/cpu/vulnerabilities/*
    

3.3.2 Userspace Software-Sicherheitsfunktionen unter Linux

  1. Programm zum Prüfen der Sicherheitsfunktionen
    apt install git binutils
    git clone https://github.com/slimm609/checksec.sh
    cd checksec.sh/
    bash ./checksec --proc-all
    bash ./checksec --kernel
    bash ./checksec --dir=/usr/sbin --verbose
    

3.4 Linux Sicherheitsmeldungen

Quelle Link
Linux Weekly News Sicherheitsmeldungen https://lwn.net/Security/
Red Hat Sicherheitsmeldungen https://access.redhat.com/security/security-updates/#/security-advisories
Debian Security Tracker https://security-tracker.debian.org/tracker/
Debian "stable" Sicherheitsmeldungen https://security-tracker.debian.org/tracker/status/release/stable
SUSE Sicherheitsmeldungen https://www.suse.com/de-de/support/update/
Ubuntu Sicherheitsmeldungen https://www.ubuntu.com/usn/
Gentoo Sicherheitsmeldungen https://security.gentoo.org/glsa

3.5 Audit Subsystem

  • Das Audit-Subsystem überwacht Dateien und Systemaufrufe (Systemcalls) und schreibt Log-Informationen in das Audit-Log
  • Audit Subsystem Homepage https://people.redhat.com/sgrubb/audit/
  • Audit-Subsystem Programme installieren
apt install auditd audispd-plugins
  • Audit-Subsystem Trace eines Prozesses (hier 4 x ICMP Echo per ping)
autrace /bin/ping -c 4 8.8.8.8
  • Audit Log für einen speziellen autrace Aufruf anschauen
ausearch -i -p <audit-id>
  • Alle System-Calls des autrace Aufruf auflisten und nach Häufigkeit sortiert ausgeben
ausearch -i -p <audit-id> | grep type=SYSCALL | cut -f 6 -d ' ' | sort | uniq -c
  • Audit-Daemon Konfiguration anpassen (Grössen-Werte in MB)
$EDITOR /etc/audit/auditd.conf
----
space_left=4000
admin_space_left=2000
num_logs=10
max_log_file=<max-groesse-der-log-datei>
max_log_file_action=rotate
  • Audit-Dämon anschalten (so dass er bei einem Restart neu gestartet wird) und prüfen das der Prozess läuft
systemctl enable --now auditd
systemctl status auditd
  • eine Audit-Policy erstellen
$EDITOR /etc/audit/rules.d/audit.rules
  • hier ist eine Beispiel-Policy:
## First rule - delete all
-D

## Increase the buffers to survive stress events.
## Make this bigger for busy systems
-b 8192

## This determine how long to wait in burst of events
--backlog_wait_time 0

## Set failure mode to syslog
-f 1

# audit_time_rules - Record attempts to alter time through adjtime
-a always,exit -F arch=b64 -S adjtimex -k audit_time_rules

# audit_time_rules - Record attempts to alter time through settimeofday
-a always,exit -F arch=b64 -S settimeofday -k audit_time_rules

# audit_time_rules - Record Attempts to Alter Time Through stime
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -S clock_settime -k audit_time_rules

# audit_time_rules - Record Attempts to Alter Time Through clock_settime
-a always,exit -F arch=b64 -S clock_settime -k audit_time_rules

# Record Attempts to Alter the localtime File
-w /etc/localtime -p wa -k audit_time_rules

# Record Events that Modify User/Group Information
# audit_account_changes
-w /etc/group -p wa -k audit_account_changes
-w /etc/passwd -p wa -k audit_account_changes
-w /etc/gshadow -p wa -k audit_account_changes
-w /etc/shadow -p wa -k audit_account_changes
-w /etc/security/opasswd -p wa -k audit_account_changes

# Record Events that Modify the System's Network Environment
# audit_network_modifications
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k audit_network_modifications
-w /etc/issue -p wa -k audit_network_modifications
-w /etc/issue.net -p wa -k audit_network_modifications
-w /etc/hosts -p wa -k audit_network_modifications

#Record Events that Modify the System's Mandatory Access Controls
-w /etc/selinux/ -p wa -k MAC-policy

#Record Events that Modify the System's Discretionary Access Controls - chmod
-a always,exit -F arch=b32 -S chmod -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chmod  -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - chown
-a always,exit -F arch=b32 -S chown -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chown -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - fchmod
-a always,exit -F arch=b32 -S fchmod -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchmod -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - fchmodat
-a always,exit -F arch=b32 -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - fchown
-a always,exit -F arch=b32 -S fchown -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchown -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - fchownat
-a always,exit -F arch=b32 -S fchownat -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchownat -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - fremovexattr
-a always,exit -F arch=b32 -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - fsetxattr
-a always,exit -F arch=b32 -S fsetxattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fsetxattr -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - lchown
-a always,exit -F arch=b32 -S lchown -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S lchown -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - lremovexattr
-a always,exit -F arch=b32 -S lremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S lremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - lsetxattr
-a always,exit -F arch=b32 -S lsetxattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S lsetxattr -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - removexattr
-a always,exit -F arch=b32 -S removexattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S removexattr -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Events that Modify the System's Discretionary Access Controls - setxattr
-a always,exit -F arch=b32 -S setxattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S setxattr -F auid>=500 -F auid!=4294967295 -k perm_mod

#Record Attempts to Alter Logon and Logout Events
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins

#Record Attempts to Alter Process and Session Initiation Information
-w /var/run/utmp -p wa -k session
-w /var/log/btmp -p wa -k session
-w /var/log/wtmp -p wa -k session

#Ensure auditd Collects Unauthorized Access Attempts to Files (unsuccessful)
-a always,exit -F arch=b32 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access
-a always,exit -F arch=b32 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access
-a always,exit -F arch=b64 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access
-a always,exit -F arch=b64 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access

#Ensure auditd Collects Information on the Use of Privileged Commands
#
#  Find setuid / setgid programs then modify and uncomment the line below.
#
##  sudo find / -xdev -type f -perm -4000 -o -perm -2000 2>/dev/null
#
# -a always,exit -F path=SETUID_PROG_PATH -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged

#Ensure auditd Collects Information on Exporting to Media (successful)
-a always,exit -F arch=b64 -S mount -F auid>=500 -F auid!=4294967295 -k export

#Ensure auditd Collects File Deletion Events by User
-a always,exit -F arch=b64 -S rmdir -S unlink -S unlinkat -S rename -S renameat -F auid>=500 -F auid!=4294967295 -k delete

#Ensure auditd Collects System Administrator Actions
-w /etc/sudoers -p wa -k actions

#Ensure auditd Collects Information on Kernel Module Loading and Unloading
-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules

#Make the auditd Configuration Immutable
-e 2
  • die Policy kompilieren und prüfen
augenrules --check
  • die neue Policydatei in den Kernel laden
augenrules --load
  • aktive Regeln auflisten
auditctl -l
  • Status des Audit-Subsystems
# auditctl -s
enabled 2
failure 1
pid 12901
rate_limit 0
backlog_limit 8192
lost 0
backlog 0
backlog_wait_time 0
loginuid_immutable 0 unlocked
  • Alle Audit-Einträge zum Thema "sudo" zeigen
ausearch -i -x sudo
  • Report über fehlgeschlagende Anmeldeversuche
ausearch -m USER_AUTH,USER_ACCT --success no
  • Alle Audit-Meldungen für Benutzer UID 1000
ausearch -ua 1000 -i
  • Fehlgeschlagende Syscalls seit gestern
ausearch --start yesterday --end now -m SYSCALL -sv no -i
  1. Aufgabe:
    • das Audit-Subsystem um neue Regel(n) zu Systemd erweitern:
      • alle Systemd-Konfigurationsdateien mit der Endung *.conf direkt unter (nicht in den Unterverzeichnissen) /etc/systemd sollen auf Schreibzugriffe überwacht werden
      • die neue Richtlinie kompilieren und aktivieren (ggf. Reboot notwendig)
      • die neue Richtlinie testen, in dem manuell an einer der überwachten Dateien eine Änderung vorgenommen wird
      • die Audit-Meldungen per ausearch anzeigen und analysieren
  2. Beispiel-Lösung
    [...]
    # Systemd Konfiguration
    -w /etc/systemd/journald.conf -p wa -k systemd
    -w /etc/systemd/logind.conf -p wa -k systemd
    -w /etc/systemd/networkd.conf -p wa -k systemd
    -w /etc/systemd/resolved.conf -p wa -k systemd
    -w /etc/systemd/sleep.conf -p wa -k systemd
    -w /etc/systemd/system.conf -p wa -k systemd
    -w /etc/systemd/timesyncd.conf -p wa -k systemd
    -w /etc/systemd/user.conf -p wa -k systemd
    [...]
    

3.5.1 Audit-Hilfsprogramme

  • die letzten Logins auf dem System anzeigen
aulast
  • Wann haben sich Benutzer zum letzten Mal eingelogged?
aulastlog
  • Zusammenfassung des Audit-Log
aureport
  • grafische Auswertung von Audit-Logs
$ sudo apt install graphviz gnuplot git
$ git clone https://github.com/cstrotm/audit-visualize
$ cd audit-visualize
$ chmod +x ./mkgraph
$ chmod +x ./mkbar
  • grafische Reports erstellen
$ sudo aureport -s -i --summary  | bash ./mkbar syscall
$ sudo aureport -f -i --summary --failed | bash ./mkbar failed-access
$ sudo aureport -e -i --summary | egrep -vi '(syscall|change)'
$ sudo aureport -e -i --summary | egrep -vi '(syscall|change)' | bash ./mkbar events2
  • Syscall Benutzung von Programmen
$ sudo aureport -s -i | awk '/^[0-9]/ { printf "%s %s\n", $6, $4 }' | sort | uniq | bash ./mkgraph
Gzipping graph...
Graph was written to gr.png
  • welcher Benutzer führt welche Programme aus?
sudo aureport -u -i | awk '/^[0-9]/ { printf "%s %s\n", $4, $7 }' | sort | uniq | bash ./mkgraph
  • wer greift auf welche Dateien zu?
sudo aureport -f -i | awk '/^[0-9]/ { printf "%s %s\n", $8, $4 }' | sort | uniq | bash ./mkgraph

3.5.2 CIS Benchmarks mit Vorlagen für Audit-Regeln

3.6 Secomp-bpf

3.7 eBPF/BCC

  • eBPF ist die extended Berkeley Packet Filter Infrastruktur im Linux Kernel
  • eBPF ist eine Weiterentwicklung der Berkeley Packet Filter Technologie (Firewall) https://en.wikipedia.org/wiki/Berkeley_Packet_Filter
  • eBPF ist eine Technologie im Linux-Kernel, welche Sandbox-Programme in einem Betriebssystem-Kernel ausführen kann.
    • eBPF wird verwendet, um die Fähigkeiten des Kernels sicher und effizient zu erweitern, ohne dass der Kernel-Quellcode geändert oder Kernel-Module geladen werden müssen.
    • eBPF kann neben Netzwerk-Paketen auch andere Daten aus dem Linux-Kernel überwachen und manipulieren

ebpf.png

  • Einsatzgebiete:
    • Netzwerksicherheit (erweiterte Firewall-Funktionen)
    • Host-Sicherheit
    • Forensik
    • Fehler-Diagnose
    • Performance-Messungen
  • eBPF wird derzeit von Microsoft auf die Windows Betriebssysteme portiert

3.7.1 BCC Übersicht

  • BCC ist die BPF Compiler Collection, eine Sammlung von Tools und eBPF Programmen

    bcc_tracing_tools_2019.png

3.7.2 BCC Installieren (inkl. der Kernel-Header)

  • BCC Programme sind abhängig von der jeweiligen Kernel-Version und müssen daher auf der Maschine mit Hilfe der aktuellen Kernel-Header kompiliert werden. Das Kompilieren geschied im Hintergrund beim Aufruf des Wrapper-Scripts.
# apt install bpfcc-tools bpfcc-lua bpftrace python3-bpfcc
# apt install linux-headers-$(uname -r)

3.7.3 BCC Tools für Linux-Server

  • Unter Debian enden alle BCC Programme auf -bpfcc:
    # ls -l /usr/sbin/*bpfcc
    -rwxr-xr-x 1 root root 34536 Feb  4  2019 /usr/sbin/argdist-bpfcc
    -rwxr-xr-x 1 root root  1648 Feb  4  2019 /usr/sbin/bashreadline-bpfcc
    -rwxr-xr-x 1 root root  4231 Feb  4  2019 /usr/sbin/biolatency-bpfcc
    -rwxr-xr-x 1 root root  5066 Feb  4  2019 /usr/sbin/biosnoop-bpfcc
    -rwxr-xr-x 1 root root  6387 Feb  4  2019 /usr/sbin/biotop-bpfcc
    -rwxr-xr-x 1 root root  1721 Feb  4  2019 /usr/sbin/bitesize-bpfcc
    -rwxr-xr-x 1 root root  2453 Feb  4  2019 /usr/sbin/bpflist-bpfcc
    -rwxr-xr-x 1 root root  6339 Feb  4  2019 /usr/sbin/btrfsdist-bpfcc
    -rwxr-xr-x 1 root root 10101 Feb  4  2019 /usr/sbin/btrfsslower-bpfcc
    -rwxr-xr-x 1 root root  4674 Feb  4  2019 /usr/sbin/cachestat-bpfcc
    [...]
    
  • Im folgenden werden einige BCC Tools vorgestellt, welche für die Sicherheit von Linux-Servern interessant sind
  1. opensnoop
    • Das BCC-Programm opensnoop-bpfcc zeigt systemweit an welche Prozesse auf Dateien zugreifen (lesend und schreibend):
      # opensnoop-bpfcc
      PID    COMM               FD ERR PATH
      16884  links               3   0 /lib/x86_64-linux-gnu/liblz.so.1
      16884  links               3   0 /lib/x86_64-linux-gnu/liblzma.so.5
      16884  links               3   0 /lib/x86_64-linux-gnu/libbz2.so.1.0
      16884  links               3   0 /lib/x86_64-linux-gnu/libbrotlidec.so.1
      16884  links               3   0 /lib/x86_64-linux-gnu/libz.so.1
      16884  links               3   0 /lib/x86_64-linux-gnu/libssl.so.1.1
      16884  links               3   0 /lib/x86_64-linux-gnu/libcrypto.so.1.1
      16884  links               3   0 /lib/x86_64-linux-gnu/libgpm.so.2
      16884  links               3   0 /lib/x86_64-linux-gnu/libc.so.6
      16884  links               3   0 /lib/x86_64-linux-gnu/libm.so.6
      16884  links               3   0 /lib/x86_64-linux-gnu/libbrotlicommon.so.1
      16884  links               3   0 /lib/x86_64-linux-gnu/libdl.so.2
      16884  links              -1   2 /etc/links.cfg
      16884  links              -1   2 /etc/.links.cfg
      16884  links              -1   2 /root/.links2/links.cfg
      16884  links              -1   2 /root/.links2/.links.cfg
      16884  links              -1   2 /root/.links2/html.cfg
      16884  links              -1   2 /root/.links2/.html.cfg
      16884  links              -1   2 /root/.links2/user.cfg
      16884  links              -1   2 /root/.links2/.user.cfg
      16884  links               8   0 /root/.links2/bookmarks.html
      16884  links               8   0 /root/.links2/links.his
      16884  links               8   0 /dev/pts/1
      16884  links              -1   2 /dev/gpmctl
      11348  tmux: server        7   0 /proc/16884/cmdline
      11348  tmux: server        7   0 /proc/16880/cmdline
      11348  tmux: server        7   0 /proc/16880/cmdline
      
  2. statsnoop
    • Das BCC-Programm statsnoop-bpfcc zeigt systemweit Dateizugriffe mit den stat Systemaufruf:
      # statsnoop-bpfcc
      PID    COMM               FD ERR PATH
      11348  tmux: server        0   0 /etc/localtime
      11349  bash                0   0 .
      11349  bash               -1   2 /usr/local/sbin/stat
      11349  bash               -1   2 /usr/local/bin/stat
      11349  bash               -1   2 /usr/sbin/stat
      11349  bash                0   0 /usr/bin/stat
      11349  bash                0   0 /usr/bin/stat
      11349  bash                0   0 /usr/bin/stat
      11349  bash                0   0 /usr/bin/stat
      11349  bash                0   0 /usr/bin/stat
      11349  bash                0   0 /usr/bin/stat
      16893  stat               -1   2 /sys/fs/selinux
      16893  stat               -1   2 /selinux
      
  3. memleak
    • Das BCC-Programm memleak-bpfcc zeigt Memory-Leaks auf und kann benutzt werden, um Programme mit fehlerhafter Speicherverwaltung zu finden
      [12:03:09] Top 10 stacks with outstanding allocations:
              40 bytes in 5 allocations from stack
                      __kmalloc_node+0x171 [kernel]
              64 bytes in 1 allocations from stack
                      __kmalloc_track_caller+0x163 [kernel]
              64 bytes in 1 allocations from stack
                      kmem_cache_alloc_node+0x152 [kernel]
              320 bytes in 5 allocations from stack
                      kmem_cache_alloc_node_trace+0x14e [kernel]
                      __get_vm_area_node+0x7a [kernel]
              480 bytes in 5 allocations from stack
                      kmem_cache_alloc_node_trace+0x14e [kernel]
                      alloc_vmap_area+0x75 [kernel]
                      alloc_vmap_area+0x75 [kernel]
                      __get_vm_area_node+0xb0 [kernel]
                      __vmalloc_node_range+0x67 [kernel]
                      __vmalloc+0x30 [kernel]
                      bpf_prog_alloc+0x40 [kernel]
                      bpf_prog_load+0xf3 [kernel]
                      __x64_sys_bpf+0x279 [kernel]
                      do_syscall_64+0x53 [kernel]
                      entry_SYSCALL_64_after_hwframe+0x44 [kernel]
              1632 bytes in 14 allocations from stack
                      __kmalloc+0x16e [kernel]
              4840 bytes in 19 allocations from stack
                      kmem_cache_alloc+0x149 [kernel]
              14592 bytes in 30 allocations from stack
                      kmem_cache_alloc_trace+0x14c [kernel]
              21913600 bytes in 240 allocations from stack
                      __alloc_pages_nodemask+0x1e0 [kernel]
      
      
  4. mountsnoop
    • Das BCC-Programm mountsnoop-bpfcc zeigt alle Aufrufe der mount und umount Systemaufrufe (Systemcalls):
      # mountsnoop-bpfcc
      COMM             PID     TID     MNT_NS      CALL
      umount           16930   16930   4026531840  umount("/boot/efi", 0x0) = 0
      mount            16932   16932   4026531840  mount("/dev/sda15", "/boot/efi", "vfat", MS_NOSUID|MS_NOEXEC|MS_REMOUNT|MS_MANDLOCK|MS_DIRSYNC|MS_NOATIME|MS_NODIRATIME|MS_BIND|MS_MOVE|MS_REC|MS_I_VERSION|MS_NOUSER|0x7f9a00000300, "") = 0
      
  5. execsnoop
    • Das BCC- Programm execsnoop protokolliert alle neu gestarteten Prozesse des Linux-Systems:
      # execsnoop-bpfcc
      PCOMM            PID    PPID   RET ARGS
      systemd-getty-g  16948  16941    0 /usr/lib/systemd/system-generators/systemd-getty-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-gpt-aut  16949  16941    0 /usr/lib/systemd/system-generators/systemd-gpt-auto-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      cloud-init-gene  16942  16941    0 /usr/lib/systemd/system-generators/cloud-init-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-hiberna  16950  16941    0 /usr/lib/systemd/system-generators/systemd-hibernate-resume-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      lvmconfig        16951  16943    0
      systemd-detect-  16952  16942    0 /usr/bin/systemd-detect-virt --container --quiet
      systemd-system-  16955  16941    0 /usr/lib/systemd/system-generators/systemd-system-update-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-run-gen  16954  16941    0 /usr/lib/systemd/system-generators/systemd-run-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-sysv-ge  16956  16941    0 /usr/lib/systemd/system-generators/systemd-sysv-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-veritys  16957  16941    0 /usr/lib/systemd/system-generators/systemd-veritysetup-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-rc-loca  16953  16941    0 /usr/lib/systemd/system-generators/systemd-rc-local-generator /run/systemd/generator /run/systemd/generator.early /run/systemd/generator.late
      systemd-detect-  16958  16942    0 /usr/bin/systemd-detect-virt --container --quiet
      ds-identify      16959  16942    0 /usr/lib/cloud-init/ds-identify
      mkdir            16960  16942    0 /usr/bin/mkdir -p /run/systemd/generator.early/multi-user.target.wants
      ln               16961  16942    0 /usr/bin/ln -snf /lib/systemd/system/cloud-init.target /run/systemd/generator.early/multi-user.target.wants/cloud-init.target
      
  6. killsnoop
    • Das BCC-Programm killsnoop-bpfcc zeichnet alle Aufrufe des Systemaufruf kill auf:
    # killsnoop-bpfcc
    TIME      PID    COMM             SIG  TPID   RESULT
    12:46:34  16998  pkill            1    632    0
    
  7. pidpersec
    • Das BCC-Programm pidpersec-bpfcc zeichnet die Anzahl der neuen Prozesse pro Sekunde auf
      # pidpersec-bpfcc
      Tracing... Ctrl-C to end.
      12:48:11: PIDs/sec: 0
      12:48:12: PIDs/sec: 23
      12:48:13: PIDs/sec: 3
      12:48:14: PIDs/sec: 0
      

3.7.4 bpftrace

  • bpftrace ist eine kleine Programmiersprache (ähnlich wie awk), die es Administratoren ermöglicht, kleine eBPF Programme zu schreiben, welche auf eBPF Ereignisse reagieren
  • Histogram-Daten werden nach dem Beenden des Script mit CTRL+C ausgegeben
  • Unter Debian liegen die mitgelieferten bpftrace Programme unterhalb von /usr/sbin/ und haben die Dateiendung .bt (für bpftrace)
# ls /usr/sbin/*.bt
/usr/sbin/bashreadline.bt  /usr/sbin/execsnoop.bt       /usr/sbin/pidpersec.bt  /usr/sbin/tcpconnect.bt
/usr/sbin/biolatency.bt    /usr/sbin/gethostlatency.bt  /usr/sbin/runqlat.bt    /usr/sbin/tcpdrop.bt
/usr/sbin/biosnoop.bt      /usr/sbin/killsnoop.bt       /usr/sbin/runqlen.bt    /usr/sbin/tcpretrans.bt
/usr/sbin/bitesize.bt      /usr/sbin/loads.bt           /usr/sbin/statsnoop.bt  /usr/sbin/vfscount.bt
/usr/sbin/capable.bt       /usr/sbin/mdflush.bt         /usr/sbin/syncsnoop.bt  /usr/sbin/vfsstat.bt
/usr/sbin/cpuwalk.bt       /usr/sbin/oomkill.bt         /usr/sbin/syscount.bt   /usr/sbin/writeback.bt
/usr/sbin/dcsnoop.bt       /usr/sbin/opensnoop.bt       /usr/sbin/tcpaccept.bt  /usr/sbin/xfsdist.bt
  • Beispiel eines bpftrace Scriptes
# cat /usr/sbin/syscount.bt
#!/usr/bin/env bpftrace
/*
 * syscount.bt  Count system callls.
 *              For Linux, uses bpftrace, eBPF.
 *
 * This is a bpftrace version of the bcc tool of the same name.
 * The bcc versions translates syscall IDs to their names, and this version
 * currently does not. Syscall IDs can be listed by "ausyscall --dump".
 *
 * Copyright 2018 Netflix, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License")
 *
 * 13-Sep-2018  Brendan Gregg   Created this.
 */

BEGIN
{
        printf("Counting syscalls... Hit Ctrl-C to end.\n");
        // ausyscall --dump | awk 'NR > 1 { printf("\t@sysname[%d] = \"%s\";\n", $1, $2); }'
}

tracepoint:raw_syscalls:sys_enter
{
        @syscall[args->id] = count();
        @process[comm] = count();
}

END
{
        printf("\nTop 10 syscalls IDs:\n");
        print(@syscall, 10);
        clear(@syscall);

        printf("\nTop 10 processes:\n");
        print(@process, 10);
        clear(@process);
}
  1. bpftrace Beispiel-Skripte für Server-Diagnose
    • syscount.bt protokolliert Systemaufrufe
    # syscount.bt
    Attaching 3 probes...
    Counting syscalls... Hit Ctrl-C to end.
    ^C
    Top 10 syscalls IDs:
    @syscall[217]: 851
    @syscall[4]: 863
    @syscall[232]: 999
    @syscall[46]: 1532
    @syscall[9]: 2069
    @syscall[0]: 2366
    @syscall[47]: 3532
    @syscall[5]: 3573
    @syscall[3]: 4147
    @syscall[257]: 4883
    
    Top 10 processes:
    @process[systemd-fstab-g]: 439
    @process[cloud-init-gene]: 540
    @process[systemd-detect-]: 732
    @process[systemd-machine]: 1018
    @process[systemd-gpt-aut]: 1697
    @process[dbus-daemon]: 1733
    @process[systemd-logind]: 1812
    @process[systemctl]: 2268
    @process[systemd-sysv-ge]: 3532
    @process[systemd]: 12369
    
    • Liste der Linux-Syscalls ausgeben (ausyscall ist Teil des Linux Audit-Daemons, Paket auditd)
      # ausyscall --dump | awk 'NR > 1 { printf("\t@sysname[%d] = \"%s\";\n", $1, $2); }'
      
    • capable.bt überwacht Syscalls, welche die Capabilities von Linux-Prozessen ändern:
    # capable.bt
    Attaching 3 probes...
    Tracing cap_capable syscalls... Hit Ctrl-C to end.
    TIME      UID    PID    COMM             CAP  NAME                 AUDIT
    13:05:07  0      17406  ln               21   CAP_SYS_ADMIN        2                                         [145/1917]
    13:05:07  0      295    systemd-journal  21   CAP_SYS_ADMIN        0
    13:05:07  0      1      systemd          19   CAP_SYS_PTRACE       2
    13:05:07  0      1      systemd          19   CAP_SYS_PTRACE       2
    13:05:07  0      1      systemd          19   CAP_SYS_PTRACE       2
    13:05:07  0      1      systemd          19   CAP_SYS_PTRACE       2
    13:05:07  0      1      systemd          19   CAP_SYS_PTRACE       2
    13:05:07  0      1      systemd          1    CAP_DAC_OVERRIDE     0
    13:05:07  0      1      systemd          5    CAP_KILL             0
    13:05:07  0      1      systemd          1    CAP_DAC_OVERRIDE     0
    13:05:07  0      1      systemd          5    CAP_KILL             0
    13:05:07  0      17385  systemctl        21   CAP_SYS_ADMIN        2
    13:05:07  0      1      systemd          21   CAP_SYS_ADMIN        0
    13:05:07  0      1      systemd          21   CAP_SYS_ADMIN        0
    13:05:07  0      1      systemd          21   CAP_SYS_ADMIN        0
    
    • bashreadline.bt instrumentiert die von der bash benutzten readline Bibliothek und zeichnet alle in der bash (systemweit) eingegebenen Befehle auf:
    # bashreadline.bt
    Attaching 2 probes...
    Tracing bash commands... Hit Ctrl-C to end.
    TIME      PID    COMMAND
    13:07:39  11349  bash
    13:07:48  17414  su - nutzer
    13:08:06  17416  ls
    13:08:16  17416  rm -rf *
    13:08:20  17416  ls -la
    13:08:25  17416  exit
    
  2. bpftrace One-Liner
    • Systemaufrufe nach Prozessen
    bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[pid, comm] = count(); }'
    
    • execve Systemaufrufe (neue Prozesse inkl. Argumente)
    bpftrace -e 'tracepoint:syscalls:sys_enter_execve { join(args->argv); }'
    
    • Den Aufrufstapel (Execution-Stack) eines Prozesses (hier PID 189) in fünf Ebenen protokollieren
    bpftrace -e 'profile:hz:49 /pid == 189/ { @[ustack(5)] = count(); }'
    
    • Speicheranforderungen von Prozessen protokollieren (ACHTUNG: verursacht hohe Systemlast)
    bpftrace -e 'u:/lib/x86_64-linux-gnu/libc.so.6:malloc { @[ustack, comm] = sum(arg0); }'
    

3.7.5 Bücher zu eBPF/BCC

  1. Linux Observability with BPF
    • by Lorenzo Fontana, David Calavera
    • Publisher: O'Reilly Media, Inc.
    • Release Date: November 2019
    • ISBN: 9781492050209
  2. BPF Performance Tools: Linux System and Application Observability
  3. Systems Performance, 2nd Edition

3.7.6 Links

3.8 Namespaces

  • Dieses Kapitel zeigt, das Namespaces (und damit Container) eine Standard-Technologie des Linux-Kernel ist und keiner weiteren Software benötigt. systemd-nspawn und auch Docker sind nur Verwaltungsprogramme für die Namespaces und Controll-Groups des Linux-Kernels.
  • Namepspaces 'virtualisieren' die Sicht auf Ressourcen des Linux-Kernels
  • Programme wie Docker, Chrome, systemd-nspawn, LXC/LXD, Firejail etc. benutzen die Namespaces im Linux-Kernel
  • Verfügbare Namespaces in Linux
Namespace Konstante Isolation
Cgroup CLONE_NEWCGROUP Cgroup root Verzeichnis
IPC CLONE_NEWIPC System V IPC, POSIX message queues
Network CLONE_NEWNET Network devices, stacks, ports, etc.
Mount CLONE_NEWNS Mount points
PID CLONE_NEWPID Process IDs
User CLONE_NEWUSER Benutzer und Gruppen IDs
UTS CLONE_NEWUTS Hostname und NIS Domain Name

3.8.1 Namespace Beispielprogramm

apt install build-essential
  • Unser Ausgangs-C-Programm: Leeres Verzeichnis anlegen und die leere Quelltextdatei im Editor öffnen
cd /usr/src
mkdir namespaces
cd namespaces
$EDITOR namespaces.c
----
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

#define STACK_SIZE (1024 * 1024)

static char child_stack[STACK_SIZE];
char* const child_args[] = {
  "/bin/bash",
  NULL
};

int child_main(void* arg)
{
  printf("Namespace aktiv\n");
  execv(child_args[0], child_args);
  printf("Ooops\n");
  return 1;
}

int main()
{
  printf("Namespace wird erzeugt\n");
  int child_pid = clone(child_main, child_stack+STACK_SIZE, \
   CLONE_NEWUTS | CLONE_NEWIPC | SIGCHLD, NULL);
  waitpid(child_pid, NULL, 0);
  printf("Namespace beendet\n");
  return 0;
}

----
  • Programm übersetzen
gcc -o namespaces namespaces.c
  • Programm ausführen
./namespaces
  • den Namespace mit exit verlassen, dann einen Process-Namespace zum Programm hinzufügen
...
 int child_pid = clone(child_main, child_stack+STACK_SIZE, \
   CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | SIGCHLD, NULL);
...
  • neu übersetzen und ausführen
gcc -o namespaces namespaces.c
  • Einen Netzwerk-Namespace hinzufügen
...
  int child_pid = clone(child_main, child_stack+STACK_SIZE, \
   CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID |  CLONE_NEWNET | SIGCHLD, NULL);
...

3.9 Netzwerk Namespaces per ip Kommando

  • Netzwerk Namespace netns1 erzeugen
# ip netns add netns1
# ip netns list
  • Befehl im Netzwerk-Namespace ausführen
# ip netns exec netns1 ip link list
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  • Loopback ist "down", ein ping geht nicht
# ip netns exec netns1 ping 127.0.0.1
connect: Network is unreachable
  • Nun bringen wir das Loopback-Interface "up"
# ip netns exec netns1 ip link set dev lo up
# ip netns exec netns1 ping 127.0.0.1
  • Wir erstellen nun virtuelle Netzwerkschnittstellen
# ip link add veth0 type veth peer name veth1
# ip link
  • Netzwerkschnittstelle veth1 wird in den Netzwerk-Namespace netns1 verschoben
# ip link set veth1 netns netns1  # auch physische NICs koennen in Namespaces verschoben werden
# ip link
  • Wir konfigurieren ein IP-Adresse auf veth1 im Namespace
# ip netns exec netns1 ifconfig veth1 10.1.1.1/24 up
# ip netns exec netns1 ip a
# ping 10.1.1.1  # ping in den Namespace geht jetzt noch nicht!
  • Eine IP-Adresse auf dem veth0 auf dem Linux-Host konfigurieren
ifconfig veth0 10.1.1.2/24 up
  • Ping von aussen in den Namespace geht jetzt!
# ping 10.1.1.1
  • Ping aus den Namespace nach draussen sollte auch gehen
ip netns exec netns1 ping 10.1.1.2
  • der Namespace hat eine eigene Routing-Tabelle und eine eigene Netfilter-Firewall
ip netns exec netns1 route
ip netns exec netns1 ip route show
ip netns exec netns1 iptables -L
  • Namespace wieder löschen
ip netns delete netns1

3.10 Einfache Container mit unshare

  • mit dem Programm unshare können die einzelnen Namespaces separat erstellt und eingeschaltet werden. Wird kein zu startendes Programm angegeben, so wird die Standard-Shell des Systems mit den neuen Namespaces gestartet. Beispiel: ein Namespace mit privatem Netzwerk, Mount- und Prozess-ID- Namespace:
    # unshare -n -p -f --mount-proc
    
  • Container mit Benutzer root, welcher nicht root auf dem Host ist
    sudo unshare --map-root-user --user sh
    

3.11 Namespaces auflisten

  • Befehl lsns:
[root@centos-sec-oct-2017 ~]# lsns
        NS TYPE  NPROCS   PID USER   COMMAND
4026531836 pid       81     1 root   /usr/lib/systemd/systemd --system --deserialize 22
4026531837 user      81     1 root   /usr/lib/systemd/systemd --system --deserialize 22
4026531838 uts       81     1 root   /usr/lib/systemd/systemd --system --deserialize 22
4026531839 ipc       81     1 root   /usr/lib/systemd/systemd --system --deserialize 22
4026531840 mnt       78     1 root   /usr/lib/systemd/systemd --system --deserialize 22
4026531856 mnt        1    12 root   kdevtmpfs
4026531956 net       81     1 root   /usr/lib/systemd/systemd --system --deserialize 22
4026532212 mnt        1 11299 root   /usr/lib/systemd/systemd-udevd
4026532227 mnt        1   551 chrony /usr/sbin/chronyd

3.12 Container/Namespace mit Systemd

  • Ab Debian 9 müssen die Systemd-Container-Tools extra installiert werden:
apt install systemd-container
  • wir erstellen ein Verzeichnis für den neuen Container
mkdir -p /srv/container/centos7
  • initialisieren eine neue RPM-Instanz im Container-Verzeichnis (bei Debian mit debboostrap, bei SUSE mit RPM und zypper)
apt -y install rpm yum
rpm --root /srv/container/centos7 --initdb
  • Das Basis-Paket für CentOS 7 laden
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/centos-release-7-9.2009.0.el7.centos.x86_64.rpm
rpm --nodeps --root /srv/container/centos7 -ivh  centos-release-7-9.2009.0.el7.centos.x86_64.rpm
  • das CentOS Basis-System installieren
yum -y --nogpg --releasever=7 --installroot=/srv/container/centos7 \
  install systemd passwd yum procps-ng iproute tmux
echo 7 > /srv/container/centos7/etc/yum/vars/releasever
  • eine Shell im Container starten
systemd-nspawn -D  /srv/container/centos7
  • Root-Passwort setzen und neuen Benutzer anlegen
-bash-4.2$ passwd
-bash-4.2$ adduser nutzerXX
-bash-4.2$ passwd nutzerXX
  • Shell im Container verlassen
-bash-4.2# exit
  • Container booten
systemd-nspawn -bD  /srv/container/centos7
  • Container stoppen (im Container eingeben)
conainter# poweroff
  • Container mit privatem Netzwerk-Namespace:
systemd-nspawn -bD  /srv/container/centos7 --private-network

Container mit eigener (virtuellen) Netzwerkkarte (neue MAC-Adresse)

systemd-nspawn --network-macvlan=enp1s0f1 -M centos01 \
  -bD /srv/container/centos7
container# ip links
container# dhclient mv-enp1s0f1
container# ip address show
container# ping 1.1.1.1
  • Container vom Host kontrollieren
machinectl list
machinectl status centos
machinectl terminate centos
machinectl kill centos
  • per nsenter mit dem Container verbinden (es wird eine Prozess-ID eines Container-Prozesses benötigt!)
nsenter -m -u -i -n -p -t <pid-im-container> /bin/bash

3.13 Firejail

  • Firejail ist eine leichtgewichtige Sandbox für Linux-Programme auf Basis von Linux-Namespaces, secomp-bpf und der Linux-Firewall
    • Firejail wurde ursprünglich für die Absicherung des Firefox-Browsers erstellt, kann nun aber für die Absicherung vieler andere Programme benutzt werden
    • Der Fokus von Firejail liegt auf Desktop-Linux-Programmen, jedoch kann Firejail auf auch Linux-Servern eingesetzt werden
  • Homepage https://firejail.wordpress.com/
  • Quellcode https://github.com/netblue30/firejail
  • Moderne Versionen von Firejail unterstützen DNS-over-HTTPS und DNS-over-TLS mit dem FDNS Projekt https://firejaildns.wordpress.com/
  • Firejail installieren
apt install firejail firejail-profiles
  • Den Konsolen-Webbrowser links installieren (als Beispielprogramm)
# apt install links
  • Einen unprivilegierten Benutzer (z.B. nutzer) in der Datei /etc/firejail/firejail.users eintragen, um die Benutzung von firejail durch diesen Benutzer zu erlauben
  • Benutzer zu dem unprivilegierten Benutzer wechseln
# su - nutzer
  • Für den Benutzer das Verzeichnis .ssh (SSH Schlüssel und Konfiguration) erstellen. Firejail sichert dieses Verzeichnis gesondert ab, so das Programme ohne spezielle Firejail-Rechte (wie das ssh Programm) auf die Inhalte dieses Verzeichnisses nicht zugreifen können
$ cd ~
$ mkdir .ssh
$ chmod 600 .ssh
  • Test von Firejail: wir starten eine Bash-Shell kontrolliert von Firejail
# firejail bash
  • Teste die folgenden Aktionen in der Firejail-Bash:
    • Prozessliste auflisten
    • Programm top starten
    • Zeige die Datei .bash_history an
    • Wechsle in das Verzeichnis .ssh
    • Liste alle Dateien im Heimverzeichnis mit ls -la. Was fällt auf?
  • Firejail bash verlassen
  • Der Kommandozeilen-Browser links wird von den Firejail-Profilen von Debian 10 noch nicht abgesichert (in den Github-Quellen des Projektes finden sich neuere Profile)
    • Wir werden der Debian 10 Firejail Konfiguration die notwendigen Profil-Dateien hinzufügen, um links abzusichern
    • Das globale Firejail Profil für den Konsolen-Webbrowser links in der Datei /etc/firejail/links speichern
      # Firejail profile for links
      # Description: Text WWW browser
      # This file is overwritten after every install/update
      quiet
      # Persistent local customizations
      include links.local
      # Persistent global definitions
      include globals.local
      
      noblacklist ${HOME}/.links
      
      mkdir ${HOME}/.links
      whitelist ${HOME}/.links
      
      private-bin links
      
      # Redirect
      include links-common.profile
      
    • Profil-Regeln für alle links Varianten (links2, elinks) in der Datei /etc/firejail/links-common.profile anlegen:
      # This file is overwritten during software install.
      # Persistent customizations should go in a .local file.
      include links-common.local
      
      # common profile for links browsers
      
      blacklist /tmp/.X11-unix
      blacklist ${RUNUSER}/wayland-*
      
      include disable-common.inc
      include disable-devel.inc
      include disable-exec.inc
      include disable-interpreters.inc
      # Additional noblacklist files/directories (blacklisted in disable-programs.inc)
      # used as associated programs can be added in your links-common.local.
      include disable-programs.inc
      include disable-xdg.inc
      
      whitelist ${DOWNLOADS}
      include whitelist-runuser-common.inc
      include whitelist-usr-share-common.inc
      include whitelist-var-common.inc
      
      caps.drop all
      ipc-namespace
      # Add 'ignore machine-id' to your links-common.local if you want to restrict access to
      # the user-configured associated media player.
      machine-id
      netfilter
      # Add 'ignore no3d' to your links-common.local if you want to restrict access to
      # the user-configured associated media player.
      no3d
      nodvd
      nogroups
      #noinput
      nonewprivs
      noroot
      # Add 'ignore nosound' to your links-common.local if you want to restrict access to
      # the user-configured associated media player.
      nosound
      notv
      nou2f
      novideo
      protocol unix,inet,inet6
      seccomp
      shell none
      tracelog
      
      disable-mnt
      # Add  'private-bin PROGRAM1,PROGRAM2' to your links-common.local  if you want to use user-configured programs.
      private-bin sh
      private-cache
      private-dev
      private-etc alternatives,ca-certificates,crypto-policies,nsswitch.conf,pki,resolv.conf,ssl
      # Add the next line to your links-common.local to allow external media players.
      # private-etc alsa,asound.conf,machine-id,openal,pulse
      private-tmp
      
      #dbus-user none
      #dbus-system none
      
      memory-deny-write-execute
      
    • Datei /etc/firejail/disable-exec.inc
      # This file is overwritten during software install.
      # Persistent customizations should go in a .local file.
      include disable-exec.local
      
      noexec ${HOME}
      noexec ${RUNUSER}
      noexec /dev/mqueue
      noexec /dev/shm
      noexec /tmp
      # /var is noexec by default for unprivileged users
      # except there is a writable-var option, so just in case:
      noexec /var
      
    • In der Datei /etc/firejail/whitelist-runuser-common.inc Zugriff auf üblicherweise von Benutzer-Programmen benutzte Verzeichnisse erlauben
      # This file is overwritten during software install.
      # Persistent customizations should go in a .local file.
      include whitelist-runuser-common.local
      
      # common ${RUNUSER} (=/run/user/$UID) whitelist for all profiles
      
      whitelist ${RUNUSER}/bus
      whitelist ${RUNUSER}/dconf
      whitelist ${RUNUSER}/gdm/Xauthority
      whitelist ${RUNUSER}/ICEauthority
      whitelist ${RUNUSER}/.mutter-Xwaylandauth.*
      whitelist ${RUNUSER}/pulse/native
      whitelist ${RUNUSER}/wayland-0
      whitelist ${RUNUSER}/wayland-1
      whitelist ${RUNUSER}/xauth_*
      whitelist ${RUNUSER}/[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]-[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]-[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]-[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]-[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]
      
    • In der Datei /etc/firejail/whitelist-usr-share-common.inc Zugriff auf Dateien und Verzeichnisse unterhalb von /usr/share erlauben
      # This file is overwritten during software install.
      # Persistent customizations should go in a .local file.
      include whitelist-usr-share-common.local
      
      # common /usr/share whitelist for all profiles
      
      whitelist /usr/share/alsa
      whitelist /usr/share/applications
      whitelist /usr/share/ca-certificates
      whitelist /usr/share/crypto-policies
      whitelist /usr/share/cursors
      whitelist /usr/share/dconf
      whitelist /usr/share/distro-info
      whitelist /usr/share/drirc.d
      whitelist /usr/share/enchant
      whitelist /usr/share/enchant-2
      whitelist /usr/share/file
      whitelist /usr/share/fontconfig
      whitelist /usr/share/fonts
      whitelist /usr/share/fonts-config
      whitelist /usr/share/gir-1.0
      whitelist /usr/share/gjs-1.0
      whitelist /usr/share/glib-2.0
      whitelist /usr/share/glvnd
      whitelist /usr/share/gtk-2.0
      whitelist /usr/share/gtk-3.0
      whitelist /usr/share/gtk-engines
      whitelist /usr/share/gtksourceview-3.0
      whitelist /usr/share/gtksourceview-4
      whitelist /usr/share/hunspell
      whitelist /usr/share/hwdata
      whitelist /usr/share/icons
      whitelist /usr/share/icu
      whitelist /usr/share/knotifications5
      whitelist /usr/share/kservices5
      whitelist /usr/share/Kvantum
      whitelist /usr/share/kxmlgui5
      whitelist /usr/share/libdrm
      whitelist /usr/share/libthai
      whitelist /usr/share/locale
      whitelist /usr/share/mime
      whitelist /usr/share/misc
      whitelist /usr/share/Modules
      whitelist /usr/share/myspell
      whitelist /usr/share/p11-kit
      whitelist /usr/share/perl
      whitelist /usr/share/perl5
      whitelist /usr/share/pixmaps
      whitelist /usr/share/pki
      whitelist /usr/share/plasma
      whitelist /usr/share/publicsuffix
      whitelist /usr/share/qt
      whitelist /usr/share/qt4
      whitelist /usr/share/qt5
      whitelist /usr/share/qt5ct
      whitelist /usr/share/sounds
      whitelist /usr/share/tcl8.6
      whitelist /usr/share/tcltk
      whitelist /usr/share/terminfo
      whitelist /usr/share/texlive
      whitelist /usr/share/texmf
      whitelist /usr/share/themes
      whitelist /usr/share/thumbnail.so
      whitelist /usr/share/uim
      whitelist /usr/share/vulkan
      whitelist /usr/share/X11
      whitelist /usr/share/xml
      whitelist /usr/share/zenity
      whitelist /usr/share/zoneinfo
      
    • Den Browser links im Jail starten (als unprivilegierter Benutzer)
      # su - nutzer
      $ firejail links https://notes.defaultroutes.de
      
    • Auf der Webseite des Trainings die PDF-Datei LinuxSecurityEinfuehrung.pdf finden, auswählen und per Taste d (Download) sichern, danach den Browser links mit der Taste q verlassen
      • Wo ist die Datei gespeichert worden?
  • Erstelle im Heimverzeichnis des Benutzers ein Verzeichnis mit den Namen Downloads
    $ mkdir ~/Downloads
    
  • Starte links nochmals, lade das PDF von der Trainings-Webseite und speichere es in Verzeichnis Dowloads. Nach dem Beenden des Browsers ist die Datei dort zu finden
  • Starte den Browser mit einer Datei-System-URL des Heimverzeichnisses links file://. mit und ohne FireJail. Welche Unterschiede gibt es?
  • Erstelle (als Benutzer root) einen symbolischen Link von /usr/bin/firejail zu /usr/local/bin/links
    • Wird Firejail über einen solchen Symlink aufgerufen, so startet es das Programm mit dem Namen unter der Kontrolle von Firejail. Der Benutzer kann daher das Programm "direkt" aufrufen, ohne den Befehl firejail voranstellen zu müssen
      $ ln -s /usr/bin/firejail /usr/local/bin/links
      
  • Firejail kann automatisiert für unterstützte Programme solche Wrapper-Links installieren. Die Wrapper-Links überlagern die Programm-Namen von schützenswerten Linux-Anwendungen.
$ sudo firecfg
  • Firejail Programme überwachen (in einem separaten Terminal starten und dann z.B. links starten)
firejail --top
  • Im System verfügbare Firejail Profile auflisten
ls /etc/firejail

4 Tag 4

4.1 Docker

  • Podman ist eine "drop-in" (Kommandozeilen-Kompatible) Alternative zu Docker (Podman wird von RedHat als Open Source Projekt vorangetrieben). Die weiteren Ausführungen in diesen Kapitel gelten bis auf wenige Ausnahmen auch für Podman.

4.1.1 Docker als Sicherheits-Werkzeug

  • Docker bietet gegenüber dem Betrieb von klassischen Linux-Installationen (auf „bare Metal“ oder virtualisiert) einige Vorteile:
    • Anwendungen werden voneinander isoliert. Selbst die Bestandteile einer Anwendung (z.B. LAMP - Linux/Apache/MySQL/PHP) können in eigene Docker-Container ausgelagert und voneinander isoliert werden.
    • die Rechte einer Anwendung im Docker-Conatiner kann per Seccomp-bpf und Linux-Capabilities beschränkt werden
    • die Sicht auf den Netzwerkstack kann für Anwendungen eingeschränkt werden (Admin-Netzwerk für Anwendungen nicht sichtbar)
    • Docker unterstützt ein Implementations-Design, bei dem Anwendungs-Programme und Daten getrennt gehalten werden (Anwendungen in Container-Images, Daten in Speicher-Volumes ausserhalb der Container)
    • Über Dockerfiles sind die Container jederzeit reproduzierbar. Bei einem Einbruch in einen Docker-Container kann dieser zu Beweiszwecken eingefroren werden und durch ein neues, sauberes Container-Image ersetzt werden
    • Docker-Container werden nicht per Software-Update aktualisiert, sondern durch ein neues Container-Image mit aktueller Software ersetzt. Hierdurch kann sich ein (auch bisher unbemerkter) Einbrecher nicht im System festsetzen
  • Nachteile:
    • die Isolierung von Anwendungen durch Linux-Container-Virtualisierung ist nicht so stark und vollständig wie bei einer Voll-Virtualisierung (VMWare, HyperV, VirtualBox). Linux-Container können jedoch innerhalb einer Voll-Virtualisierung eingesetzt werden und somit werden die Vorteile beider Systeme genutzt
    • Anwendungs-Installationen müssen angepasst werden, um Programme und Daten sauber zu trennen
    • Docker erhöht die Komplexität der Installation
    • Docker-Verwaltungswerkzeuge (Kubernetes etc) erhöhen die Komplexität und haben ggf. eigene Sicherheitsprobleme

4.1.2 Docker Installieren

  • Docker installieren und starten
apt install docker.io
  • Docker testen
docker run hello-world

4.1.3 erste Schritte mit Docker

  • Docker Image herunterladen
# docker pull centos
# docker images
  • Ein Centos mit Bash starten
# docker run --name=application1 -it centos /bin/bash
docker# yum update -y
docker# yum install -y procps httpd
docker# yum clean all
docker# exit
# docker ps -a
  • mit laufendem Docker Container verbinden
docker attach application1
  • Docker Container Statistiken anzeigen
# docker top <container>
# docker stats <container1> <container2> ...
  • einen weiteren Prozess im Docker Container ausfuehren
# docker exec -d <container> touch /etc/new-config
# docker exec -t -i <container> /bin/sh
  • Docker Container stoppen
# docker stop application1
  • Docker bei Applikations-Ende automatisch neu starten
docker run --restart=always
docker run --restart=on-failure:5
docker inspect <container>
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container>
  • Docker Container im Hintergrund (-d) starten
docker run --name <name> -d <image> <command>
  • Ausgaben der Anwendung im Docker Container anschauen
docker logs <container>
docker logs -f <container>
docker logs --tail -f <container>
docker logs --tail 50 <container>
  • Docker Log-Ausgaben können mittels eigener log drivers auf andere Ziele umgelenkt werden(json-file, syslog, none, …)
docker run --log-driver="syslog" ...
  • Ein Docker Image aus einem Dockerfile (Docker-Image Bauanleitung) erstellen
mkdir -p docker-work
cd docker-work
$EDITOR Dockerfile
-----
# Debian with nginx
# Version 1
FROM debian:latest

MAINTAINER Linuxhotel Trainer

# Update image
RUN apt update
# Add httpd package. procps and iproute are only added to investigate the image later.
RUN apt -y install nginx
RUN echo container.example.com > /etc/hostname

# Create an index.html file
RUN bash -c 'echo "Your Web server test on Debian Docker Container is successful." >> /var/www/html/index.html'
# create a nginx start-command
CMD ["nginx", "-g", "daemon off;"]
------
docker build -t debian-nginx --no-cache .
docker run -d -t --name=deb-nginx1 -p 8080:80 debian-nginx

4.1.4 Docker Container verbinden

  • Volumes
docker run -v <local-dir>:<container-dir>[:ro] ...
  • Volumes im Dockerfile definieren. Hierdurch werden Volumes beim Erstellen des Containers ausserhalb des Containers erstellt (unter /var/lib/docker/... auf dem Linux-Host) und in den Container eingebunden
# Dockerfile
[...]
VOLUME /data
VOLUME /var/www/html

4.1.5 Docker Übung: Caddy-Webserver:

  • installiere ein Image mit dem 'Caddy' Webserver (https://caddyserver.com) aus der Docker Hub Registry (abiosoft/caddy). Caddy ist ein in der Sprache go geschriebener Webserver, welcher automatisch TLS/x509 Zertifikate von Let's Encrypt besorgt und aktualisiert.
    • starte einen Container aus dem Image, mappe Port 2015 vom Container auf einen freien Port auf dem Host
    • teste die Caddy-Webseite mit dem Firefox auf dem Laptop http://<ip-der-VM>:<port>
    • starte eine Shell im Caddy-Webserver Container per docker exec. Suche das Verzeichnis mit den HTML-Dateien.
    • stoppe den Container, lösche den Container (docker rm)
    • erstelle ein leeres Verzeichnis auf dem Container-Host (Laptop) unter /srv/websites/html. Erstelle eine einfache HTML-Datei index.html in diesem Verzeichnis.
    • starte einen neuen Container, verbinde das Verzeichnis /srv/websites/html vom Container-Host in den Container (Parameter -v, siehe oben).
    • Teste den Webserver mit dem Firefox Browser
    • Ändere die Datei index.html unter /srv/websites/html, teste das die Änderungen im Browser sichtbar sind
    • erstelle einen neuen NGINX Container (auf Basis des NGINX Dockerfiles oben in der Anleitung), bei dem das Verzeichnis /srv/websites/html in den Webroot des NGINX-Webservers gemappt wird (Achtung: anderen Port als für den Caddy-Webserver benutzen. Beide Webserver-Container sollten zur gleichen Zeit aktiv sind)
    • Einige Befehle zum Probieren (als Benutzer root auf dem Host)
docker logs <container>   # Anzeige der Logausgaben des Hauptprozesses
docker top <container>    # Anzeige der Prozesse im Container
docker stats <container>  # Anzeige der vom Container benutzten Resourcen
  1. Beispiellösung
    • Caddy-Webserver Image aus dem Docker Repository
    docker run --name=caddyweb -d -p 8088:2015 abiosoft/caddy
    
    • Im Docker-Container nach den HTML-Dateien suchen
    docker exec caddyweb find / -name index.html
    
    • Caddy Container stoppen und löschen
    docker stop caddyweb
    docker rm caddyweb
    
    • Verzeichnis für die Webseiten anlegen und eine index.html Datei erstellen
    mkdir -p /srv/websites/html
    echo "Dies ist meine Webseite" > /srv/websites/html/index.html
    
    • Caddy Container mit dem externen Webseiten-Verzeichnis starten
    docker run --name=caddyweb -v /srv/websites/html:/srv -d -p 8088:2015 abiosoft/caddy
    
    • (wenn notwendig) vorherigen NGINX Container stoppen und löschen
    docker stop debian-nginx
    docker rm debian-nginx
    
    • NGINX Container mit dem Web-Verzeichnis starten
    docker run --name=debian-nginx -v /srv/websites/html:/var/www/html -p 8080:80 debian-nginx
    

4.2 Docker Sicherheit

4.2.1 Docker Images

4.2.2 Container Sicherheit

  • keine SUID Programme im Container
  • keinen "echten" Benutzer "root" (UID0) im Container (Capabilities benutzen)
  • Anwendungen im Container nicht unter einem Root-Account betreiben
  • Capabilities sparsam einsetzen (kein CAP_SYS_ADMIN)
  • Dateien in /tmp sind keine Daten, nicht von extern mounten
  • Programme (im Container) und Daten (ausserhalb des Containers) trennen
  • sensitive Programme read-only in den Container mappen/mounten
  • Container auf bekannte Sicherheitslücken der im Container benutzen Software überwachen
  • Container oft und regelmässig auffrischen

4.2.3 Audit-Regeln fuer Docker einrichten

  • Beispiel-Regelwerk (generisch, muss ggf. für die eigene Repository angepasst werden)
 -w /etc/docker -k docker
-w /etc/docker/key.json -k docker
-w /etc/docker/daemon.json -k docker
-w /etc/docker/certs.d -k docker
-w /etc/sysconfig/docker -k docker
-w /etc/sysconfig/docker-network -k docker
-w /etc/sysconfig/docker-storage -k docker
-w /etc/sysconfig/docker-storage-setup -k docker
-w /usr/lib/systemd/system/docker.service -k docker
-w /usr/bin/docker-containerd -k docker
-w /usr/bin/docker-containerd-current -k docker
-w /usr/bin/docker-containerd-shim -k docker
-w /usr/bin/docker-containerd-shim-current -k docker
-w /usr/bin/docker -k docker
-w /usr/bin/docker-current -k docker
-w /usr/bin/docker-ctr-current -k docker
-w /usr/bin/dockerd -k docker
-w /usr/bin/dockerd-current -k docker
-w /usr/bin/container-storage-setup -k docker
-w /var/lib/docker -k docker
-w /var/run/docker.sock -k docker

4.2.4 Docker-Engine nicht auf einem (ungeschützten) TCP Port betreiben

4.2.5 Docker Repository mit TLS absichern (x509 Zertifikate benötigt)

  • in der Datei /etc/sysconfig/docker
dockerd --tlsverify ...

4.2.6 User-Namespaces verwenden

  • in der Datei /etc/sysconfig/docker
dockerd --userns-remap=default ...

4.2.7 Legacy-Registry abschalten

  • in der Datei /etc/sysconfig/docker
dockerd --disable-legacy-registry ...

4.2.8 Ulimits auf Container setzen

  • in der Datei /etc/sysconfig/docker, Format --default-ulimit <ulimit-spec>=<soft-limit>:<hard-limit>
  • Information ueber ULIMIT Schluesselwoerter in /etc/security/limits.conf
  • Default-Ulimit setzen
dockerd --default-ulimit nofile=50:150 --default-ulimit nproc=10:20
  • Ulimit fuer einzelnen Container
docker run --ulimit nofile=20:50 ...

4.2.9 Docker Container nicht als Benutzer root betreiben

docker run -u dockeruser -d ...

4.2.10 Capabilities von Container-Prozessen beschraenken

  • Docker Container mit beschraenkten Capabilities starten
docker run --cap-drop=all --cap-add [notwendige capabilities] ...
  • Capabilities eines Prozesses in einem Docker Container herausfinden am Beispiel des nginx Webservers
 # Prozess-ID des nginx Prozesses herausfinden
docker exec $(docker ps -q) pgrep -a nginx
# Capabilities der Prozess-ID 1 (nginx) abfragen
docker exec $(docker ps -q) cat /proc/1/status | grep CapEff | awk '{print $NF}'
00000000a80425fb
# Capabilties dekodieren und Docker-Parameter ausgeben
capsh --decode=00000000a80425fb | echo "--cap-drop=all --cap-add={$(sed -e 's/.*=//' -e 's/cap_//g')}"
--cap-drop=all --cap-add={chown,dac_override,fowner,fsetid,kill,setgid,setuid,setpcap,net_bind_service,net_raw,sys_chroot,mknod,audit_write,setfcap}
  • Die Capabilities unter –cap-add pruefen und ggf. einschraenken

4.2.11 /etc/localtime im Container Read-only

  • die Datei /etc/localtime im Container Read-Only setzen, verhindert, das die Zeitzone im Container veraendert wird
docker run -v /etc/localtime:/etc/localtime:ro

4.2.12 Speicher- und CPU-Resources des Containers einschraenken

Docker Parameter Beschreibung
–cpu-period Laenge der CPU CFS (Completely Fair Scheduler) Zeitscheibe
–cpu-quota CPU CFS (Completely Fair Scheduler) quota
–cpuset-cpus Container an CPUs binden (0-3, 0,1).
–cpuset-mems Container an Speicher-Nodes binden (0-3, 0,1) nur fuer NUMA Maschinen
–kernel-memory Kernel Speicher-Limit
-m, –memory Speicher Limit
–memory-reservation Limit fuer Speicherreservierungen (Virtueller noch nicht benutzer Speicher)
–memory-swap Vollstaendiges Speicherlimit (memory + swap), '-1' schaltet virtuellen Speicher (SWAP) aus

4.2.13 Dateisysteme "nur-lesbar" einbinden

  • Das Root-Dateisystem im Container „nur-lesend“ einbinden
docker run --read-only ...
  • Container Volume nur-lesend einbinden
docker run -v /volume:ro ...
  • Pfade des Hosts nur-lesend in den Container einbinden
docker run -v /srv/container/name:/srv:ro ...

4.2.14 Fähigkeiten eines Docker Containers per SELinux einschränken

Für Linux-Sicherheits-Module (LSM) auf Label Basis (Role Based Access Control, RBAC) kann der Benutzer, die Rolle, der Tyoe und der Level für einen Container festgelegt werden. LSM funktionieren nicht innerhalb von Containers, sondern nur für einen gesamten Container.

docker run --security-opt=[label=user:USER]

4.2.15 Fähigkeiten eines Docker Containers per AppArmor einschränken

4.2.16 Syscalls einschränken mit Seccomp

4.2.17 Vorsicht bei dem Einsatz von KSM (Kernel-Same-Pages-Merging)

# systemctl status ksm
● ksm.service - Kernel Samepage Merging
   Loaded: loaded (/usr/lib/systemd/system/ksm.service; enabled; vendor preset: enabled)
   Active: active (exited) since Mi 2017-10-25 19:20:35 CEST; 13h ago
  Process: 777 ExecStart=/usr/libexec/ksmctl start (code=exited, status=0/SUCCESS)
 Main PID: 777 (code=exited, status=0/SUCCESS)
    Tasks: 0
   Memory: 0B
   CGroup: /system.slice/ksm.service

Okt 25 19:20:35 notebook51 systemd[1]: Starting Kernel Samepage Merging...
Okt 25 19:20:35 notebook51 systemd[1]: Started Kernel Samepage Merging.
# /usr/libexec/ksmctl stop
# echo 0 > /sys/kernel/mm/ksm/run
# systemctl disable ksm
# systemctl disable ksmtuned
# echo 2 > /sys/kernel/mm/ksm/run

4.3 weitere Container-Tools

4.3.1 Das mbox Programm

  • das mbox Programm bietet eine einfache, simple sandbox mittels CGroups und Namespaces. mbox kann benutzt werden um die Ausführung von unbekannten Programmen (Scripts, Binärprogramme) einzuschränken und zu überwachen https://github.com/tsgates/mbox

4.4 Incidence Response

4.4.1 Vorbereitungen auf den Notfall

  • Forensik Live-Linux-CD-ROM bereithalten und regelmässig üben (1/2 jährlich)
  • Kontaktadressen von Forensikern/Strafverfolgungsbehörden bereithalten
  • das Erstellen von Platten-Images üben
  • PGP/GPG Schlüssel erstellen und aktuell halten. PGP/GPG-E-Mail regelmässig benutzen, um in Übung zu bleiben
  • Ersatz-Hardware vorhalten (Festplatten, SSD), Speicherplatz für Platten-Images
  • Beutel für manipulationssichere Beweissicherung bestellen und "vor Ort" bereithalten
  • Hardware-RAID meiden (Alternativen: Software RAID - DM-RAID, btrfs, zfs)
  • alternative Kommunikationswege (Twitter, externes E-Mail-System, externer Web-Server) vorbereiten. Kunden über diese alternativen Kommunikationswege informieren!
  • Minimale-Installationen benutzen
  • Datensparsamkeit - nur Daten, die nicht gespeichert werden, können nicht mißbraucht werden -> Datenhaltung kostet
  • Incident-Modus für die IT-Systeme definieren –> welche Teile der IT können im Fall eines Angriffs ohne starke Auswirkungen auf den Firmenbetrieb ausgeschaltet oder abgeschottet werden
  • Incident-Modus automatisiert per Configuration-Management System anschalten –> Testen

4.4.2 Kunden/Benutzer im Falle eines Sicherheitsvorfalls informieren

  • wenn die eigene Kommunikationsstruktur (z.B. E-Mail) betroffen ist, die alterntaiven Kommunikationswege benutzen
  • dokumentierte Notfall-Prozedur zur Kunden-Kommunikation vorhalten und verteilen
  • bei erkannten Angriffen 4 Augen-Prinzip beachten, nicht alleine arbeiten!

4.4.3 Spurensicherung

  • VM Snapshots erstellen (per GPG signieren)
  • von einem Forensik-Linux booten (Kali-Linux, Deft o.ä.)
  • revisionssichere Images (dcfldd, aff4) erstellen http://www.osforensics.com/tools/create-disk-images.html
    apt install dcfldd
    dcfldd if=/dev/sda1 hash=sha256 hashwindow=100M sha256log=sha256.txt \
      hashconv=after bs=512 conv=noerror,sync split=100M splitformat=aa of=sda1.dd
    
  • Images sofort nach der Erstellung per GPG signieren (mit externer Signaturdatei)
  • erst Platten-Images erstellen, dann Log-Dateien etc. anschauen
  • Festplatten ausbauen und durch fabrikneue Platten ersetzen, Festplatten mit kompromittiertem System versiegeln (lassen)
  • Analyse des Einbruches auf den Read-Only-Dateisystem-Images (nicht auf den echten Platten, die echten Platten sind ein Beweismittel und dürfen nach der Versiegelung nicht angefasst werden)

4.4.4 Backup/Rebuild eines kompromitierten Systems

  • Server komplett neu aufsetzen (Docker dockerfile, Foreman/Ansible/Salt etc, VM Templates)
  • Festplatte(n) austauschen
  • nur Daten ohne ausführbare Teile (Maschinencode, Java, .NET, Python pyc, PHP, Scripte etc) zurückspielen
    • bei der Einrichtung der Server schon auf eine Trennung von System, Anwendungen und Daten achten!
  • Scripte neu erstellen, von einem bekannt sauberen Backup zurückspielen oder einzeln per Pair-Review (2 Personen Review) prüfen

4.5 Rootkits aufspüren

  • Root-Kit-Hunter installieren
apt install rkhunter
  • WEB_CMD in der Datei /etc/rkhunter.conf setzen
WEB_CMD=/usr/bin/curl
  • MIRROR_MODE in der Datei /etc/rkhunter.conf auf "0" setzen
MIRROR_MODE=0
  • Root-Kit Tests aktualisieren
rkhunter --update
  • RKHunter Baseline Datenbank erstellen
rkhunter --propupd
  • nach Root-Kits suchen
rkhunter --check
less /var/log/rkhunter.log

4.6 Intrusion Detection

4.6.1 rhash

  • rhash Installation
apt install rhash
  • Datenbank mit den Hash-Werten erstellen (Hash=SHA3/Keccak mit 224 bit, Datenbankformat wie bei BSD)
rhash -r --sha3-224 --bsd /etc -o hash.lst
  • Datenbank anschauen
less hash.lst
  • Datenbank sichern (in Produktionsumgebung)
scp hash.lst benutzer@sicherer-server.example.com
  • Dateien gegen die Datenbank prüfen
rhash -r -c --bsd hash.lst
  • Die Benutzer-Authentisierungsdateien durch Anlegen eines neuen Benutzers ändern
adduser intruder
  • nochmal Dateien gegen die Datenbank prüfen
rhash -r -c --bsd hash.lst
  • Nur die "nicht-OK" Dateien anzeigen
rhash --skip-ok -r -c --bsd hash.lst

4.6.2 AIDE

  • Installation
apt install aide aide-common
  • Konfiguration anschauen und ggf. ändern
$EDITOR /etc/aide/aide.conf
update-aide.conf
less /var/lib/aide/aide.conf.autogenerated
  • AIDE Datenbank erstellen (Dauer ca. 3-6 Minuten auf den Linuxhotel Laptops)
aideinit
  • Ausgabe von aideinit
Start timestamp: 2019-11-13 07:58:08 +0100 (AIDE 0.16.1)
AIDE initialized database at /var/lib/aide/aide.db.new
Verbose level: 6

Number of entries:      178250

---------------------------------------------------
The attributes of the (uncompressed) database(s):
---------------------------------------------------

/var/lib/aide/aide.db.new
  RMD160   : w/xQIwY8je09TrZAMFOFN2JqAY4=
  TIGER    : MRqyf0hq+8N+Kv/wILF7v0X3HEFcvhdv
  SHA256   : 8Jvgtqq0amatTf+Tj0o42W2HYne6Jf2g
             i5PClJmWv04=
  SHA512   : OWGC4zRYKyBTEg9fBBDgUCLVDoERZjve
             GI5EdEPCoGXwRnTR6tBP67tAa9tj7llh
             bd2O2CbTZ08pVI9AQ22Q2g==
  CRC32    : B9czIg==
  HAVAL    : 9GLjw3cDS/k2qpnZhoiZHmKYoSMZ1I3h
             mL2pUnyMoCQ=
  GOST     : mfBemqOHFSzWHf49h33R7gysjoLA4JiH
             oA+P3T9v6xU=

End timestamp: 2019-11-13 08:01:19 +0100 (run time: 3m 11s)
  • Datenbank sichern
scp  /var/lib/aide/aide.db.new.gz user@secure-machine
  • eine unbefugte Änderung am System simulieren
groupadd intruders
  • AIDE Check laufen lassen
aide --check -c /var/lib/aide/aide.conf.autogenerated

4.6.3 Samhain

  • Installation
apt install samhain
  • Samhain internen Schlüssel ergänzen (<key> sollte durch eine lange, zufällige Zahl ersetzt werden)
systemctl stop samhain
samhain --add-key=<key>@/usr/sbin/samhain
cp /usr/sbin/samhain.out /usr/sbin/samhain
rm -f /var/lib/samhain/samhain_file
systemctl start samhain
  • Samhain Konfigurationsdatei anschauen/anpassen. Die Samhain Konfigurationsdatei ist noch nicht auf Debian 10 angepasst und sollte, um Fehlmeldungen zu vermeiden, an einigen Stellen (z.B. /bin, /sbin, /lib) geändert werden
$EDITOR /etc/samhain/samhainrc
  • Datenbank auf einen sicheren Server kopieren (in Produktionsumgebungen)
scp /var/lib/samhain/samhain_file nutzer@secure-host:.
  • Samhain ist als Service-Dämon gestartet
systemctl status samhain
  • Test Passwort-Dateien ändern
# test, Datei (/etc/shadow und /etc/passwd) ändern
passwd nutzerXX
  • Check mit Ausgaben nur Level "crit"
samhain -t check --foreground -l none -p crit
  • Samhain Datenbank aktualisieren
samhain -t update --foreground

4.7 Lynis

  • Lynis ist ein Sicherheitsscanner welcher veraltete Software-Versionen und bekannt unsichere Konfigurationen in Linux-Installationen aufspürt
  • Homepage: https://cisofy.com/lynis/
  • Lynis installieren (die lynis Version in den Debian Paket-Repositories ist veraltet)
sudo apt install dirmngr
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C80E383C3DE9F082E01391A0366C67DE91CA5D5F
sudo apt install apt-transport-https
echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list
apt update
apt install lynis
  • Lynis Version Information abfragen
lynis update info
  • Lynis starten
lynis audit system
  • Lynis Informationen anzeigen
lynis show help
lynis show commands
lynis show settings
lynis show profiles
lynis --man-page
  • In der Produktion: Lynis als Cron-Job (oder Systemd-Timer-Unit) eingerichten und periodisch ausführen, Ausgaben/Reports per E-Mail versenden

4.8 LSM - Linux-Sicherheits-Module

  • LSM (Linux Security Module) sind Erweiterungen des Linux-Kernels
    • Der Linux-Kernel definiert Schnittstellen, in welche sich die LSMs einklinken können:
      • Syscalls
      • Dateizugriffe
      • Prozess-Erstellung
      • Namespaces und cgroups
      • Benutzer-Identität (UID/GID)
    • Ein LSM Modul kann sich in eine oder mehrere dieser Schnittstellen einklinken
    • Wird diese Kernel-Funktion benutzt, so wird das LSM aktiv und wird die Kernel-Funktion nach Prüfung erlauben oder verbieten
  • Link: A Brief Tour of Linux Security Modules
  • Major LSMs: Mandatory Access Controls - nur eines dieser LSM kann (derzeit) im Linux-Kernel aktiviert sein
    • SELinux
    • AppArmor
    • SMACK (Simplified Mandatory Access Control)
    • TOMOYO
  • Minor LSMs: diese LSMs können zusätzlich zu den Major-LSMs und anderen Minor-LSMs aktiviert sein
    • YAMA
    • LoadPin
    • SafeSetID
    • Lockdown
    • Landlock
    • BPF - LSM Sicherheitsrichtlinien können mittels eBPF durchgesetzt werden
    • capabilities - Linux capabilities

4.8.1 Prüfen, welche LSMs im aktuell aktiven Linux-Kernel aktiv sind

# cat /sys/kernel/security/lsm
lockdown,capability,yama,tomoyo,bpf

4.8.2 YAMA

  • YAMA sammelt Sicherheitsfunktionen aus Linux-Kernel-Sicherheitspatches, welche nicht in eine der anderen Linux-Sicherheits-Module passen
  • in aktuellen Linux-Kerneln bietet mit YAMA einen Schutz gegen ptrace (ptrace_scope), d.h. das ein Prozess den Speicher und die Ausführung eines anderen Prozesses überwachen kann (diese Funktion wird für die Benutzung von Debuggern bei der Programmentwicklung benötigt). Auf Produktions-Serversystemen ist diese Funktion oft nicht benötigt.
  • Werte für ptrace_scope
    Wert Beschreibung
    0 normales Verhalten, jeder Prozess und Benutzer kann andere Prozesse überwachen
    1 ein Prozess kann nur einen eigenen Kind-Prozess überwachen
    2 nur ein Systemadministrator mit CAP_SYS_PTRACE kann Prozesse überwachen
    3 keine Überwachen von Prozessen mittels ptrace möglich, diese Einstellung kann im laufenden System nicht überschrieben werden
  1. Beispiel (Firefox als nutzerXX gestartet):
    root$ apt install strace
    nutzerXX$ strace -p $(pgrep firefox)
    root$ echo "1" > /proc/sys/kernel/yama/ptrace_scope
    nutzerXX$ strace -p $(pgrep firefox)
    strace: attach: ptrace(PTRACE_ATTACH, 3135): Operation not permitted
    

4.8.3 LoadPin

4.8.4 SafeSetID

  • Das SafeSetID Modul überwacht die Benutzung der SetUID/SetGID Syscalls (UID oder GID eines Prozesses ändern, z.B. via su oder sudo oder per SetUID-Bit in den Dateisystemrechten) und prüft die Benutztung gegen eine systemweite Whitelist
    • Mittels SafeSetID können Prozesse die Capability CAP_SETUID/CAP_SETGID benutzen um von einem unpriviligierten Benutzeraccount in einen anderen zu wechseln (um Rechte abzugeben), ohne das diese Programme die Rechte ausweiten können oder sogar Root- Rechte erlangen können
    • Die Whitelist wird als Text-Datei mit je einer Regel pro Zeile in das securityfs Pseudo-Dateisystem unter dem Pfad safesetid/uid_allowlist_policy (für UID Übergänge) und safesetid/gid_allowlist_policy (für GID Übergänge) geschrieben
    • Das Format jedes Eintrages ist <ausgangs-UID>:<neue-UID>\n
  • Dokumentation: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/LSM/SafeSetID.rst

4.8.5 Lockdown

  • Das Lockdown Modul beschränkt bestimmte Funktionen des Linux Kernels (Laden von unsignierten Modulen, PTRACE, eBPF, Hibernation = Speicherinhalte auf Datenträger schreiben, Zugriffe auf spezielle Gerätedateien unter /dev, Kernel perf Schnittstellen, ACPI-Tabellen …)
    • Lockdown kann per Kernel-Commandozeile aktiviert werden: Parameter lockdown=
    • Nachträglich kann Lockdown über das Pseudo-Dateisystem unter /sys/kernel/security/lockdown ein- oder aus-geschaltet werden
    • Lockdown kennt zwei Modi
      • integrity - Funktionen sind ausgeschaltet, welche den laufenden Kernel verändern können
      • confidentiality - Funktionen sind ausgeschaltet über welche sensible Daten aus dem Kernel ausgelesen werden können (z.B. Zugriffe auf /dev/mem
  • Lockdown LSM ist seit Kernel 5.4 verfügbar
  • Lockdown Status ausgeben (hier none, Modi integrity und confidentiality sind möglich)
    # cat /sys/kernel/security/lockdown
    [none] integrity confidentiality
    
  • Links

4.8.6 Landlock

  • Landlock ist ein LSM welches Prozessen erlaubt, die eigenen Dateisystem-Rechte (und die Rechte von Kind-Prozessen) über die Unix-Dateisystemrechte hinaus einzuschränken.
    • Da die Landlock Rechte-Einschränkungen vererbt werden, können auch Supervisor Programme erstellt werden, um Kind-Prozesse zu beschränken, ohne diese Kind-Prozesse im Quellcode ändern zu müssen
    • Landlock ist von der Idee vergleichbar mit dem OpenBSD pledge Mechanismus, wirkt jedoch nur auf Dateisystemrechte (pledge wirkt auf verschiedenen Syscall-Gruppen)
  • Seit Kernel 5.13 verfügbar
  • Dokumentation: https://landlock.io/
  • Kernel Dokumentation: https://www.kernel.org/doc/html/latest/security/landlock.html

4.8.7 SELinux

  • wir arbeiten auf einer VM im Internet. Benutzername nutzer und Passwort villa, Benutzer root hat das Passwort vogelsang.
Hostname IP-Adresse Teilnehmer
VM01 165.22.22.201 Stefan
VM02 167.71.32.142 Mario
VM03 167.71.34.240 Robin
VM04 167.71.44.11 Carsten
  • SELinux Hilfspakete installieren
yum install policycoreutils setools libselinux-utils selinux-policy-doc setools-console
  \ policycoreutils-python3 selinux-policy-devel policycoreutils-newrole
  • SELinux Label (Context) auf Dateien/Prozesse/Benutzer anzeigen
ls -lZ <pfad>
ps -auxZ
id -Z
  • SELinux Status abfragen
getenforce
sestatus
sestatus -v
  • SELinux Module auflisten
semodule -l | less
  • Modul-Dateien (binär) und die fertige Policy
ls -l /etc/selinux/targeted/active/modules/100/
ls -lh /etc/selinux/targeted/policy/
  • SELinux Policy Quelldateien
ls -l /usr/share/selinux/devel/
  • Apache Webserver installieren und starten
yum install httpd
systemctl enable --now httpd
  • Kleine Webseite anlegen
$EDITOR /var/www/html/index.html
  • Inhalt der HTML-Datei
<html>
<body>
<h1>Apache Webserver</h1>
</body>
</html>
  • SELinux Security Context auf der Datei
ls -lZ /var/www/html/index.html
  1. Ein Problem für SELinux erzeugen und bereinigen
    • index-html Datei im Verzeichnis des Benutzers root erstellen und dann in das Apache-WWW-Verzeichnis verschieben:
    rm /var/www/html/index.html
    $EDITOR /root/index.html
    mv /root/index.html /var/www/html/index.html
    ls -lZ /var/www/html/index.html
    
    • Apache sollte nun nicht mehr in der Lage sein, die HTML-Datei auszuliefern (Default-Apache 2 Webseite erscheint)
    • SELinux Meldungen im Audit-Log
    ausearch -m avc -ts recent -c httpd -i
    
    • SELinux Security Context prüfen
    matchpathcon -V /var/www/html/index.html
    
    • SELinux Security Context anpassen
    chcon --type httpd_sys_content_t /var/www/html/index.html
    
    • (Alternativ) SELinux Security Context aus der SELinux Policy angleichen
    restorecon -v /var/www/html/index.html
    
    • SELinux Security Context für Apache
    sesearch --allow --source httpd_t --target httpd_sys_content_t --class file
    
    • weitere SELinux Tools
    seinfo       # Übersicht über das SELinux Regelwerk
    seinfo -u    # Übersicht der SELinux Benutzer
    seinfo -r    # Übersicht der SELinux Rollen
    seinfo -t    # Übersicht der SELinux (Datei-) Typen
    
  2. SELinux und Benutzer
    • Benutzer nutzerXX in die Benutzerklasse user_u einfügen
    semanage login -l
    semanage user -l
    semanage login -a -s user_u nutzer
    # su oder sudo sollten nun für den Benutzer nicht mehr moeglich sein
    cat /etc/selinux/targeted/seusers
    semanage login -a -s guest_u nutzer
    getsebool allow_guest_exec_content
    setsebool allow_guest_exec_content off
    # scripts sind nun nicht mehr direkt ausführbar (indirekt über BASH oder SH trotzdem)
    
    • Fehlersuche
    ausearch -m avc -ts recent
    

5 Tag 5

5.1 Linux LSMs (Fortsetzung)

5.1.1 SELinux - Policy Development

  1. SELinux Policy erweitern - Ein simpler HTTP-Server
    • C-Compiler installieren
    yum install gcc
    
    • der Quellcode
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <err.h>
    
    char response[] = "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html; charset=UTF-8\r\n\r\n"
    "<!DOCTYPE html><html><head><title>Bye-bye baby bye-bye</title>"
    "<style>body { background-color: #111 }"
    "h1 { font-size:4cm; text-align: center; color: black;"
    " text-shadow: 0 0 2mm red}</style></head>"
      "<body><h1>Goodbye, world!</h1></body></html>\r\n";
    
    int main()
    {
      int one = 1, client_fd;
      struct sockaddr_in svr_addr, cli_addr;
      socklen_t sin_len = sizeof(cli_addr);
    
      int sock = socket(AF_INET, SOCK_STREAM, 0);
      if (sock < 0)
        err(1, "can't open socket");
    
      setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
      int port = 8080;
      svr_addr.sin_family = AF_INET;
      svr_addr.sin_addr.s_addr = INADDR_ANY;
      svr_addr.sin_port = htons(port);
    
      if (bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) {
        close(sock);
        err(1, "Can't bind");
      }
    
      listen(sock, 5);
      while (1) {
        client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
        printf("got connection\n");
    
        if (client_fd == -1) {
          perror("Can't accept");
          continue;
        }
    
        write(client_fd, response, sizeof(response) - 1); /*-1:'\0'*/
        close(client_fd);
      }
    }
    
    
    • Quellcode vorbereiten
    mkdir ~/src
    cd ~/src
    $EDITOR simple-server1.c
    
    • Übersetzen
    gcc -o simple-server simpler-server1.c
    
    • Installieren
    cp simple-server /usr/local/bin
    
    • Server startenm, Testen, mit einem Web-Browser an Port 8080 verbinden
    simple-server &
    
    • SELinux Label des Dienstes anzeigen
    ps -eZ | grep simple
    ls -lZ /usr/local/bin/simple-server
    
    • SELinux Policy Modul erstellen
    mkdir ~/selinux-src
    cd ~/selinux-src
    
    • ein Basis SELinux Policy Modul erstellen
    sepolicy generate -n simple-server --init /usr/local/bin/simple-server
    
    • die erstellen Policy-Dateien anschauen
    less simple-server.te
    less simple-server.fc
    less simple-server.if
    
    • SELinux Policy compilieren und ein RPM-Paket erstellen
    yum -y install rpm-build
    sh simple-server.sh
    ls -l
    
    • neues Modul aktivieren
    semodule -i simple-server.pp
    
    • den vorher gestarteten simple-server Prozess stoppen
    pkill simple-server
    
    • eine SystemD Service-Unit für den Server Dienst erstellen
    $EDITOR /etc/systemd/system/simple-server.service
    
    • die Unit-Datei
    [Unit]
    Description=a simple http server
    After=syslog.target network.target
    
    [Service]
    ExecStart=/usr/local/bin/simple-server
    
    [Install]
    WantedBy=multi-user.target
    
    • neue Systemd-Service-Datei mit dem richtigen SELinux Label versehen
    restorecon -R -v /etc/systemd/system/simple-server.service
    
    • Systemd Service-Units neu laden und den Simple-Server starten
    systemctl daemon-reload
    systemctl start simple-server
    systemctl enable simple-server
    
    • Nun den Dienst benutzen. Das Modul ist noch im Permissive Mode, Verstösse gegen die Policy werden im Audit-Log protokolliert
    ausearch -m avc -ts recent -c simple-server
    
    • Erklärungen zu den Policy-Fehlermeldungen
    ausearch -m avc -ts today -c simple-server | audit2why  | less
    
    • Policy-Regeln aus den Audit-Meldungen erstellen
    sepolgen-ifgen
    ausearch -m avc -ts today -c simple-server | audit2allow -R
    require {
            type simple-server_t;
            class tcp_socket { bind create setopt accept listen };
    }
    
    #============= simple-server_t ==============
    allow simple-server_t self:tcp_socket { bind create setopt accept listen };
    corenet_tcp_bind_generic_node(simple-server_t)
    corenet_tcp_bind_http_cache_port(simple-server_t)
    
    • Neue Policy-Regeln in die Policy einfügen, Modul entfernen, neu kompilieren und dann neu laden
    semodule -r simple-server
    sh ./simple-server.sh
    semodule -i simple-server.pp
    systemctl restart simple-server
    
  2. Eine Änderung an einer SELinux Policy
    • Unser Server lernt Logging. Den Inhalt in eine Datei simple-server.patch in das Verzeichnis mit dem Quellcode des simple-server speichern:
    --- simple-server1.c    2016-08-24 20:12:56.379000000 +0000
    +++ simple-server2.c    2016-08-24 21:13:31.648000000 +0000
    @@ -15,13 +15,20 @@
     "h1 { font-size:4cm; text-align: center; color: black;"
     " text-shadow: 0 0 2mm red}</style></head>"
       "<body><h1>Goodbye, world!</h1></body></html>\r\n";
    -
    +
     int main()
     {
       int one = 1, client_fd;
    +  FILE *f = fopen("/var/log/simple-server.log", "a");
    +  if (f == NULL)
    +  {
    +      printf("Error opening file!\n");
    +      exit(1);
    +  }
    +
       struct sockaddr_in svr_addr, cli_addr;
       socklen_t sin_len = sizeof(cli_addr);
    -
    +
       int sock = socket(AF_INET, SOCK_STREAM, 0);
       if (sock < 0)
         err(1, "can't open socket");
    @@ -41,7 +48,7 @@
       listen(sock, 5);
       while (1) {
         client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
    -    printf("got connection\n");
    +    fprintf(f,"got connection\n");
    
         if (client_fd == -1) {
           perror("Can't accept");
    
    • Patch einspielen
    patch -p1 < simple-server.patch
    
    • das gepatchte Programm:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <err.h>
    
    char response[] = "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html; charset=UTF-8\r\n\r\n"
    "<!DOCTYPE html><html><head><title>Bye-bye baby bye-bye</title>"
    "<style>body { background-color: #111 }"
    "h1 { font-size:4cm; text-align: center; color: black;"
    " text-shadow: 0 0 2mm red}</style></head>"
      "<body><h1>Goodbye, world!</h1></body></html>\r\n";
    
    int main()
    {
      int one = 1, client_fd;
      struct sockaddr_in svr_addr, cli_addr;
      socklen_t sin_len = sizeof(cli_addr);
    
      int sock = socket(AF_INET, SOCK_STREAM, 0);
      if (sock < 0)
        err(1, "can't open socket");
    
      setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
      int port = 8080;
      svr_addr.sin_family = AF_INET;
      svr_addr.sin_addr.s_addr = INADDR_ANY;
      svr_addr.sin_port = htons(port);
    
      if (bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) {
        close(sock);
        err(1, "Can't bind");
      }
    
      FILE *f = fopen("/var/log/simple-server.log", "a");
      if (f == NULL)
      {
          printf("Error opening file!\n");
          exit(1);
      }
    
      listen(sock, 5);
      while (1) {
        client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
        fprintf(f,"got connection\n");
        fflush(f);
    
        if (client_fd == -1) {
          perror("Can't accept");
          continue;
        }
    
        write(client_fd, response, sizeof(response) - 1); /*-1:'\0'*/
        shutdown(client_fd,2);
        close(client_fd);
      }
    }
    
    
    
    • den neuen Server-Dienst übersetzen, alten simple-server stoppen, neue Programm-Datei nach /usr/local/bin kopieren, SELinux Label anpassen und den Dienst neu starten
    gcc -o simple-server simple-server2.c
    systemctl stop simple-server
    cp simple-server /usr/local/bin
    restorecon -R -v /usr/local/bin/simple-server
    systemctl start simple-server
    
    • per Web-Browser die Webseite auf http://localhost:8080/ aufrufen
    • neue SELinux Log-Meldungen tauchen auf
    # ausearch -m avc -ts recent
    ----
    time->Wed Aug 24 21:17:34 2016
    type=SYSCALL msg=audit(1472073454.717:1390): arch=c000003e syscall=2 success=yes exit=3 a0=400ae2 a1=441 a2=1b6 a3=21000 items=0 ppid=1 pid=7869 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="simple-server" exe="/usr/local/bin/simple-server" subj=system_u:system_r:simple-server_t:s0 key=(null)
    type=AVC msg=audit(1472073454.717:1390): avc:  denied  { open } for  pid=7869 comm="simple-server" path="/var/log/simple-server.log" dev="vda1" ino=268256 scontext=system_u:system_r:simple-server_t:s0 tcontext=system_u:object_r:var_log_t:s0 tclass=file
    type=AVC msg=audit(1472073454.717:1390): avc:  denied  { create } for  pid=7869 comm="simple-server" name="simple-server.log" scontext=system_u:system_r:simple-server_t:s0 tcontext=system_u:object_r:var_log_t:s0 tclass=file
    type=AVC msg=audit(1472073454.717:1390): avc:  denied  { add_name } for  pid=7869 comm="simple-server" name="simple-server.log" scontext=system_u:system_r:simple-server_t:s0 tcontext=system_u:object_r:var_log_t:s0 tclass=dir
    type=AVC msg=audit(1472073454.717:1390): avc:  denied  { write } for  pid=7869 comm="simple-server" name="log" dev="vda1" ino=258603 scontext=system_u:system_r:simple-server_t:s0 tcontext=system_u:object_r:var_log_t:s0 tclass=dir
    
    • Policy-Erweiterung ausgeben, prüfen und in die Type-Enforcement-Datei simple-server.te einfügen:
    # ausearch -m avc -ts recent -c simple-server | audit2allow -R
    
    require {
            type var_log_t;
            type simple-server_t;
            class file { create open };
    }
    
    #============= simple-server_t ==============
    allow simple-server_t var_log_t:file { create open };
    
    • simple-server SELinux Modul entfernen, Policy neu übersetzen, Modul neu laden, testen
    • Solange die Policy anpassen, bis keine Permission-Meldungen im Audit-Log erscheinen
    • "Permissive" aus der finalen Policy herausnehmen
    # less simple-server.te
    policy_module(simple-server, 1.0.0)
    
    ########################################
    #
    # Declarations
    #
    
    type simple-server_t;
    type simple-server_exec_t;
    init_daemon_domain(simple-server_t, simple-server_exec_t)
    
    #permissive simple-server_t;
    
    ########################################
    #
    # simple-server local policy
    #
    require {
            type simple-server_t;
            type var_log_t;
            class tcp_socket { bind create setopt accept listen shutdown write };
            class file { create open write };
            class dir { write add_name };
    }
    
    allow simple-server_t self:fifo_file rw_fifo_file_perms;
    allow simple-server_t self:unix_stream_socket create_stream_socket_perms;
    allow simple-server_t self:tcp_socket { bind create setopt accept listen shutdown write };
    allow simple-server_t var_log_t:file { create open write };
    allow simple-server_t var_log_t:dir { write add_name };
    
    corenet_tcp_bind_generic_node(simple-server_t)
    corenet_tcp_bind_http_cache_port(simple-server_t)
    domain_use_interactive_fds(simple-server_t)
    logging_manage_generic_logs(simple-server_t)
    logging_rw_generic_log_dirs(simple-server_t)
    
    • simple-server SELinux Modul laden, simple-server Prozess per SystemD neu starten, Programm testen

5.1.2 TOMOYO

  • TOMOYO LSM kann zur Analyse eines Linux-Systems, oder zur Implementation einer Sicherheitrichtlinie für das Linux-System verwendet werden
  • TOMOYO beschränkt Linux-Prozesse auf Basis des Dateisystem-Pfads und der Prozess-Hierarchy ("Domain" in der TOMOYO Terminology, hat aber keinen Zusammenhang mit DNS, dem Domain-Name-System)
  • TOMOYO fasst einen oder mehrere Prozesse zu einer Domain zusammen
    • Jede Domain wird über ein Profil reglementiert
    • Es können 255 unterschiedliche Profile im TOMOYO LSM definiert werden
    • Jedes Profil kann unabhängig von anderen Profilen in einem von 3 Modi verwendet werden
      • Learning: Syscall-Aufrufe und Dateisystem-Interaktionen werden protokolliert und in das Profil aufgenommen (Erstellung eines Baseline-Profils für eine Prozess-Gruppe/Domain)
      • Permissive: Verstösse gegen die Policy werden protokolliert, aber nicht durchgesetzt
      • Enforcing: Verstösse gegen die Policy werden aktiv verhindert und protokolliert
  • Kernel-Dokumentation: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/LSM/tomoyo.rst
  • Handbuch: https://tomoyo.osdn.jp/2.6/index.html.en
  • TOMOYO kann alternativ auch als Linux-Kernel-Modul geladen werden (dann ist es kein LSM, sondern kann zusätzlich zu anderen Major-LSMs benutzt werden)

5.1.3 SMACK

  • SMACK ist ein Mandatory Access Controll System im Linux Kernel, welches im Vergleich zu SELinux weniger komplex ist
  • SMACK ist seit Kernel 2.6.25 Teil des Linux-Kernels
  • SMACK wird heute hauptsächlich in Linux-Systemen von IoT-Geräten und in Automotive-Anwendungen verwendet (z.B. im Tizen OS von Samsung)
    • Wie auch SELinux arbeitet SMACK auch mit Sicherheits-Label auf Basis von erweiterten Attributen in den Linux-Dateisystemen
      • Es ist möglich SMACK in mittels der eingebauten Sicherheitspolicy auch ohne erweiterte Attribute zu betreiben, dann kann die Sicherheitsrichtlinie jedoch nicht angepasst werden
    • SMACK bindet Sicherheitslabel beim Empfang an IP-Pakete
      • Die Sicherheitsrichtlinie kann benutzt werden, um die Kommunikation von Anwendungen auf bestimmte IP-Adressen oder Netzwerke zu beschränken
      • Diese Funktion von SMACK kann zu Performance-Verlusten bei der Netzwerkkommunikation führen, wenn SMACK im Kernel aktiv ist
  • SMACK Kernek Dokumentation
  • Heise iX: SMACK im Linux Kernel

5.1.4 AppArmor

  • AppArmor ist bei Debian 10 installiert und aktiviert
  • AppArmor Wiki http://wiki.apparmor.net/index.php/Main_Page
  • Im Gegensatz zu SELinux definiert AppArmor die Sicherheits-Richtlinien auf Basis von Dateisystem-Pfaden und nicht auf Dateisystem-Attributen

5.2 Kernel Parameter

  • Kernel Parameter können auf der Kernel-Kommando-Zeile im Bootloader angegeben werden, um Kernel-Funktionen zu steuern

5.2.1 Audit-Subsystem

  • Audit-Subsystem anschalten
audit=[0|1]
  • wenn audit nicht gesetzt ist, dann wir das Audit-Subsystem erst mit dem Starten des Audit-Daemon auditd aktiv
  • Wert 0 – Audit-Subsystem ist ausgeschaltet
  • Wert 1 – Audit-Subsystem wird sofort aktiv, der Kernel sammelt Audit Informationen und übergibt diese an den Audit-Daemon, sobald dieser gestartet ist

5.2.2 AppArmor

apparmor=[0|1]
  • AppArmor an/ausschalten

5.2.3 SELinux

  • SELinux an/ausschalten
selinux=[0|1]
  • SELinux Regeln durchsetzen (enforcing)
enforcing=[0|1]
  • Wert 0 = SELinux im permissive Modus
  • Wert 1 = SELinux im enforcing Modus

5.2.4 Signierte Module

module.sig_enforce
  • wenn gesetzt, können nur Kernel-Module mit einer gültigen Signatur geladen werden

5.2.5 NOEXEC

noexec=[on|off]
  • bei 32bit PAE Kerneln, schaltet Schreibschutz auf Daten-Speicherseiten an

5.2.6 Datei-Capabilities

no_file_caps
  • Schaltet die Datei-Capabilities aus

5.2.7 Keine Module nachladen

nomodule
  • es können keine Module nachgeladen werden

5.2.8 Kernel-Panic

panic=<timeout>
  • Wert > 0 - Sekunden bis zum Reboot
  • Wert = 0 - kein Reboot (* aus Sicherheitsgründen empfohlen)
  • Wert < 0 - sofortiger Reboot

5.2.9 sysctl

sysctl -a
  • Permanente sysctl Einstellungen in /etc/sysctl.conf
kernel.randomize_va_space = 2

# Restrict core dumps
fs.suid_dumpable = 0

# Hide exposed kernel pointers
kernel.kptr_restrict = 1

#Prevent SYN attack, enable SYNcookies (they will kick-in when the max_syn_backlog reached)
# use iptables synproxy
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096

# Disables packet forwarding
net.ipv4.ip_forward = 0
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv6.conf.all.forwarding = 0
net.ipv6.conf.default.forwarding = 0

# Disables IP source routing
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0

# Enable Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Don't relay bootp
net.ipv4.conf.all.bootp_relay = 0

# Don't proxy arp for anyone
net.ipv4.conf.all.proxy_arp = 0

# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1

5.3 Netzzwerksicherheit

5.3.1 offene Port am Server prüfen

  • netstat - auf welchen Ports horchen Programme
netstat -tulpen
  • netstat - welche Verbindungen sind aktuell offen
netstat -puten
  • socket-stat
ss -tu46a
  • lsof, alle Verbindungen und offenen Ports anzeigen
lsof -i
  • Scan von aussen auf den Server per nmap
yum install nmap
# TCP-Scan mit Betriebssystem-Erkennung
nmap -sT -O 192.168.1.235
# kein DNS, kein Ping, TCP-Connect-Scan, UDP-Connect-Scan, alle Ports
nmap -n -Pn -sT -sU -p-  192.168.1.235
  • IPv6 nmap Scan
nmap -6 -sT -O 2001:4dd0:ff00:809d:216:d3ff:feb0:9c3

5.4 Secret Sharing

apt install ssss
  • Ein Geheimniss (Passwort) auf 5 Shares aufteilen, bei denen 3 Shares reichen um das Geheimnis wiederherzustellen
ssss-split -t 3 -n 5
  • Geheimnis aus 3 Shares wiederherstellen
ssss-combine -t 3

5.5 CVE (Common Vulnerabilities and Exposures)

5.5.1 Common Vulnerability Scoring System (CVSS)

  1. CVSS V2
    • Access Vector (AV) - wie kann der Angreifer die Lücke ausnutzen
      • AV:L lokaler Angriff möglich
      • AV:A Angriff aus den gleichen Subnetz möglich
      • AV:N Remote über das Netzwerk
    • Access Complexity (AC) - wie schwierig ist es für einen Angreifer die Lücke auszunutzen, sobald er im System ist
      • AC:H Hoch
      • AC:M Medium
      • AC:L Niedrig
    • Authentication (Au) - wie oft muss sich der Angreifer am System anmelden/authentisieren muss
      • Au:M mehrfache Authentisierung notwendig (Benutzer -> sudo Root)
      • Au:S einmalige Anmeldung genügt (normaler Benutzer)
      • Au:N garnicht
    • Confidentiality Impact (C) - Auswirkung auf die Datensicherheit
      • C:N keine
      • C:P Teil-Daten
      • C:C alle Daten
    • Integrity Impact (I) - Auswirkung auf die Integrität des Systems
      • I:N keine Auswirkung
      • I:P System teilweise nicht mehr vertrauenswürdig
      • I:C System nicht mehr vertrauenswürdig
    • Availability Impact (A) - Auswirkung auf die Verfügbarkeit des Systems
      • A:N keine Auswirkung
      • A:P teilweise beeinträchtigung der Verfügbarkeit
      • A:C Komplettausfall des Systems
  2. CVSS V3
    • Angriffs Vektor (AV)
      • Network (N) - Angriff über Netzwerk möglich
      • Adjacent (A) - Angreifer muss im lokalen Netz sein
      • Local (L) - Angreifer muss lokal auf dem System sein
      • Physical (P) - Angreifer muss physischen Zugang zu dem System haben
    • Angriffs Komplexität (AC)
      • Low (L) - keine besondern Kentnisse beim Angreifer erforderlich
      • High (H) - der Angreifer braucht spezielle Kenntnisse
    • benötigte Privilegien (PR)
      • None (N) - keine besonderen Privilegien notwendig
      • Low (L) - Normale Benutzeranmeldung notwendig
      • High (H) - Angreifer benötigt spezielle Rechte
    • Unterstützung duch einen Benutzer (UI)
      • None (N) - der Angriff kann ohne Aktion eines lokalen Benutzers erforderlich sein
      • Required (R) - der Angriff benötigt die Unterstützung eines lokalen Benutzers
    • Scope (Reichweite) (S)
      • Unchanged (U) - die Sicherheitslücke beeinträchtigt nur das angegriffene System
      • Changed (C) - über die Sicherheitslücke werden auch andere Systeme als das angegriffene beeinträchtigt
    • Auswirkungen auf den Schutz von Daten (Confidentiality Impact) (C)
      • High (H) - Datenschutz kann nicht mehr sichergestellt werden
      • Low (L) - einige Daten können in die Hände des Angreifers fallen
      • None (N) - die Sicherheitslücke hat keine Auswirkungen auf den Schutz der Daten
    • Auswirkungen auf die Integrität der Daten (I)
      • High (H) - die Daten können vom Angreifer verändert werden und der Angreifer kann damit direkt Schaden verursachen
      • Low (L) - der Angreifer kann Daten verändern, hat aber keine Kontrolle über die Auswirkungen
      • None (N) - der Angreifer kann keine Daten verändern
    • Auswirkungen auf die Verfügbarkeit des Systems (A)
      • High (H) - das System fällt aus
      • Low (L) - es gibt Beeinträchtigungen der Verfügbarkeit
      • None (N) - die Sicherheitslücke hat keine Auswirkungen auf die Verfügbarkeit
    • Verfügbarkeit von Angriffscode
      • Undefiniert (X) - es liegen keine Informationen über die Verfügbarkeit von Schadcode vor
      • High (H) - es gibt automatisierte Angriffs-Programme
      • Functional (F) - es existiert Schadcode der manuell ausgeführt werden kann und in den meisten Fällen erfolgreich ist
      • Proof-of-Concept (P) - es gibt Beispiele für Schadcode, dieser ist jedoch auf dem meisten Systemen nicht einsetzbar
      • Unproven (U) - es gibt noch keinen Code oder die Sicherheitslücke ist nur theoretisch
    • Abhilfe
      • Undefiniert (X) - es liegen noch keine Informationen über Patche vor
      • Unavailable (U) - es gibt noch keinen Schutz gegen die Sicherheitslücke
      • Workaround (W) - es gibt keinen Fix, aber eine Anleitung die Ausnutzung der Sicherheitslücke zu verhindern
      • temporary fix (T) - es gibt einen vorläufigen Patch
      • official fix (O) - es gibt einen offiziellen Patch
    • Glaubwürdigkeit
      • Undefiniert (X) - es können keine Aussagen zur Glaubwürdigkeit der Meldung gemacht werden
      • Confirmed (C) - die Sicherheitslücke wurde bestätigt
      • Reasonable (R) - die Sicherheitslücke ist glaubhaft
      • Unknown (U) - es gibt Berichte über Sicherheitsprobleme, aber eine Verbindung zur Sicherheitslücke konnte noch nicht bestätigt werden

5.6 DNSSEC

5.6.2 DNS Sicherheit (oder die Abwesenheit derselben)

  1. DNS Sicherheit - Grundlagen

    dns-dangers01.png

  2. DNS Sicherheit - Grundlagen

    dns-dangers02.png

  3. DNS Sicherheit - Grundlagen

    dns-dangers03.png

  4. DNS Sicherheit - Grundlagen

    dns-dangers04.png

5.6.3 DNS Sicherheit - Angriffe

dns-dangers05.png

  1. DNS Sicherheit - Angriffe

    dns-dangers06.png

  2. DNS Sicherheit - Angriffe

    dns-dangers07.png

  3. DNS Sicherheit - Angriffe

    dns-dangers08.png

5.6.4 DNSSEC

roadsign.png

  1. Was ist DNSSEC
    • Absicherung von DNS Daten mittels kryptografischer Signaturen
    • Asymmetrische Verschlüsselung
    • der Empfänger von DNS Daten kann prüfen (validieren) das
      • die Daten vom Besitzer des privaten Schlüssels der Zone kommen
      • die Daten seit dem Einstellen in die Zone nicht geändert wurden

5.6.5 DNSSEC Geschichte

  1. DNSSEC Geschichte

    DNSSEC-History01.png

  2. DNSSEC Geschichte

    DNSSEC-History02.png

  3. DNSSEC Geschichte

    DNSSEC-History03.png

  4. DNSSEC Geschichte

    DNSSEC-History04.png

  5. DNSSEC Geschichte

    DNSSEC-History05.png

  6. DNSSEC Geschichte

    DNSSEC-History06.png

  7. DNSSEC Geschichte

    DNSSEC-History07.png

  8. DNSSEC Geschichte

    DNSSEC-History08.png

  9. DNSSEC Geschichte

    DNSSEC-History09.png

  10. DNSSEC Geschichte

    DNSSEC-History10.png

  11. DNSSEC Geschichte

    DNSSEC-History11.png

  12. DNSSEC Geschichte

    DNSSEC-History12.png

  13. DNSSEC Geschichte

    DNSSEC-History13.png

  14. DNSSEC Geschichte

    DNSSEC-History14.png

5.6.6 DNSSEC Validierung Grundlagen

  1. DNSSEC Validierung

    DNSSEC-Validation01.png

  2. DNSSEC Validierung

    DNSSEC-Validation02.png

  3. DNSSEC Validierung

    DNSSEC-Validation03.png

  4. DNSSEC Validierung

    DNSSEC-Validation04.png

  5. DNSSEC Validierung

    DNSSEC-Validation05.png

  6. DNSSEC Validierung

    DNSSEC-Validation06.png

  7. DNSSEC Validierung

    DNSSEC-Validation07.png

  8. DNSSEC Validierung

    DNSSEC-Validation08.png

  9. DNSSEC Validierung

    DNSSEC-Validation09.png

  10. DNSSEC Validierung

    DNSSEC-chain-of-trust.png

  11. DNSSEC Validierung

    DNSSEC-Validation10.png

  12. DNSSEC Validierung

    DNSSEC-Validation11.png

  13. DNSSEC Validierung

    DNSSEC-Validation12.png

  14. DNSSEC Validierung

    DNSSEC-Validation13.png

  15. DNSSEC Validierung

    DNSSEC-Validation14.png

  16. DNSSEC Validierung

    DNSSEC-Validation15.png

  17. DNSSEC Validierung

    DNSSEC-Validation16.png

  18. DNSSEC Validierung

    DNSSEC-Validation17.png

  19. DNSSEC Validierung

    DNSSEC-Validation18.png

  20. DNSSEC Validierung

    DNSSEC-Validation19.png

5.6.7 DNSSEC Records

  1. RRSIG - Resource Record Signature

    DNSSEC-Records01.png

  2. RRSIG - Resource Record Signature

    DNSSEC-Records02.png

  3. RRSIG - Resource Record Signature

    DNSSEC-Records03.png

  4. RRSIG - Resource Record Signature

    DNSSEC-Records04.png

  5. RRSIG - Resource Record Signature

    DNSSEC-Records05.png

  6. RRSIG - Resource Record Signature

    DNSSEC-Records06.png

  7. RRSIG - Resource Record Signature

    DNSSEC-Records07.png

  8. RRSIG - Resource Record Signature

    DNSSEC-Records08.png

  9. RRSIG - Resource Record Signature

    DNSSEC-Records09.png

  10. DNSKEY - DNSSEC Schlüssel

    DNSSEC-Records10.png

  11. DNSKEY - DNSSEC Schlüssel

    DNSSEC-Records11.png

  12. DNSKEY - DNSSEC Schlüssel

    DNSSEC-Records12.png

  13. DNSKEY - DNSSEC Schlüssel

    DNSSEC-Records13.png

  14. DS - Delegation Signer Record

    DNSSEC-Records14.png

  15. DS - Delegation Signer Record

    DNSSEC-Records15.png

  16. DS - Delegation Signer Record

    DNSSEC-Records16.png

  17. DS - Delegation Signer Record

    DNSSEC-Records17.png

5.6.8 DNSSEC Validierung (vereinfacht)

DNSSEC-val-simple01.png

  1. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple02.png

  2. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple03.png

  3. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple04.png

  4. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple05.png

  5. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple06.png

  6. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple07.png

  7. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple08.png

  8. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple09.png

  9. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple10.png

  10. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple11.png

  11. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple12.png

  12. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple13.png

  13. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple14.png

  14. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple15.png

  15. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple16.png

  16. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple17.png

  17. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple18.png

  18. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple19.png

  19. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple20.png

  20. DNSSEC-Validierung (vereinfacht)

    DNSSEC-val-simple21.png

5.6.9 DNSSEC und Client-Systeme

dnssec-stub-resolver1.png

  1. DNSSEC und Client-Systeme

    dnssec-stub-resolver2.png

  2. DNSSEC und Client-Systeme

    dnssec-stub-resolver5.png

  3. DNSSEC und Client-Systeme

    dnssec-stub-resolver6.png

  4. DNSSEC und Windows DNSSEC-Aware-Clients

    dnssec-stub-resolver7.png

5.7 DNS-Transportverschlüsselung

5.7.1 Datenschutz im DNS?

  • In den letzten Jahren hat die IETF das DNS-Protokoll um Datenschutzfunktionen erweitert
    • DNS-over-TLS (Transport-Verschlüsselung zwischen DNS-Client und DNS-Resolver)
    • DNS-over-HTTPS (Transport-Verschlüsselung zwischen DNS-Client und DNS-Resolver)
    • QNAME-Minimierung (weniger Metadaten im DNS)
    • EDNS-Padding (Verstecken von DNS-Daten in verschlüsselten Verbindungen)

5.7.2 Der Bedarf für mehr DNS-Datenschutz

  • Eine auf der IETF 105 im Rahmen des Applied Networking Research (ANR) Workshop im Juli 2019 vorgestellte Studie ergab, dass
    • 8,5 % der Netzwerke (AS) DNS-Anfragen abfangen (27,9 % in China)
    • (heute) die meisten abgefangenen Anfragen (noch) unverändert beantwortet werden
  • aber die Situation könnte sich ändern, die Abfangserver könnten DNS-Antworten ändern

5.7.3 Transportverschlüsselung für DNS

  • Terminology
    • Do53 = DNS-over-Port53 - klassisches DNS (UDP/TCP Port 53)
    • DoT = DNS-over-TLS - TLS als Transport für DNS
    • DoH = DNS-over-HTTPS - HTTPS als Transport für DNS
    • DoQ = DNS-over-QUIC - QUIC als Transport für DNS
    • DoC = DNS-over-Cloud - DNS Namensauflösung via Cloud-Diensten (Google, Q9, Cloudflare …)

5.7.4 DoT - DNS-over-TLS

  1. DNS-over-TLS (1/3)

    dns-over-tls01.png

  2. DNS-over-TLS (2/3)

    dns-over-tls02.png

  3. DNS-over-TLS (3/3)

    dns-over-tls03.png

5.7.5 DoH - DNS over HTTP(S)

  1. DoH - DNS-over-HTTPS

    dns-over-https.png

5.7.6 DoH timeline

  • IETF 100 - November 2017 - DNS over HTTP(S) (DoH) workinggroup started: https://datatracker.ietf.org/wg/doh/about/
  • IETF 101 - March 2018 - work on DNS Queries over HTTPS finished, start of working group last call (WGLC) in April 2018
  • October 2018 - RFC 8484 published

5.7.7 DNS-over-HTTPS und IDS/Network-filter

Zitat aus RFC 8484:

Operational Considerations […] Filtering or inspection systems that rely on unsecured transport of DNS will not function in a DNS over HTTPS environment due to the confidentiality and integrity protection provided by TLS.

5.7.8 DoT vs DoH

  • Unterschiede zwischen DoT und DoH
    • DoT kann leicht blockiert werden, da es über einen speziellen Port (853) läuft.
    • DoH sieht wie normaler HTTPS-Verkehr aus, selektives Blockieren von DoH ist schwierig
    • DoH scheint einfacher zu implementieren zu sein, da bereits viele HTTPS Bibliotheksfunktionen in Programmiersprachen existieren
    • DoH ermöglicht es Entwicklern, die DNS-Namensauflösung auf Anwendungsebene durchzuführen (dies kann problematisch sein, das es pro Computer keine einheitliche Namensauflösung mehr gibt)

5.7.9 Das Dilemma von DoH

  • Um möglichst viele der Internetnutzer zu erreichen, die einen Schutz der Privatsphäre benötigen, muss DoH standardmäßig aktiviert sein
    • Die (Vor-)Auswahl des DoH-Servers kann ähnlich wie die Auswahl der CA im Browser betrachtet werden
  • eine feste Auswahl "pro Region" führt (immer noch) zu einer Zentralisierung aller DNS-Anfragen bei einigen wenigen DNS-Betreibern
    • aber das könnte auch ohne DoH der Fall sein, einige Länder in Asien senden > 90% der DNS-Anfragen an DoC (Google)
  • Die IETF arbeitet an neuen Protokollspezifikationen, die es den Kunden ermöglichen, sichere und vertrauenswürdige DNS-Resolver zu finden (ADD "Adaptive DNS Discovery" Working Group https://datatracker.ietf.org/wg/add/about/)

5.7.10 DoH kontrollieren - die Canary Domain

  • Mozilla hat eine Prüfung auf eine Canary Domain im Firefox implementiert
  • Der Domain-Name der Canary-Domain ist use-application-dns.net.
  • Wenn dieser Domain-Name über DNS53 -> unmanaged DNS aufgelöst werden kann, kann DoH auto-aktiviert werden
  • wenn der Domain-Name nicht aufgelöst werden kann (= gesperrt ist) -> managed DNS, DoH wird nicht automatisch aktiviert (aber Benutzer können DoH manuell aktivieren)
  • IETF diskutiert eine ähnliche Signalisierung: "Signaling resolver's filtering policies" (draft-mglt-add-signaling-filtering-policies)
  1. andere Prüfungen, die Firefox vor der Aktivierung von DoH durchführt
    • Auflösen von Canary-Domains bestimmter bekannter DNS-Anbieter zur Erkennung von Inhaltsfilterung
    • Auflösen der safe-search-Varianten von google.com und youtube.com auf, um festzustellen, ob das Netzwerk auf sie umleitet
    • Windows und macOS: Erkennung von Kindersicherungen, die im Betriebssystem installiert sind
    • Bei privaten Enterprise-Netzwerken werden zusätzlich folgende Prüfungen durchgeführt:
      • Ist die Firefox-Einstellung security.enterprise_roots.enabled auf true gesetzt?
      • Ist eine Unternehmensrichtlinie im Browser konfiguriert?

5.7.11 Aktueller DoT/DoH-Status

  1. Firefox-Browser
  2. Chrome(ium) Browser
    • DoH ist implementiert und kann vom Benutzer aktiviert werden.
      • Google Chrome
      • Opera
      • Vivaldi
      • Brave
      • Microsoft Edge
      • Bromite
    • DoH auto upgrade für die konfigurierten DNS-Resolver (manuell konfiguriert oder per DHCP/RA bereitgestellt)
    • Google experimentiert mit adaptiver DoH-Resolver-Erkennung über DNS
  3. Safari Browser (iOS, iPadOS, MacOS)
    • Unterstützung für DoH und DoT in iOS 14 und MacOS 11 'Big Sur'
    • Unterstützung für Adaptive DNS-Resolver-Discovery
  4. Microsoft Windows 10
    • Unterstützung in aktuellen Builds von Windows 10
    • verwendet den konfigurierten DNS-Resolver im Netzwerk-Stack (auch bekannt als "auto Update" auf DoH)
  5. Linux
    • DoT-Unterstützung in systemd-resolved seit einiger Zeit verfügbar
    • Nur opportunistischer Modus (automatischer Fallback zu DNS53)
    • keine Server-Authentifizierung (MITM möglich)
    • globale oder "pro Schnittstelle"-Einstellung
    • standardmäßig nicht aktiviert
  6. OpenBSD
    • DoT-Unterstützung in unwind
    • standardmäßig aktiviert seit OpenBSD 6.9
    • opportunistischer "auto update" Modus oder manuell konfigurierter "strict" Modus
    • Server-Authentifizierung über TLS-Zertifikat
  7. Android
    • DoT verfügbar ab Andoid 9 "Pie"
    • manuelle Einstellung
    • "Auto-Upgrade" vom konfigurierten DNS-Resolver oder Google DNS als Fallback
  8. Apple MacOS 11 und iOS/iPadOS 14
    • Unterstützung für DoT und DoH
    • Auswahl des Resolvers global und pro App/Applikation möglich
    • "verschlüsselte DNS"-Konfiguration Apps möglich, Benutzer kann Anbieter durch Installation der App wählen. Manuelle Konfiguration nicht möglich.
    • OS kann "pro Domain" DoH/DoT-Einstellung über DNS oder HTTP lernen (Adaptive DNS-over-HTTPS)
    • OS kann DoH/DoT Server über DHCP/PvD (Provisioning Domains) ermitteln oder Abfragen an resolver.arpa über klassischen DNS53
    • Die Erkennungsmethoden werden in der IETF-Arbeitsgruppe ADD aktiv diskutiert

5.7.12 Adaptives DNS-über-HTTPS

  • Ziele (direkt aus dem Internet-Entwurf übernommen):
    • Keine andere Partei als der Client und der Server kann die vom Client abgefragten Namen oder die vom Server zurückgegebenen Antworten lesen oder kontrollieren
    • Nur ein designierter DNS-Resolver, welcher organisatorisch zu dem Server gehört, welcher auch die Inhalte hostet, ist in der Lage, sowohl die Client IP-Adresse und die abgefragten Namen für datenschutzsensible Verbindungen lesen.
    • Clients sind in der Lage, die von VPNs und lokalen Netzwerken geforderten Richtlinien einzuhalten
  1. Designierter DoH-Server für Domänen
    • DoH-Server für eine Domäne können vpm Browser oder vom Betriebssystem gelernt werden
      • aus DNSSEC-gesicherten HTTPSSVC/SVCB-DNS-Records
      • HTTP(S) ALT-SVC Header
      • DoH-Server "well-known" URL
      • lokale Bereitstellungsdomäne (PvD)
  2. HTTPSSVC-Record
    • Eliminiert zusätzlichen Roundtrip (DNS oder HTTP)
    • HTTPSSVC liefert
      • Adressinformationen (ipv4hint, ipv6hint)
      • Protokollinformationen (Protokoll-Upgrade-Anfrage -> HTTP/3[QUIC])
      • öffentliche Schlüssel (verschlüsselter TLS-Client-Hallo)
      • andere Daten, wie Informationen zu DNS-Transportverschlüsselung (dohuri)
  3. HTTPSSVC Example
    example.com.       IN HTTPSSVC 0 svc.example.net.
    svc.example.net.   IN HTTPSSVC 2 svc1.example.net. (
    			dohuri=https://doh.example.net/dns-query
    			odohkey="..." )
    
  4. Oblivious DoH (oDoH)
    • eine Erweiterung von DoH, die es erlaubt, die Client-IP-Adressen von den Abfragen-daten über Proxying zu trennen (pauly-dprive-oblivious-doh)
  5. Adaptive DNS Discovery and oDoH

    01-oDoH-Overview.png

  6. Adaptive DNS Discovery and oDoH

    02-oDoH-Local-Bootstrap-DNS53.png

  7. Adaptive DNS Discovery and oDoH

    03-oDoH-Local-Bootstrap-DNS53 1.png

  8. Adaptive DNS Discovery and oDoH

    04-oDoH-Local-Bootstrap-PvD.png

  9. Adaptive DNS Discovery and oDoH

    05-oDoH-Local-Bootstrap-PvD.png

  10. Adaptive DNS Discovery and oDoH

    06-oDoH-Remote-Bootstrap.png

  11. Adaptive DNS Discovery and oDoH

    07-oDoH-Remote-Bootstrap.png

  12. Adaptive DNS Discovery and oDoH

    08-oDoH-Remote-DoH-verification.png

  13. Adaptive DNS Discovery and oDoH

    09-oDoH-Remote-DoH-verification.png

  14. Adaptive DNS Discovery and oDoH

    10-oDoH-Query-via-Proxy.png

  15. Adaptive DNS Discovery and oDoH

    11-oDoH-Query-via-Proxy.png

  16. Adaptive DNS Discovery and oDoH

    12-oDoH-Query-via-Proxy.png

  17. Adaptive DNS Discovery and oDoH

    13-oDoH-Query-via-Proxy.png

6 Anhang

6.1 Literaturliste

6.2 Linkliste

6.2.1 Crypto Wettbewerbe

6.2.2 Linux Zufallszahlen