Linux Server Sicherheit Kursnotizen Mai 2025
- Live Script: http://server-sicherheit.lxht.de
- Einführung und Krypto Basics: http://server-sicherheit.lxht.de/intro.html
- Linuxhotel Lab-Server (Bewertung, Passwort ändern etc): http://lab.linuxhotel.de
- Wiki https://wiki.linuxhotel.de/doku.php?id=server-sicherheit:start
- Literaturliste
- SUDO Mastery https://www.michaelwlucas.com/nonfiction/sudo-mastery
- SSH Mastery https://www.michaelwlucas.com/nonfiction/ssh-mastery
- PGP & GPG https://www.michaelwlucas.com/nonfiction/pgp-gpg-email-for-the-practical-paranoid
- Christof Paar, Jan Pelzl – Understanding Cryptography ISBN: 3642446493
- Klaus Schmeh – Kryptografie ISBN: 3864900158
- Niels Ferguson, Bruce Schneier, Tadayoshi Kohno – Cryptography Engineering ISBN: 0470474246
- Malcolm Harkins – Managing Risk and Information Security ISBN: 1430251131
- Tobias Klein – Aus dem Tagebuch eines Bughunters ISBN: 978-3-89864-659-8
- Ross Anderson – Security Engineering (PDF: http://www.cl.cam.ac.uk/~rja14/book.html)
- Steven M. Bellovin – Thinking Security: Stopping Next Year’s Hackers (Addison-Wesley Professional Computing) ISBN-10: 0134277546/ISBN-13: 978-0134277547
- Donald A. Tevault – Mastering Linux Security and Hardening ISBN: 1788620305
- Kyle Rankin – Linux Hardening in Hostile Networks ISBN-13: 978-0134173269
- Nikolai Philipp Tschacher – Typosquatting in Programming Language Package Managers http://incolumitas.com/data/thesis.pdf
1 Tag 1
1.1 Crypto Wettbewerbe
- Cryptographic competitions http://competitions.cr.yp.to/
- NIST SHA3 Competition http://csrc.nist.gov/groups/ST/hash/sha-3/
- NIST AES Competition http://csrc.nist.gov/archive/aes/index2.html
- NIST - Announcing Request for Nominations for Public-Key Post-Quantum Cryptographic Algorithms: https://www.federalregister.gov/documents/2016/12/20/2016-30615/announcing-request-for-nominations-for-public-key-post-quantum-cryptographic-algorithms
1.2 Links zum Thema Krypto-Algorithmen
- Guidance for Choosing an Elliptic Curve Signature Algorithm in 2022 https://soatok.blog/2022/05/19/guidance-for-choosing-an-elliptic-curve-signature-algorithm-in-2022/
TL;DR
Ed25519 is great. NIST P-256 and P-384 are okay (with caveats). Anything else is questionable, and their parameter selection should come with a clear justification.
1.3 Aufgabe: Hash und HMAC
- Lade die Datei https://server-sicherheit.lxht.de/LinuxSecurityEinfuehrung.pdf
- Welcher SHA256 Hash-Wert ist korrekt?
- 0245bcddf700ddfb4fd37c58bbfc67e19b9aa8827d0242fc9beb40078925f191
- f8eee6980c49d8020b10449a0fec6544e266af09
- 22833704a424725d5725d977cc733244afe0e38a6e2a987a560c95aa39da2d01
- 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:
- ’LinuxHotel’
- ’EssenHorst’
- ’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 od -xa cipher.txt # 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 Zufallszahlen und Linux (heutzutage meistens obsolet)
1.6.1 Moderne Kernel (ab Version?)
- benutzen einen internen HAVE-Algorithmus,
d.h. dort sind weder
haveged
noch dierng-tools
sinnvoll!
1.6.2 Für ältere Systeme und/oder spezielle Systeme (ohne hwrng
)
- Starte
top
in einem anderen Terminal-Fenster, beobachte dort die CPU Benutzung desssh-keygen
Prozesses - Erstelle einen 10000 bit ssh RSA Schlüssel (hier nur zur Demo von
Zufallszahlen und
haveged
oderrngd
)
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!
- Durchsatz des Zufallszahlengenerators messen
- rngd installieren
apt install rng-tools5 systemctl status rngd
- aus
/dev/random
lesen und der Durchsatz perpv
anzeigen lassen
apt install pv dd if=/dev/random | pv > /dev/null
haveged
an-/ausschalten (in einem anderen Terminal, die Datenrate impv
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.6.3 Weitere Informationen zu Linux Zufallszahlen
- Problems emerge for a unified
/dev/*random
https://lwn.net/Articles/889452/ - Kernel 5.4: random: try to actively add entropy rather than passively wait for it https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=50ee7529ec45
- LWN- “Waiting for entropy” https://lwn.net/Articles/724643/
- On Linux’s Random Number Generation https://research.nccgroup.com/2019/12/19/on-linuxs-random-number-generation/
1.7 Verschlüsselungssysteme
1.7.1 GnuPG/GPG - GNU Privacy Guard
- GnuPG is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). GnuPG allows you to encrypt and sign your data and communications; it features a versatile key management system, along with access modules for all kinds of public key directories. GnuPG, also known as GPG, is a command line tool with features for easy integration with other applications. A wealth of frontend applications and libraries are available. GnuPG also provides support for S/MIME and Secure Shell (ssh): https://gnupg.org
1.7.2 AGE - Actually Good Encryption
- A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability: https://age-encryption.org
1.7.3 XCA - X Certificate and Key Management
- X.509 graphisch und nachvollziehbar ;-)
1.8 su
- mit dem Programm
su
(Switch User eigentlich Substitute User) kann ein Benutzer ein einen anderen Benutzerkontext wechseln - Unterschiede bei den Umgebungsvariablen zwischen
su
undsu -
odersu -l
- bei
su
werden die Umgebung des aufrufenden Benutzer übernommen (kann Sicherheitsprobleme erzeugen) - die Variablen
$IFS
,$HOME
,$SHELL
,$USER
,$LOGNAME
,$PATH
werden beisu -
odersu -l
zurückgesetzt
- bei
- Such-Pfade für Benutzer und
root
werden in/etc/login.defs
über die OptionenENV_PATH
undENV_SUPATH
konfiguriert
1.9 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.9.1 Links zur Passwort Sicherheit
- Auch das BSI verabschiedet sich vom präventivem,regelmäßigen Passwort-Wechsel: https://www.heise.de/news/Passwoerter-BSI-verabschiedet-sich-vom-praeventiven-Passwort-Wechsel-4652481.html?utm_source=chatgpt.com
1.9.2 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.9.3 Yesycrypt ab 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
- erst bei einer Passwortänderung mittels
- 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:::
- Yescrypt in Debian 11 https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html#pam-default-password
- Yescrypt Informationen https://www.openwall.com/yescrypt/
- pam_unix und yescrypt
- yescrypt benutzt einen cost factor [1..11] anstelle der rounds
[...] password [success=1 default=ignore] pam_unix.so obscure yescrypt rounds=10 [...]
Man erkennt es am Parameterteil im gehashten passwort (shadow) $jDT
statt $j9T
Standard sind 5 “Runden”
1.9.4 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.9.5 Benutzerdatenbank
- Die Benutzerinformationen für die Passwortanmeldung unter
Unix/Linux werden in der Datei
/etc/shadow
gespeichert
- 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
- 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) y yescrypt
1.10 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
- Passwortänderung nach der initialen Anmeldung erzwingen
chage -d 0 fritz
1.11 sudo
sudo
ist ein moderner Ersatz fürsu
. Gegenübersu
hatsudo
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 -V
sudo
Basis-Konfiguration ausgebensudo
Konfigurationsdatei sicher editieren (ggf. Variable$EDITOR
setzen, sonst wirdvi
verwendet)
EDITOR=emacs visudo
- aliase (host, user, command)
- sudo und das Environment
sudo -i
vs.sudo su -
1.11.1 Beispiel:
- Befehl
cat
auf die Datei/var/log/apt/term.log
für Benutzernutzer02
visudo -f /etc/sudoers.d/apt-term-cat ---- nutzer02 ALL=(root) /bin/cat /var/log/apt/term.log ---- nutzerXX$ sudo -l
sudo -l
Zeigt diesudo
-Konfiguration und die erlaubten Befehle einessudo
-Benutzers an.
1.11.2 Aufgabe:
- Erstelle eine
sudo
Konfiguration, um es dem Benutzer nutzerXX zu erlauben, die Logdatei/var/log/boot.log
und unter den Benutzerberechtigungen des Benutzersroot
mit den Programmless
anzuschauen
1.11.3 Lösung
visudo -f /etc/sudoers.d/log-message-view ------ ... nutzerXX ALL=(root) /usr/bin/less /var/log/boot.log ...
- in einem anderen Terminal/Tmux-Fenster, teste sudo als nutzerXX
nutzerXX$ sudo less /var/log/boot.log nutzerXX$ sudo less /etc/shadow # <--- darf nicht gehen
1.11.4 Frage:
- gibt es mit dieser Konfiguration ein Sicherheitsproblem?
1.11.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.11.6 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
- Gruppe berechtigen
visudo -f /etc/sudoers.d/admins %sudo ALL=(ALL) NOPASSWD: ALL
- Shells
sudo -s # entspricht su sudo -i # entspricht su -
1.11.7 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.11.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 -i
- 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.11.9 einfaches Intrusion Detection mit sudo
(ab sudo 1.8.7) (nur Theorie)
openssl dgst -sha256 /usr/bin/passwd SHA256(/usr/bin/passwd)= a92b1b6fb52549ed23b12b32356c6a424d77bcf21bfcfbd32d48e12615785270 visudo ---- nutzerXX ALL= sha256:a92b1b6fb52... /usr/bin/passwd ----
1.11.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.11.11 Befehle ohne Passwort
nutzer ALL=(dba) NOPASSWD: /opt/oracle/bin/befehl
1.11.12 Passwort des Zielaccount angeben (SUSE Linux Default)
Defaults targetpw
1.11.13 Links zu “sudo”
- Sudo for blue teams: how to control and log better https://www.sudo.ws/posts/2022/05/sudo-for-blue-teams-how-to-control-and-log-better/
1.12 PAM -Pluggable Authentication Modules
- Dokumentation des Linux-PAM-Systems
- https://github.com/linux-pam/linux-pam/
- (nicht mehr vorhanden) http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html
- https://fossies.org/linux/Linux-PAM-docs/doc/sag/Linux-PAM_SAG.pdf
- (als Archiv, enthält auch das alte HTML SAG) https://fossies.org/linux/misc/Linux-PAM-1.6.1-docs.tar.xz/
- Debian 8-11 Pfad für PAM-Module
/lib/x86_64-linux-gnu/security/
- Debian 12 Pfad für PAM-Module
/usr/lib/x86_64-linux-gnu/security/
- Beispiel der PAM Konfigurationsdatei
/etc/pam.d/common-auth
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 …]
- Return-Values
- vgl. z.B. /usr/include//security/_pam_types.h
- 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.12.1 Aufgabe: pam_warn.so
für Login installieren
- Installiere das Modul
pam_warn.so
fuer die Facilityauth
(zusätzlichsession
) in PAM-Dienstlogin
- 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.13 Lösung
- in Datei
/etc/pam.d/login
(ans Ende hinter alle @include)
auth required pam_warn.so session required pam_warn.so
- per STRG+ALT+F2 auf eine Text-Konsole wechseln
- die neuen Log-Einträgen mit
journalctl -f --grep pam_warn
oderjournalctl -f --facility=authpriv
prüfen - als
nutzerXX
einloggen
1.13.1 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,
wirkt sich aber nicht aus (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 wann es sich auswirkt.
- 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.13.2 Lösung:
- Modul
pam_nologin.so
, aktiviert durch die Datei/etc/nologin
:
echo 'Heute kein Login möglich! Wartungsarbeiten bis Dienstag!' > /etc/nologin
1.13.3 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 "secrt" | od -x 0000000 6573 7263 0a74 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.13.4 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 vomsu
aufnehmen, die Konfiguration von OATH undcommon-auth
auskommentieren
... auth required pam_otpw.so ... session optional pam_otpw.so #@include common-auth ...
- Auf alten Systemen benutzt
otpw-gen
zur Initialisierung des Zufallszahlengeneratorsnetstat
(ist das sicher?). Auf debian 12 (bookworm) ist das nicht mehr erforderlich.
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.13.5 Weitere Links zu PAM
- Understanding the effects of PAM module results (’controls’ in PAM jargon) https://utcc.utoronto.ca/~cks/space/blog/sysadmin/PAMModuleResultsEffects
- A Linux PAM setup and the problem of stopping authentication https://utcc.utoronto.ca/~cks/space/blog/linux/PAMStackingAndStopping
- TOTP authenticator implement as a terminal tool https://github.com/MinaOTP/MinaOTP-Shell
- Minimal TOTP generator in 20 lines of Python https://github.com/susam/mintotp
- Using a Yubikey as a touchless, magic unlock key for Linux https://kliu.io/post/yubico-magic-unlock/
- Windows Hello™ style facial authentication for Linux https://github.com/boltgolt/howdy
1.13.6 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.14 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> |
CTRL+B O | |
Größe ändern | CTRL+B CTRL+<cursor> |
CTRL+B <ESC> <cursor> | |
Zoomen | CTRL+B z |
Layout ändern | CTRL+B <space> |
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 |
2 Tag 2
2.1 Zugriff auf Ressourcen beschränken
2.1.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)
- 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
- Aktuelle Limits der aktuellen Session anzeigen
ulimit -a
- limit setzen und testen
ulimit -S -t 2 dd if=/dev/urandom | gzip > /dev/null
- das stress Programm https://people.seas.harvard.edu/~apw/stress/
apt install stress ulimit -S -t 2 prlimit --cpu=10:20 stress -c 1
- Anzahl Logins beschränken
wir passen die Anzahl der erlaubten Logins pro Benutzer an
nutzerXX - maxlogins 2
- testen der neuen Konfiguration
ssh nutzerXX@localhost
3 x wiederholen oder auf mehr als 3 Konsolen anmelden
- 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
- testen
ps -p $$ -o pid,user,nice,cmd ulimit -a forkbomb(){ forkbomb | forkbomb & }; forkbomb
2.1.2 nice, renice und cpulimit
apt install cpulimit stress-ng -c 8 # CPU Kerne * 2 renice -n <nice-wert> <pid> cpulimit -l 50 -p <pid> # nicht mehr empfohlen
2.1.3 ionice
- 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 zuionice
findet sich in der Linux-Kernel Dokumentation/usr/src/linux/Documentation/block/ioprio.txt
.
- per
- iotop
iotop
zeigt die IO-Auslastung des Systems nach Prozessen an. In der Spalte “PRIO” wird dieionice
Klasse und die Priorität angezeigt. Shortcuts beachten: Eventuell sortierung und accup anpassenapt install iotop stress -d 2 iotop
2.2 Linux cgroups (Controll-Groups)
- CGroups Informationen anzeigen
cat /proc/cgroups ps xawf -eo pid,user,cgroup,args systemd-cgls systemd-cgtop
2.2.1 CGroups manuell
- Stress erzeugen
stress-ng --cpu $(($(nproc)*2)) & pgrep -alf stress-ng
- CGroup manuell anlegen und kontrollieren
cd /sys/fs/cgroup mkdir stressgroup cd stressgroup cat cgroup.controllers cat cgroup.type cat cgroup.subtree_control
- Neue Untergruppen anlegen und kontrollieren
mkdir stress1 stress2 ls -l stress1 cat stress1/cgroup.type cat stress1/cgroup.controllers
- Controller vererben
echo +io +cpu > cgroup.subtree_control ls -l stress1
- Alle Prozesse in die Gruppe stress1 legen.
cd stress1 pgrep stress-ng | while read pid; do echo $pid > cgroup.procs; done
- Schrittweise Last auf die Gruppe stress2 verteilen. Top beobachten. Weiter bis ca. Gleichstand erreicht ist.
cd ../stress2 echo <pid> > cgroup.procs
- Kontrolle mit weight. Top beobachten
echo 10 > cpu.weight
- In der anderen Gruppe mit harten Limits (CPU=100%) begrenzen
cd ../stress1 cat cpu.max echo 100000 100000 > cpu.max
- Alle Prozesse beenden
pkill stress-ng rmdir stress1 stress2 cd .. rmdir stressgroup
2.2.2 systemd
systemctl set-property --runtime cups.service CPUQuota=10% systemctl cat cups.service
2.2.3 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 CPUWeight=33 systemctl set-property run-r<UUID>.service CPUQuota=100 systemd-run --on-active=20 -p CPUQuota=50% stress-ng --cpu 4
2.2.4 systemctl accounting anschalten
$EDITOR /etc/systemd/system.conf.d/accounting.conf ----- DefaultCPUAccounting=yes DefaultIOAccounting=yes DefaultBlockIOAccounting=yes DefaultMemoryAccounting=yes DefaultTasksAccounting=yes
- BlockIO… gilt als deprecated. Deshalb fehlt die Directive.
systemd-analyze cat-config /etc/systemd/system.conf # pruefen
2.3 Dateisystemberechtigungen
2.3.1 normale Unix-Rechte
- die klassischen Unix-Dateisystemberechtigungen (RWX)
- 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
- 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
- Frage:
- kann
nutzer2
mit diesen Berechtigungen die Datei verändern?
- kann
- 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.
- 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
- Sticky-Bit auf Verzeichnis - Nur der Besitzer der Datei darf die Datei löschen
chmod o+t <verzeichnis>
2.3.2 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!
- 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
- erweiterte Attribute welche nur vom Benutzer root verwaltet werden
- a – append - Datei kann nur erweitert werden
- i – immutable - Datei ist unveraenderbar
- C – no copy-on-write - für COW-Filesysteme (btrfs)
- 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.3.3 Posix ACLs
- ACLs setzen (modify)
setfacl -m u:<nutzer>:rwx file/dir # ACL setzen setfacl -x u:<nutzer> # ACL löschen setfacl -d -m "u::rwx,g::rwx,o::-" <dir> # Default ACL auf Verzeichnisse setzen setfacl -m "d:u::rwx,d::g:rwx,d:o::-" <dir> # alternative Syntax. Generic default mask setfacl -d -m u:<uidName>:rwx <file/dir> # Benamte Default ACL macht sie "vererbbar"
- ACLs auslesen
getfacl <datei/verzeichnis>
- 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.4 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.4.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.4.2 Beispiel: root CAP_CHOWN entziehen
capsh --drop=cap_chown -- chown fritz /home/prj
2.4.3 strace
Einfache Prozessverfolgung
strace -e file ls -l
z.B. Verfolgen einer Shell mit ping
strace -e %creds -ff -p <pid>
2.5 systemd Sicherheit
2.5.1 Einfache Direktiven
- Units unter anderer uid/gid laufen lassen
- Zugriff auf Verzeichnisse beschränken
- Prozesslimits setzen
systemctl edit --full --force simplehttp.service [Unit] Description=Python HTTP Server (do not use) [Service] Type=simple Restart=on-failure EnvironmentFile=-/etc/default/%n ExecStart=/usr/bin/python3 -m http.server $HTTP_PORT # Namespace Spielereien #WorkingDirectory=/usr/share/doc ReadOnlyDirectories=/proc /sys InaccessibleDirectories=/var/log PrivateTmp=yes ProtectSystem=strict ProtectHome=read-only # Limits # darf nicht forken #LimitNPROC=1 # darf nicht ins fs schreiben #LimitFSIZE=0 # laeuft als root. Capabilities # entziehen #CapabilityBoundingSet=~cap_chown,cap_net_raw # setzen #CapabilityBoundingSet=cap_net_raw CapabilityBoundingSet=cap_net_bind_service # laeuft als user. Capabilities #User=gabi #Group=users DynamicUser=yes AmbientCapabilities=cap_net_bind_service
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.5.3 Selbstanalyse
- systemd-analyze security
- systemd-analyze security <unit.service>
3 Tag 3
3.1 SSH
3.1.1 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
3.1.2 SSH Known Hosts hashen
ssh-keygen -H -f .ssh/known_hosts
$EDITOR .ssh/config ---------- HashKnownHosts yes ---------- chmod -Rc go= .ssh
3.1.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
, nichtroot
) 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
- Es empfiehlt sich, die Schlüssel mit
ssh-copy-id -i .ssh/...
zu begrenzen - 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/authorized_keys
einzutragen. - Administrator: Nun sind die Schlüssel ausgetauscht, und wir können
Anmeldung per Passwort auf dem Server-System abschalten. Als
root
Benutzer:
- 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 ------
- 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
3.1.4 SSH Passphrase ändern
ssh-keygen -p -f .ssh/id_ed25519
3.1.5 SSH-Agent
- SSH-Agent starten (wird normalerweise in der Benutzer-Sitzung gestartet, z.B. über “.profile”)
#entweder in der aktiven Shell eval $(ssh-agent) #oder als prefix-Befehl ssh-agent tmux #oder bash
- 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
3.1.6 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>
- Ü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
3.1.7 SSH Agent-Forwarding vs. ProxyCommand
- Sicherheits-Probleme mit Agent-Forwarding!
- https://heipei.github.io/2015/02/26/SSH-Agent-Forwarding-considered-harmful/
- https://michael.stapelberg.de/Artikel/ssh-conditional-tunneling
- Agent forwarding (
ssh -A nutzerXX@notebookYY
) kann von einem Angreifer auf dem “Jumphost” abgefangen werden (Socket zum Agent im /tmp-Verzeichnis des Jumphost).
- 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
- Ü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
- erstelle eine lokale Konfigurationsdatei
3.1.8 SSH Tunnel
- Über SSH Tunnel können beliebige Ports über die SSH Verbindung geleitet werden
- Praktische Illustration zu local und remote tunnels:
https://iximiuz.com/ssh-tunnels/ssh-tunnels.png
- Tunnel von Port 80 auf dem Server (notebookYY) zu Port 8080 auf dem Client über notebookXX
ssh -L 8080:notebookYY: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
- Ü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 nutzer31@192.168.1.83
- 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
3.1.9 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)
3.1.10 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
- Übung: lokale SSH-Client-Konfigurationsdatei
- Zeit: 15 Minuten
- erstelle eine lokale SSH-Konfigurationsdatei
~/.ssh/config
für die Verbindung auf die IP-Adresse des VM Servers für das SELinux Kapitel (später im Kurs)
Benutzer Server Domainname Eva selinux001.dnslab.org Philip selinux002.dnslab.org Rafael selinux003.dnslab.org Mirko selinux004.dnslab.org Stefan selinux005.dnslab.org Michi selinux006.dnslab.org Rene selinux007.dnslab.org Carsten selinux008.dnslab.org - vergebe den symbolischen Namen
selinux
für den Server - SSH-Server läuft auf Port 22
- Benutzername
user
, Passwortvilla
- benutze die IP-Adresse des Servers als Hostnamen in der
Konfiguraionsdatei (find die IPv4-Adresse des Servers mit
dig
odernslookup
% dig selinuxNNN.dnslab.org a
- die SSH Konfigurationsdatei sollte nur für den Benutzer lesbar sein (ggf. müssen die Dateiberechtigungen angepasst werden)
- teste die Verbindung per symbolischen Namen
ssh selinux
- Beispiellösung
Host selinux Hostname 159.223.128.127 User user Port 22
- Weitere Informationen und Tipps: Simplify Your Life With an SSH Config File
3.1.11 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
3.1.12 SSH-PAM-Module
pam_ssh.so
– per SSH Key Passphrase anmelden und Schlüssel in den Agent ladenpam_sshauth.so
– lokale Anmeldung durch erfolgreiche SSH-Anmeldung an einen fernen SSH Server
3.1.13 TODO Übung: PAM-Anmeldung per SSH Passphrase
- installiere
pam_ssh
apt install libpam-ssh
- prüfe, ob sich schon SSH-Schlüssel unter
/home/nutzerXX/.ssh/
befinden. Wenn nicht, einen SSH-Schlüssel erstellen perssh-keygen
und für den Schlüssel eine Passphrase vergeben. Diese Passphrase sollte nicht das normale Benutzerpasswort sein. - Konfiguriere
pam_ssh
alssufficient
PAM-Modul für das grafische Login (Datei/etc/pam.d/gdm-password =, Facility =auth
) - Konfiguriere
pam_ssh
alsoptional
PAM-Modul in/etc/pam.d/common-session
(Facilitysession
) - Die grafische GUI verlassen und an der GUI eine Anmeldung per SSH-Passphrase versuchen
- Prüfen das der SSH-Agent gestartet ist und den/die Schlüssel geladen hat
ssh-add -l
3.1.14 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
- Option
ssh -C -D 127.0.0.1:8080 nutzer@server
3.1.15 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.1.16 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.17 SSH-Schlüssel 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.18 Verwaltung von SSH authorized_keys auf dem Server
- Authorized-Keys via FUSE und DNS http://jpmens.net/2012/12/18/ssh-public-keys-on-a-dns-fuse/
- Authorized-Keys per TXT-Record im DNS (ohne FUSE) https://blog.cloudflare.com/flexible-secure-ssh-with-dnssec/
3.1.19 Ein CHROOT für SSH
- eine Gruppe für die CHROOT SSH Benutzer erstellen
groupadd sshusers useradd -m -s /bin/bash -g sshusers sshguy passwd sshguy
- wir erzeugen ein neues root Verzeichnis, das chroot-Verzeichnis
mkdir -p /var/ssh-chroot/{dev,etc,lib,lib64,usr,bin,home} mkdir -p /var/ssh-chroot/usr/bin chown root: /var/ssh-chroot
- die Gerätedatei
/dev/null
anlegen
mknod -m 666 /var/ssh-chroot/dev/null c 1 3
- das Heimverzeichnis des Benutzers in das chroot kopieren
cp -R /home/sshguy /var/ssh-chroot/home/ chown -R sshguy /var/ssh-chroot/home/
- wir kopieren einige Dateien aus
/etc
in das Verzeichnisetc
innerhalb deschroot
cd /var/ssh-chroot/etc cp /etc/ld.so.cache /etc/ld.so.conf /etc/nsswitch.conf /etc/resolv.conf .
- der Benutzer soll
bash
undls
ausführen können, also kommen diese Dateien in die chroot
cd ../bin cp /bin/ls /bin/bash .
- für jedes Programm im chroot müssen wir nun die dynamischen
Bibliotheken in das chroot Verzeichnis kopieren. Der
ldd
Befehl listet alle Bibliotheken
ldd /bin/ls ldd /bin/bash
- Wir haben ein Skript, welches die Bibliotheken für ein Programm in das chroot kopiert:
mkdir ~/bin $EDITOR ~/bin/l2chroot ---- #!/bin/bash # Use this script to copy shared (libs) files to Apache/Lighttpd chrooted # jail server. # ---------------------------------------------------------------------------- # Written by nixCraft <http://www.cyberciti.biz/tips/> # (c) 2006 nixCraft under GNU GPL v2.0+ # + Added ld-linux support # + Added error checking support # ------------------------------------------------------------------------------ # See url for usage: # http://www.cyberciti.biz/tips/howto-setup-lighttpd-php-mysql-chrooted-jail.html # ------------------------------------------------------------------------------- # Set CHROOT directory name BASE="/var/ssh-chroot" [ ! -d $BASE ] && mkdir -p $BASE || : # iggy ld-linux* file as it is not shared one FILES="$(ldd $1 | awk '{ print $3 }' |egrep -v ^'\(')" echo "Copying shared files/libs to $BASE..." for i in $FILES do d="$(dirname $i)" [ ! -d $BASE$d ] && mkdir -p $BASE$d || : /bin/cp $i $BASE$d done # copy /lib/ld-linux* or /lib64/ld-linux* to $BASE/$sldlsubdir # get ld-linux full file location sldl="$(ldd $1 | grep 'ld-linux' | awk '{ print $1}')" # now get sub-dir sldlsubdir="$(dirname $sldl)" if [ ! -f $BASE$sldl ]; then echo "Copying $sldl $BASE$sldlsubdir..." /bin/cp $sldl $BASE$sldlsubdir else : fi
- Script ausführbar machen
chmod +x ~/bin/l2chroot
- das Script benutzen, um die Bibliotheken in das chroot zu kopieren
l2chroot /var/ssh-chroot/bin/ls l2chroot /var/ssh-chroot/bin/bash
- prüfen, das Bibliotheks-Dateien kopiert wurden
ls -l /var/ssh-chroot/lib64 ls -l /var/ssh-chroot/lib/x86_64-linux-gnu/
- einen Hardlink für BASH in
/usr/bin
im chroot erstellen
ln bin/bash usr/bin/
- Manueller Test der chroot Umgebung:
chroot /var/ssh-chroot/ /bin/bash
- Chroot für die Gruppe sshusers in der SSH-Konfiguration einrichten (Konfiguration am Ende der Datei anfügen)
$EDITOR /etc/ssh/sshd_config ---- Match group sshusers ChrootDirectory /var/ssh-chroot/ X11Forwarding no AllowTcpForwarding no PasswordAuthentication yes ----
- SSH-Daemon neu starten
systemctl restart sshd
- Ausprobieren:
ssh sshguy@localhost
- Fertig!
3.1.21 Daten mit SSH-Schlüsseln verschlüsseln
- Encrypt and decrypt a file using SSH keys https://www.bjornjohansen.com/encrypt-file-using-ssh-key
3.1.22 TPM chip protecting SSH keys - properly
3.1.23 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 Paketgcc
undbuild-essential
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.24 Vorschläge für eine sichere SSH-Server Konfiguration
- Quellen
- SSH Security https://stribika.github.io/2015/01/04/secure-secure-shell.html
- Secure Secure Shell Wiki: https://github.com/stribika/stribika.github.io/wiki/Secure-Secure-Shell
- SSH Server Konfiguration öffnen
$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 # Bei SELinux Systemen 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 # rsa-sha2-512 ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null
- Nach dem Erstellen neuer Schlüssel den 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.1.25 Links zum Thema SSH
- (Basic) SSH Keys Part 1: Simple setup + ProxyJump http://bad.network/basic-ssh-keys-part-1-simple-setup-proxyjump.html
- (Basic) SSH Keys Part 2: Agent forwarding, Adding Keys http://bad.network/basic-ssh-keys-part-2-agent-forwarding-adding-keys.html
- Using a U2F/FIDO key with OpenSSH https://xosc.org/u2fandssh.html
- Cryptographic Signing using ssh-keygen(1) with a FIDO Authenticator https://undeadly.org/cgi?action=article;sid=20201016053038
- SCP - Familiar, Simple, Insecure, and Slow https://goteleport.com/blog/scp-familiar-simple-insecure-slow/
- OpenSSH 9.0 Release Notes
This release switches scp(1) from using the legacy scp/rcp protocol to using the SFTP protocol by default.
3.2 Linux-Distributionen (Sicherheitsbewertung)
- Debian 9/10/11
- MAC ++ (AppArmor, SELinux, TOMOYO)
- BuildHardening ++ (reproducible Builds)
- Geschwindigkeit von Sicherheits-Patches: +
- Minimale Installation: +
- Ubuntu - https://wiki.ubuntu.com/Security/Features
- MAC: ++ (AppArmor, SELinux)
- Build Hardening ++
- Geschwindigkeit von Sicherheits-Patches: ++
- Minimale Installation: O
- SUSE - https://en.opensuse.org/openSUSE:Security_Features
- MAC: ++ (AppArmor, SELinux)
- Build Hardening: +
- Geschwindigkeit von Sicherheits-Patches: ++
- Minimale Installation: -
- Red Hat / CentOS / Fedora - https://fedoraproject.org/wiki/Security_Features_Matrix
- MAC: + (SELinux)
- Build Hardening: +
- Geschwindigkeit von Sicherheits-Patches: +
- Minimale Installation: -
- Gentoo (Hardened) - https://wiki.gentoo.org/wiki/Hardened_Gentoo/de
- MAC: ++ (SELinux, AppArmor, TOMOYO)
- Build Hardening: ++
- Geschwindigkeit von Sicherheits-Patches: O
- Minimale Installation: ++
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
- 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_HARDENED_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)
- 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
- RELRO - RELocation Read-Only
- PIE - Position Independent Executable
- ASLR - Address Space Layout Randomization
- Fortify Source - Array Bounds-Checks etc.
- Stack protector/StackCanary - Stack Canary
- NX-No-Execute - Daten im Speicher als nicht ausführbar (NX=no execute) markieren
- Hintergrund-Informationen zu diesen Sicherheitsfunktionen: Notes on Build Hardening (December 15, 2018) https://blog.erratasec.com/2018/12/notes-on-build-hardening.html
- Studie von Sicherheitsfunktionen in Linux-Distributionen: Millions of Binaries Later: a Look Into Linux Hardening in the Wild (February 28, 2019) https://web.archive.org/web/20190302014002/https://capsule8.com/blog/millions-of-binaries-later-a-look-into-linux-hardening-in-the-wild/
- Programm zum Prüfen der Sicherheitsfunktionen
- Github Repository https://github.com/slimm609/checksec.sh
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 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 9DE922F1C2FDE6C4 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
**
3.6 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/
3.6.1 Installation
- 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 | sort -n
3.6.2 Konfiguration
- 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
- 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 anzeigen
# 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
3.6.3 Beispiele für Audit-Abfragen
- 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
- Aufgabe:
- Das Audit-Subsystem um neue Regel(n) zu Systemd erweitern:
- Alle Systemd-Konfigurationsdateien mit der Endung
*.conf
, welche direkt unter/etc/systemd
(nicht in den Unterverzeichnissen) gespeichert sind, sollen auf Schreibzugriffe überwacht werden - Die Audit-Events sollen mit dem Key
systemd
markiert 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 (suchen nach Events mit dem Keysystemd
)
- Alle Systemd-Konfigurationsdateien mit der Endung
- Das Audit-Subsystem um neue Regel(n) zu Systemd erweitern:
- Beispiel-Lösung
- Erweiterung der Audit-Regeln
[...] # 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 [...]
- Suche nach Audit-Events mit dem Schlüssel
systemd
ausearch -i -k systemd
3.6.4 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.6.5 CIS Benchmarks mit Vorlagen für Audit-Regeln
3.7 Secomp
- Secomp (auch Secomp-BPF) ist eine „Firewall“ für Syscalls. Syscalls sind die Funktionsaufrufe eines Betriebssystem-Kernels. Per Secomp können per Richtlinie die Syscalls eines Processes eingeschränkt werden. So können z.B. lokalen Hilfsprogrammen der Zugriff auf Systemaufrufe zur Manipulation der Netzwerkkonfiguration oder der Systemzeit entzogen werden.
- Secomp wird in der Regel nicht alleinstehend benutzt, sondern im
Zusammenhang mit Containern (Podman, Docker, FireJail) oder Systemd
(Unit Schlüsselwort
SystemCallFilter
). - Links zu Secomp:
- LWN: A seccomp overview https://lwn.net/Articles/656307/
- Securing systemd services with seccomp profiles https://prefetch.net/blog/2017/11/27/securing-systemd-services-with-seccomp-profiles/
- Denying Syscalls with Seccomp https://eigenstate.org/notes/seccomp
- Firejail Seccomp Guide https://firejail.wordpress.com/documentation-2/seccomp-guide/
- Linux x86_64 syscall Tabelle https://filippo.io/linux-syscall-table/
- Syscall Manpage
man syscalls
- Seccomp user-space notification and signals https://lwn.net/Articles/851813/
3.8 eBPF/BCC
- eBPF ist die extended Berkeley Packet Filter Infrastruktur im Linux Kernel
- eBPF ist eine Weiterentwicklung der Berkeley Packet Filter Technologie (classic BPF = cBPF) 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
- Einsatzgebiete:
- Netzwerksicherheit (erweiterte Firewall-Funktionen)
- Host-Sicherheit
- Forensik
- Fehler-Diagnose
- Performance-Messungen
- eBPF wird derzeit von Microsoft auf die Windows Betriebssysteme
portiert
- Making eBPF work on Windows https://cloudblogs.microsoft.com/opensource/2021/05/10/making-ebpf-work-on-windows/
- eBPF implementation that runs on top of Windows https://github.com/microsoft/ebpf-for-windows
3.8.1 BCC Übersicht
- BCC ist die BPF Compiler Collection, eine Sammlung von Tools und
eBPF Programmen
3.8.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.8.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
- 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
- Das BCC-Programm
- statsnoop
- Das BCC-Programm
statsnoop-bpfcc
zeigt systemweit Dateizugriffe mit denstat
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
- Das BCC-Programm
- 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]
- Das BCC-Programm
- mountsnoop
- Das BCC-Programm
mountsnoop-bpfcc
zeigt alle Aufrufe dermount
undumount
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
- Das BCC-Programm
- 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
- Das BCC- Programm
- killsnoop
- Das BCC-Programm
killsnoop-bpfcc
zeichnet alle Aufrufe des Systemaufrufkill
auf:
# killsnoop-bpfcc TIME PID COMM SIG TPID RESULT 12:46:34 16998 pkill 1 632 0
- Das BCC-Programm
- 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
- Das BCC-Programm
3.8.4 bpftrace
bpftrace
ist eine kleine Programmiersprache (ähnlich wieawk
), welche es Administratoren ermöglicht, kleine eBPF Scripts zu schreiben- Homepage https://bpftrace.org/
- Github Source Repository https://github.com/iovisor/bpftrace
- Histogram-Daten werden in der Regel 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); }
- 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, Paketauditd
)# 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 derbash
benutztenreadline
Bibliothek und zeichnet alle in derbash
(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
- 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.8.5 Bücher zu eBPF/BCC
- Linux Observability with BPF
- by Lorenzo Fontana, David Calavera
- Publisher: O’Reilly Media, Inc.
- Release Date: November 2019
- ISBN: 9781492050209
- BPF Performance Tools: Linux System and Application Observability
- by Brendan Gregg
- Publisher: Addison-Wesley Professional
- Release Date: December 2019
- ISBN: 9780136624523
- http://www.brendangregg.com/bpf-performance-tools-book.html
- Systems Performance, 2nd Edition
- by Brendan Gregg
- Publisher: Addison-Wesley Professional
- Release Date: December 2020
- ISBN: 978-0136820154
- https://www.brendangregg.com/systems-performance-2nd-edition-book.html
3.8.6 Links
- A brief introduction to XDP and eBPF https://blogs.igalia.com/dpino/2019/01/07/a-brief-introduction-to-xdp-and-ebpf/
- Dive into BPF: a list of reading material https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/
- A curated list of awesome projects related to eBPF: https://github.com/zoidbergwill/awesome-ebpf
- BPF, eBPF, XDP and Bpfilter… What are These Things and What do They Mean for the Enterprise? https://www.netronome.com/blog/bpf-ebpf-xdp-and-bpfilter-what-are-these-things-and-what-do-they-mean-enterprise/
- BCC Tutorial https://github.com/iovisor/bcc/blob/master/docs/tutorial.md
- Learn eBPF Tracing: Tutorial and Examples http://www.brendangregg.com/blog/2019-01-01/learn-ebpf-tracing.html
- Network debugging with eBPF (RHEL 8) https://developers.redhat.com/blog/2018/12/03/network-debugging-with-ebpf/
- Using eBPF for network traffic analysis https://www.ntop.org/wp-content/uploads/2018/10/Sabella.pdf
- BCC Referenz: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md
- eBPF Summit 2021:
- eBPF Foundation https://ebpf.io/
- Comparing SystemTap and bpftrace https://lwn.net/Articles/852112/
- nsjail | A light-weight process isolation tool, making use of Linux namespaces and seccomp-bpf syscall filters (with help of the kafel bpf language)
- How io_uring and eBPF Will Revolutionize Programming in Linux – The New Stack
- Auch in eBPF kann es Sicherheits-Fehler geben Zero Day Initiative — CVE-2020-8835: Linux Kernel Privilege Escalation via Improper eBPF Program Verification
- boopkit - Linux eBPF backdoor over TCP. Spawn reverse shells, RCE, on prior privileged access. https://github.com/kris-nova/boopkit
- BPFDoor — an active Chinese global surveillance tool https://doublepulsar.com/bpfdoor-an-active-chinese-global-surveillance-tool-54b078f1a896?gi=bd3c470d93a8
- hBPF = eBPF in hardware (An extended Berkley Packet Filter CPU written entirely in Python3 for PC and FPGA) https://github.com/rprinz08/hBPF
3.9 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.9.1 Namespace Beispielprogramm
- mit diesem kleinen Beispielprogramm wird gezeigt, das Linux-Container mit nur einem Systemaufruf erzeugt werden.
- Quelle: https://blog.lizzie.io/linux-containers-in-500-loc.html
- C-Compiler und Entwicklungs-Tools installieren
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); if (child_pid < 0) { printf("Es konnte kein namespace erzeugt werden (Fehler %d)\n", child_pid); return 1; } 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 (im Namespace das Proc-Dateisystem neu
mounten um die Prozess-Isolierung via
top
oderps
zu sehen:mount -t proc proc /proc
gcc -o namespaces namespaces.c
- Namespace via
exit
beenden und dasproc
Dateisystem auf dem Host neu mountenmount -t proc proc /proc
- 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); ...
- Die Netzwerkconfiguration im Namespace mit
ip
oderifconfig
anschauen
3.10 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
4 Tag 4
4.1 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 nichtroot
auf dem Host istsudo unshare --map-root-user --user sh
4.2 Namespaces auflisten RedHat
- 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
4.3 Container/Namespace mit Systemd
- Jedes Linux mit Systemd bietet mächtige Container-Verwaltungs-Werkzeuge mit
systemd-nspawn
arbeitet neben Image-Dateien für Container auch mit installieren Linux-Root-Dateien in einem beliebigen Verzeichnis auf dem Container-Host-System- Damit ist es sehr einfach, ein Container-System aufzusetzen und Dateien zwischen dem Container-Host und dem Linux im Container auszutauschen
- In diesem Kapitel installieren wir als Beispiel ein Rocky-Linux
(eine freie Red Hat Enterprise Linux Distribution) in einem
Verzeichnis unter Debian
- Andere Linux-Distributionen wie Ubuntu, Suse, Arch-Linux oder ältere Debian-Versionen wären auch möglich
- Wichig ist das die Dateien im Container-Verzeichnis für die CPU-Architektur des Container-Hosts übersetzt wurden und die Programme keinen neueren Kernel benötigen (keine neuen System-Calls)
- Seit Debian 9 müssen die Systemd-Container-Tools separat installiert werden:
apt install systemd-container
- Wir erstellen ein Verzeichnis für den neuen Container
mkdir -p /srv/container/rocky-linux8
- Initialisieren eine neue RPM-Instanz im Container-Verzeichnis (bei Debian mit debboostrap, bei SUSE mit RPM und zypper)
apt -y install rpm dnf rpm --root /srv/container/rocky-linux8 --initdb
- Das Basis-Paket für Rocky-Linux laden (Achtung: URLs ändern sich regelmäßig)
wget https://ftp.plusline.net/rockylinux/8/BaseOS/x86_64/os/Packages/r/rocky-release-8.8-1.8.el8.noarch.rpm wget https://ftp.plusline.net/rockylinux/8/BaseOS/x86_64/os/Packages/r/rocky-repos-8.8-1.8.el8.noarch.rpm rpm --nodeps --root /srv/container/rocky-linux8 -ivh rocky-release-8.5-3.el8.noarch.rpm rocky-repos-8.5-3.el8.noarch.rpm
- Das Rocky-Linux Basis-System installieren
dnf -y --nogpg --releasever=8 --installroot=/srv/container/rocky-linux8 \ install systemd passwd dnf procps-ng iproute tmux rocky-gpg-keys echo 8 > /srv/container/rocky-linux8/etc/dnf/vars/releasever
- Eine Shell im Container starten
systemd-nspawn -D /srv/container/rocky-linux8
- 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/rocky-linux8
- Weitere Software im Container installieren (hier den Apache Webserver)
dnf install httpd
- Anwendung im Rocky Linux Container starten (prüfen das kein andere Prozess auf dem Container-Host die Ports 80 und/oder 443 belegt)
systemctl enable --now httpd
- Der Apache Webserver innerhalb des Rocky Linux Containers sollte nun vom Firefox des Debian unter http://localhost erreichbar sein.
- Container stoppen (im Container eingeben)
conainter# poweroff
- Container mit privatem Netzwerk-Namespace starten:
systemd-nspawn -bD /srv/container/rocky-linux8 --private-network
- Container können auch mit virtuellen Netzwerkkarten und/oder Port-Mappings konfiguriert werden
- Systemd-Befehle um einen Container vom Host aus zu 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
**
4.4 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 heuter auch 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 die Absicherung der DNS Namensauflösung mittels 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
,gabi
etc., ggf. den Benutzer neu anlegen) in der Datei/etc/firejail/firejail.users
eintragen (Die Datei ggf. anlegen, pro Benutzer eine Zeile), um die Benutzung vonfirejail
durch diesen Benutzer zu erlauben - Zum 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 dasssh
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 (wenn die Datei noch nicht existiert dann die Bash einmal verlassen und wieder neu mitfirejail bash
starten) - Wechsle in das Verzeichnis
.ssh
- Liste alle Dateien im Heimverzeichnis mit
ls -la
und vergleiche mit der Ausgabe ohne Firejail. Was fällt auf?
- Firejail
bash
verlassen - Firejail mit einem Browser (hier Links)
- 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 Tasted
(Download) sichern, danach den Browserlinks
mit der Tasteq
verlassen- Wo ist die Datei gespeichert worden?
- Den Browser
- Erstelle im Heimverzeichnis des Benutzers ein Verzeichnis mit den
Namen
Downloads
$ mkdir ~/Downloads
- Starte
links
nochmals viafirejail
, lade das PDF von der Trainings-Webseite und speichere es im VerzeichnisDowloads
. 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
- 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 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.5 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.5.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-Container 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.5.2 Docker Installieren
- Docker installieren und starten
apt install docker.io usermod -aG docker <username>
- Docker testen
docker run hello-world
4.5.3 erste Schritte mit Docker
- Docker Image herunterladen
# docker pull almalinux # docker images
- Ein Alma-Linux (eine weitere freie Distribution von Red Hat Enterprise Linux) mit Bash starten
# docker run --name=application1 -it almalinux /bin/bash docker# dnf update -y docker# dnf install -y procps httpd docker# dnf 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 Container Konfiguration anzeigen -> siehe Go Template wie man nach Konfiguration-Informationen filtern kann https://golang.org/pkg/text/template/
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.5.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.5.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, verbinde Port 2015 vom Container auf einen freien Port auf dem Host
- teste die Caddy-Webseite mit dem Firefox auf dem Laptop http://<ip-des-Laptop>:<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-Dateiindex.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)
- stoppe den Container, lösche den Container (
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
- 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.5.6 mit Docker Images arbeiten
- Docker Image History anschauen
docker images docker history <image-name>
- Docker Image(s) in eine Datei sichern. Metadaten und Schichten bleiben erhalten
docker save -o mydockerapp.tar <image-name> [<image-name2>]
- Docker-Image aus einer Datei laden (welche mit
docker save
erstellt wurde)
docker load -i mydockerapp.tar
- Docker Container exportieren (nur das Dateisystem wird exportiert, die Schichten/Layer verschwinden)
docker ps -a docker export -o mydockerapp.tar <container-name> xz -v mydockerapp.tar
- Docker Container vom Tarball importieren
xzcat mydockerapp.tar.xz | docker import - <image-name>
- Docker Container in ein Image umwandeln (z.B. für forensische Analyse)
docker commit <container-ID> <image-name>
4.6 Docker Sicherheit
4.6.1 Docker Images
- Top ten most popular docker images each contain at least 30 vulnerabilities (Februar 2019): https://snyk.io/blog/top-ten-most-popular-docker-images-each-contain-at-least-30-vulnerabilities/
4.6.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.6.3 Audit-Regeln für 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.6.4 Docker-Engine nicht auf einem (ungeschützten) TCP Port betreiben
4.6.5 Docker Repository mit TLS absichern (x509 Zertifikate benötigt)
- in der Datei
/etc/sysconfig/docker
dockerd --tlsverify ...
4.6.6 User-Namespaces verwenden
- in der Datei
/etc/sysconfig/docker
dockerd --userns-remap=default ...
4.6.7 Legacy-Registry abschalten
- in der Datei
/etc/sysconfig/docker
dockerd --disable-legacy-registry ...
4.6.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.6.9 Docker Container nicht als Benutzer root betreiben
docker run -u dockeruser -d ...
4.6.10 Capabilities von Container-Prozessen beschränken
- 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.6.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.6.12 Speicher- und CPU-Resources des Containers einschränken
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.6.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.6.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.6.15 Fähigkeiten eines Docker Containers per AppArmor einschränken
- Docker mit AppArmor Profilen benutzen https://cloud.google.com/container-optimized-os/docs/how-to/secure-apparmor
- Docker Default AppArmor Profil: https://docs.docker.com/engine/security/apparmor/ https://github.com/docker/labs/tree/master/security/apparmor
4.6.16 Syscalls einschränken mit Seccomp
- LWN A seccomp overview https://lwn.net/Articles/656307/
- Default Docker Seccomp Profile https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
- Linux x86_64 syscall Tabelle https://filippo.io/linux-syscall-table/
man syscalls
- Docker Container mit eigenem Seccomp Profil starten:
docker run --security-opt=[seccomp=/pfad/zur/eignen/seccomo-profile.json]
4.6.17 Vorsicht bei dem Einsatz von KSM (Kernel-Same-Pages-Merging) RedHat
- Gefahr eines Rowhammer Angriffs auf Speicherbereiche über VM/Containergrenzen https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/virtualization_tuning_and_optimization_guide/chap-ksm
# 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.
- Rowhammer Angriff: https://de.wikipedia.org/wiki/Rowhammer
- Attacking a co-hosted VM: A hacker, a hammer and two memory modules https://thisissecurity.stormshield.com/2017/10/19/attacking-co-hosted-vm-hacker-hammer-two-memory-modules/
- KSM ausschalten (mehrere Optionen)
# /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.7 weitere Container-Tools
4.7.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.7.3 Bocker
- Docker nachimplementiert in 100 Zeilen Bash
- https://github.com/p8952/bocker
4.8 Incidence Response
- ISO/IEC 27035-1:2016 Information security incident management — Part 1: Principles of incident management https://www.iso.org/obp/ui/#iso:std:iso-iec:27035:-1:ed-1:v1:en:sec:A
- ISO/IEC 27035-2:2016 Information security incident management — Part 2: Guidelines to plan and prepare for incident response https://www.iso.org/obp/ui/#iso:std:iso-iec:27035:-2:ed-1:v1:en:sec:A
4.8.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.8.2 Kunden/Benutzer im Falle eines Sicherheitsvorfalls informieren
- Wenn die eigene Kommunikationsstruktur (z.B. E-Mail) betroffen ist, die alternativen Kommunikationswege benutzen
- Dokumentierte Notfall-Prozedur zur Kunden-Kommunikation vorhalten und verteilen
- Bei erkannten Angriffen 4 Augen-Prinzip beachten, nicht alleine arbeiten!
4.8.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.8.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.9 Rootkits aufspüren
- Root-Kit-Hunter installieren
apt install rkhunter
- RKHunter Baseline Datenbank erstellen
rkhunter --propupd
- nach Root-Kits suchen
rkhunter --check less /var/log/rkhunter.log
4.10 Intrusion Detection
4.10.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.10.2 AIDE
- Installation
apt install aide aide-common
- Konfiguration anschauen und ggf. ändern
$EDITOR /etc/aide/aide.conf
- 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 /etc/aide/aide.conf
4.10.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.
$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.11 Unter Debian Dienste nicht sofort nach der Installation starten
- Datei
/etc/systemd/system-preset/00-disable-all.preset
anlegen mit dem Inhalt
disable *
- Unter
/usr/sbin/policyd-rc.d
ein Shell Script erzeugen, welches Fehler #101 zurückliefert
# echo -e '#!/bin/bash\nexit 101' > /usr/sbin/policy-rc.d # chmod +x /usr/sbin/policy-rc.d # /usr/sbin/policy-rc.d # echo $? 101
4.12 CVE (Common Vulnerabilities and Exposures) RedHat
- CVE = eindeutige Kennzeichnung von Sicherheitslücken in Software
- Aufbau: CVE-<Jahr>-<Nummer>
- CVE Datenbank https://web.nvd.nist.gov/view/vuln/search
4.12.1 Common Vulnerability Scoring System (CVSS)
- Spezifikation: https://www.first.org/cvss/specification-document
- 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
- Access Vector (AV) - wie kann der Angreifer die Lücke ausnutzen
- 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
- Angriffs Vektor (AV)
4.13 Kernel Parameter
- Kernel Parameter können auf der Kernel-Kommando-Zeile im Bootloader angegeben werden, um Kernel-Funktionen zu steuern
4.13.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-Daemonauditd
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
4.13.2 AppArmor
apparmor=[0|1]
- AppArmor an/ausschalten
4.13.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
4.13.4 Signierte Module
module.sig_enforce
- wenn gesetzt, können nur Kernel-Module mit einer gültigen Signatur geladen werden
4.13.5 NOEXEC
noexec=[on|off]
- bei 32bit PAE Kerneln, schaltet Schreibschutz auf Daten-Speicherseiten an
4.13.6 Datei-Capabilities
no_file_caps
- Schaltet die Datei-Capabilities aus
4.13.7 Keine Module nachladen
nomodule
- es können keine Module nachgeladen werden
4.13.8 Kernel-Panic
panic=<timeout>
- Wert > 0 - Sekunden bis zum Reboot
- Wert = 0 - kein Reboot (* aus Sicherheitsgründen empfohlen)
- Wert < 0 - sofortiger Reboot
4.13.9 sysctl
- Übersicht-
sysctl
Parameter-Tuning: https://klaver.it/linux/sysctl.conf
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 Tag 5
5.1 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
- Der Linux-Kernel definiert Schnittstellen, in welche sich die
LSMs einklinken können:
- 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
5.1.1 Prüfen, welche LSMs im aktuell aktiven Linux-Kernel aktiv sind
# cat /sys/kernel/security/lsm lockdown,capability,yama,tomoyo,bpf
5.1.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
5.1.3 LoadPin
- LoadPin ist seit Kernel 4.7 Bestandteil von Linux
- LoadPin gewährleistet das alle Kernel-Daten (Module, Firmware-Blobs etc) vom gleichen, read-only Datei-System gelesen werden.
- LoadPin verhindert Angriffe auf den Kernel durch bösartige Kernel-Module (z.B. Root-Kits)
- Dokumentation: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/LSM/LoadPin.rst
5.1.4 SafeSetID
- Das SafeSetID Modul überwacht die Benutzung der SetUID/SetGID
Syscalls (UID oder GID eines Prozesses ändern, z.B. via
su
odersudo
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 Pfadsafesetid/uid_allowlist_policy
(für UID Übergänge) undsafesetid/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
5.1.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
, Kernelperf
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önnenconfidentiality
- Funktionen aus dem Modusintegrity
sind ausgeschaltet, plus Funktionen über welche sensible Daten aus dem Kernel ausgelesen werden können (z.B. Zugriffe auf/dev/mem
)
- Lockdown kann per Kernel-Commandozeile aktiviert werden: Parameter
- Lockdown LSM ist seit Kernel 5.4 verfügbar
- Lockdown Status ausgeben (hier
none
, Modiintegrity
undconfidentiality
sind möglich)# cat /sys/kernel/security/lockdown [none] integrity confidentiality
- Links
5.1.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
5.1.7 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.8 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
- Wie auch SELinux arbeitet SMACK auch mit Sicherheits-Label auf
Basis von erweiterten Attributen in den Linux-Dateisystemen
- SMACK Kernek Dokumentation
- Heise iX: SMACK im Linux Kernel
5.1.9 SELinux
- SELinux (Security-Enhanced Linux; engl. „sicherheitsverbessertes Linux“) ist eine Erweiterung des Linux-Kernels. Es implementiert die Zugriffskontrollen auf Ressourcen im Sinne von Mandatory Access Control. SELinux wurde von der NSA für eigene Bedürfnisse entwickelt und wird von dem Linux-Distributor Red Hat gepflegt.
- SELinux ist Open-Source-Software und setzt sich aus einem Kernel-Modul, Hilfsprogramme und aus zahlreichen Erweiterungen für Systemprogramme zusammen.
- Kernbestandteil von SELinux sind die Policies, welche sehr detailliert beschreiben, welche Zugriffe (Dateisystem, Syscalls, Netzwerk) einem Prozess oder einem Benutzer erlaubt sind.
- SELinux kann mit verschiedenen Policy-Einstellungen betrieben
werden:
full
- alle Ressourcen und Anwendungen im Linux-System sind von der SELinux Policy abgedeckt. Dies ist sehr aufwändig und wird von den Linux-Distributionen nicht angebotentargeted
- SELinux Policies existieren für kritische Komponenten im Linux-System (z.B. Systemd, Webserver, Mailserver etc). Nur diese Komponenten sind von SELinux abgesichert, alle anderen Komponenten befinden sich imunconfined
Modus und werden von SELinux nicht beschränkt. Die Linux-Distributionen bieten Policies für dentargeted
Modus an.
- SELinux erkunden
- wir arbeiten auf einer Rocky Linux VM im Internet. Benutzername
user
und Passwortvilla
, Benutzerroot
kann durchsudo
erreicht werden - 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
- wir arbeiten auf einer Rocky Linux VM im Internet. Benutzername
- Ein Problem für SELinux erzeugen und bereinigen
index-html
Datei im Verzeichnis des Benutzersroot
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
- SELinux und Benutzer
- Benutzer
user
in die Benutzerklasseuser_u
einfügen
semanage login -l semanage user -l semanage login -a -s user_u user # su oder sudo sollten nun für den Benutzer nicht mehr möglich sein cat /etc/selinux/targeted/seusers semanage login -a -s guest_u user getsebool allow_guest_exec_content setsebool allow_guest_exec_content off # scripts sind nun nicht mehr direkt ausführbar (indirekt über BASH oder SH funktioniert es trotzdem)
- Fehlersuche bei SELinux Problemen
ausearch -m avc -ts recent
- Benutzer
- Aufgabe: Apache auf einem anderen Port als 80 oder 443
- Schritte auf der VM ausführen
- Ändere die Apache Konfiguration unter
/etc/httpd/conf/httpd.conf
so das der Apache auf Port 1235/TCP auf HTTP-Anfragen horcht (KonfigurationsparameterListen: 1235
) - Versuche den Apache Webserver mittels systemd neu zu starten
(
systemctl restart httpd
). Dies wird fehlschlagen, dahttpd
sich nicht auf Port 1235 binden kann. - Schaue in per
ausearch
in die Audit-Logdatei nach SELinux Fehlern des Prozesseshttpd
- Benutze den Befehl
semanage port
um den Port1234
für den Prozesshttpd
im SELinux freizuschalten und starte den Apache Webserver neu. - Teste, on der Firefox-Browser unter der URL http://selinuxNNN.dnslab.org:1235/ die Webseite des Webservers sehen kann.
- Beispiellösung
- Apache Konfiguration bearbeiten
$EDITOR /etc/httpd/conf/httpd.conf
- Apache Prozess neu starten. Dies sollte fehlschlagen, da SELinux die
Benutzung von Port 1235 für den Prozess
httpd
verbietet - SELinux Fehler für
httpd
im Audit-Log suchen
ausearch -m avc -c httpd -ts recent -i
- Port 1235 für Apache in der SELinux Richtlinie freischalten
semanage port -m -t http_port_t -p tcp 1235
- Apache Webserver neu starten
systemctl restart httpd
- Änderungen mit
semanage
sind persistent, die Port-Änderung ist unter/etc/selinux/targeted/active/ports.local
abgespeichert:
# This file is auto-generated by libsemanage # Do not edit directly. portcon tcp 1235 system_u:object_r:http_port_t:s0
5.1.10 AppArmor
- AppArmor ist bei Debian 11 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
- AppArmor Anleitung
- Installation weiterer AppArmor Tools
apt install apparmor apparmor-profiles apparmor-utils
- AppArmor Status prüfen
aa-status
- AppArmor Profil für ein Programm anschauen. Dokumentation der AppArmor Profil-Definition https://gitlab.com/apparmor/apparmor/-/wikis/AppArmor_Core_Policy_Reference
less /etc/apparmor.d/bin.ping
- Änderungen am Profil für
ping
, dasping
Programm sollte danach keine ICMP(v6) Pakete versenden können
$EDITOR /etc/apparmor.d/bin.ping --- [...] #include <abstractions/nameservice> # capability net_raw, # capability setuid, network inet raw, [...]
- Profil neu laden
apparmor_parser -r /etc/apparmor.d/bin.ping
- Enforce-Modus für ein Programm setzen
# aa-enforce /etc/apparmor.d/bin.ping Setting /etc/apparmor.d/bin.ping to enforce mode.
- Test des
ping
Programms:
# ping 8.8.8.8 ping: socket: Die Operation ist nicht erlaubt # ping fe80::3e97:eff:feeb:a358%enp0s25 ping: socket: Die Operation ist nicht erlaubt
(Achtung: Wenn firejail installiert ist, ist /usr/bin/ping ein Symlink zu firejail)
- Complain-Modus für ein Programm setzen
aa-complain /etc/apparmor.d/bin.ping Setting /etc/apparmor.d/bin.ping to complain mode.
- gestartete Programme ohne AppArmor Profil listen
# aa-unconfined 622 /usr/sbin/NetworkManager not confined 623 /usr/sbin/cupsd confined by '/usr/sbin/cupsd (enforce)' 630 /usr/sbin/avahi-daemon confined by '/usr/sbin/avahi-daemon (complain)' 650 /usr/sbin/cups-browsed confined by '/usr/sbin/cups-browsed (enforce)' 698 /usr/sbin/sshd not confined 1250 /usr/sbin/minissdpd not confined 1504 /usr/sbin/exim4 not confined 2013 /sbin/dhclient not confined
- AppArmor Profil-Vorlage automatisiert erstellen. Die Vorlage muss
immer manuell nachgearbeitet werden. (Aufgrund des Debian-Fehlers
in Debian 10, siehe
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=928160,
funktioniert
aa-genprof
nicht, wenn das Paketapparmor-profiles
installiert ist. Umaa-genprof
zu benutzen erst dieses Paket deinstallierenapt remove apparmor-profiles
und dannaa-genprof
benutzen).
aa-genprof <programm>
- AppArmor Aufgabe
- Entferne (auskommentieren) aus dem AppArmor-Profil für “ping” die
Capability
net_raw
- Starte AppArmor neu
systemctl restart apparmor
- Setze
ping
in dencomplain
Modus. Prüfe mitaa-status
- Protokolliere das Audit-Log
tail -f /var/log/audit/audit.log
- Benutze den
ping
Befehl. Derping
Befehl sollte funktionieren, aber im Audit-Log vermerkt sein - Setze
ping
in denenforce
Modus - Benutze den
ping
Befehl. Derping
Befehl sollte nicht funktionieren, im Audit-Log wird dieser Event registriert - Benutze den interaktiven Assistenten, um Policies zu erweitern:
aa-logprof -f <(cat /var/log/audit/audit.log) #ggfs. log noch greppen
- Entferne (auskommentieren) aus dem AppArmor-Profil für “ping” die
Capability
5.2 Logdateien auswerten
- Artificial Ignorance: bei diesem von Marcus Ranum beschriebenen
Konzept werden Filter aufgebaut durch welche die Log-Ausgaben
gefiltert werden. Log-Ausgaben werden in zwei Kategorien
eingeteilt:
- Meldung beschreibt eine kritische Fehlfunktion im System. Die Ursache der Fehlfunktion muss beseitigt werden, damit die Log-Ausgaben nicht mehr angezeigt werden
- Meldung beschreibt eine unkritische Situation im System. Die Filter werden erweitert, um die Log-Meldung in Zukunft zu unterdrücken
Ziel von AI-Logauswertung ist es, das die Log-Dateien nach dem Filtern leer sind. Alle neuen Log-Meldungen, welche in den Log-Dateien auftauchen, müssen entweder bereinigt werden oder durch einen Filter unterdrückt werden: http://www.ranum.com/security/computer_security/papers/ai/
5.2.1 Log-Templater
- Log-Templater ist eine Software zur Implementation von AI-Logauswertung
- Log-Templater installieren
mkdir ~/src cd ~/src apt -y install git build-essential automake autoconf git clone https://github.com/rondilley/tmpltr.git cd tmpltr ./bootstrap autoreconf -i ./configure make make install
- Systemd-Journal für den Dienst
sshd
mit tmpltr auswerten
journalctl -u ssh | tmpltr - | sort -n | sed -e 's/%s.*||//'
- Templates abspeichern, dann ignore Datei bearbeiten
journalctl -u ssh | tmpltr -w /var/log/ssh.ignore -
- Log mit ignore Datei auswerten
journalctl -u ssh | tmpltr -t /var/log/ssh.ignore - | sort -n | sed -e 's/%s.*||//'
- SSH-Fehler produzieren (z.B. Anmeldeversuch mit falschem Passwort) und Log-Datei neu auswerten
ssh bar@localhost bar@localhost's password: Permission denied, please try again. bar@localhost's password:
- Log-Auswerten
[bar@notebook32 tmpltr]# journalctl -u sshd | tmpltr -t /var/log/sshd.ignore - | sort -n | sed -e 's/%s.*||//' Opening [-] for read 1 Aug 31 12:29:25 notebook32 sshd[24691]: Connection closed by ::1 port 40372 [preauth] 1 Aug 31 12:29:25 notebook32 sshd[24691]: Failed password for bar from ::1 port 40372 ssh2 1 Aug 31 12:29:23 notebook32 sshd[24691]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "bar" 1 Aug 31 12:29:23 notebook32 sshd[24691]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=localhost user=bar
- Neue Log-Einträge in die Ignore-Datei aufnehmen
journalctl -u sshd | tmpltr -t /var/log/sshd.ignore -w /var/log/sshd.ignore.new - && \ cat /var/log/sshd.ignore.new >> /var/log/sshd.ignore
5.2.2 Greylog (Open Source)
5.2.3 Splunk (Kommerziell)
5.3 Dateisystem-Verschlüsselung
5.3.1 ext4 mit Verschlüsselung
- ACHTUNG: unter Debian 9 nicht die Boot-Partition mit
ext4-Verschlüsselung betreiben. Der von Debian 9 benutzte Boot-Loader
GRUB2 kann noch nicht von ext4 Dateisystemen mit Verschlüsselung booten
- https://lwn.net/Articles/639427/
- Installation der Linux Key-Utilities:
apt install keyutils
- Die Volume-Partition
/dev/sda4
mitext4
formatieren (mit 4096 Byte Blöcken!)mkfs.ext4 -b 4096 /dev/sda4
- Die
ext4
Funktion “Verschlüsselung” im Dateisystem auf/dev/sda4
anschaltentune2fs -O encrypt /dev/sda4
- Volume
/dev/sda4
unter/encrypted
einhängenmkdir /encrypted mount /dev/sda4 /encrypted
- einen neuen Schlüssel dem Linux-Session-Keyring hinzufügen und dem
Verzeichnis
/encrypted/test
zuordnenmkdir /encrypted/test e4crypt add_key /encrypted/test keyctl show
- Daten in das verschlüsselte Verzeichnis kopieren und die
erweiterten BSD-Attribute der Dateien anzeigen. Es sollten die
Attribute
---------E----e---- /encrypted/test/passwd
erscheinen (E = encrypted, c = komprimiert, siehe auchman chattr
)cp /etc/passwd /encrypted/test lsattr /encrypted/test
5.3.2 dmcrypt/LUKS
- LUKS Tools und LVM installieren
apt install cryptsetup lvm2
- Neues Physisches Volume in
/dev/sda5
erstellen
# pvcreate /dev/sda5 Physical volume "/dev/sda5" successfully created.
- Eine neue Volumegroup erstellen
# vgcreate crypt_vg /dev/sda5 Volume group "crypt_vg" successfully created
- ein neues logisches Volume im LVM erstellen (in der Volumegroup
crypt_vg
):
lvcreate --size 500M --name crypt crypt_vg
- Ein verschlüsseltes Laufwerk auf dem LV erstellen
cryptsetup --verbose --verify-passphrase luksFormat \ /dev/mapper/crypt_vg-crypt
- Das verschlüsselte Laufwerk im Linux-Device-Mapper anmelden
cryptsetup luksOpen /dev/mapper/crypt_vg-crypt crypt
- An dieser Stelle muss das neue Laufwerk nun im Device-Mapper auftauchen
ls -l /dev/mapper/crypt
- Das ’crypt’ Laufwerk formatieren (hier ext4, andere Dateisysteme und SWAP sind möglich)
mkfs.ext4 /dev/mapper/crypt
- Ein leeres Verzeichnis anlegen und das neue Dateisystem dort mounten:
mkdir /crypt mount /dev/mapper/crypt /crypt
- Das Dateisystem auf dem verschlüsselten Laufwerk mit Test-Daten füllen
# cp -a /etc /crypt/
- Konfigurationsdatei für verschlüsselte Laufwerke anlegen
$EDITOR /etc/crypttab
- Eintrag für unser verschlüsseltes Laufwerk
crypt /dev/mapper/crypt_vg-crypt none luks,timeout=180
- Eintrag in der
/etc/fstab
/dev/mapper/crypt /crypt ext4 defaults 0 0
- Partition in der
/etc/fstab
eintragen, Reboot testen
5.4 Secret Sharing
- Shamir’s Secret Sharing Scheme http://point-at-infinity.org/ssss/
- ssss installieren
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 APT Updates automatisieren
- nach der Installation sind die automatischen Updates angeschaltet. Die
Konfiguration der automatischen Updates findet sich unter
/etc/apt/apt.conf.d/50unattended
:
apt-get install unattended-upgrades apt-listchanges $EDITOR /etc/apt/apt.conf.d/50unattended-upgrades ---- Unattended-Upgrade::Mail "root"; Unattended-Upgrade::Automatic-Reboot-Time "02:00"; Unattended-Upgrade::Automatic-Reboot "false"; Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
- automatische Updates können über den Schalter
APT::Periodic::Unattended-Upgrade
in der Datei/etc/apt/apt.conf.d/20auto-upgrades
an- bzw. ausgeschaltet werden.
5.6 Antivirus
5.6.1 ClamAV
- ClamAV installieren
apt install clamav clamav-daemon clamav-base clamav-freshclam
- Ist SELinux aktiviert (z.B. Rocky/Alma/Fedora/CentOS/Red Hat), muss einen Antivirus-Scan im SELinux zulassen werden
setsebool -P antivirus_can_scan_system 1 setsebool -P clamd_use_jit on
- FreshClam Konfiguration pruefen, Option
DatabaseMirror
vondb.local.clamav.net
aufdb.de.clamav.net
ändern, dann den FreshClam Dienst neu starten
$EDITOR /etc/clamav/freshclam.conf systemctl restart clamav-freshclam
- Im Journal nach Meldungen schauen
journalctl -u clamav-freshclam
- Wurde FreshClam ohne Fehler gestartet?
systemctl status clamav-freshclam
- Beispiel: Virensignaturen erfolgreich geladen
[root@notebook33 src]# systemctl status clamav-freshclam freshclam.service - freshclam update ClamAV databases Loaded: loaded (/etc/systemd/system/freshclam.service; enabled) Active: inactive (dead) since Wed 2015-11-25 14:59:35 CET; 1min 2s ago Process: 28088 ExecStart=/usr/bin/freshclam -c 12 (code=exited, status=0/SUCCESS) Main PID: 28088 (code=exited, status=0/SUCCESS) Nov 25 14:59:20 notebook33 freshclam[28088]: Downloading daily.cvd [100%] Nov 25 14:59:21 notebook33 freshclam[28088]: [440B blob data] Nov 25 14:59:29 notebook33 freshclam[28088]: daily.cvd updated (version: 21096, sigs: 1700789, f-level: 63, builder: neo) Nov 25 14:59:29 notebook33 freshclam[28088]: daily.cvd updated (version: 21096, sigs: 1700789, f-level: 63, builder: neo) Nov 25 14:59:29 notebook33 freshclam[28088]: [293B blob data] Nov 25 14:59:29 notebook33 freshclam[28088]: Downloading bytecode.cvd [100%] Nov 25 14:59:30 notebook33 freshclam[28088]: bytecode.cvd updated (version: 270, sigs: 46, f-level: 63, builder: shurley) Nov 25 14:59:30 notebook33 freshclam[28088]: bytecode.cvd updated (version: 270, sigs: 46, f-level: 63, builder: shurley) Nov 25 14:59:35 notebook33 freshclam[28088]: Database updated (4125060 signatures) from database.clamav.net (IP: 62.201.161.84) Nov 25 14:59:35 notebook33 freshclam[28088]: Database updated (4125060 signatures) from database.clamav.net (IP: 62.201.161.84)
- ClamAV Konfiguration prüfen
clamconf | less
- Manueller Scan (im Vordergrund)
clamscan -vr /usr
- EICAR Test-Virus in einem Heimverzeichnis erstellen, Heimverzeichnisse scannen (per Clam-Daemon)
echo -n 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' \ > /home/nutzerXX/eicar.com clamscan -vr /home
- ClamAV Daemon starten
systemctl start clamav-daemon
- Clam-Daemon Auslastung überwachen
clamdtop
- Auf Virenfunde reagieren, in der Datei
/etc/clamav/virusevent.d/
ein Shellskript anlegen#!/bin/sh logger -t virus "Signature detected: $CLAM_VIRUSEVENT_VIRUSNAME in $CLAM_VIRUSEVENT_FILENAME"
- Shell Skript ausführbar machen
- und in der Datei
/etc/clamav/clamd.conf
eintragenVirusEvent /etc/clamav/virusevent.d/log-virus
5.7 Netzzwerksicherheit
5.7.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.8 BIOS/UEFI Sicherheit
5.8.1 TODO SMT (Meltdown/Spectre etc)
- Erklärung der Meltdown-Sicherheitslücke von Cyberus, offizielle Mit-Entdecker von Meltdown: https://www.cyberus-technology.de/posts/meltdown/
5.8.2 Intel Management Engine (ME)
- Wikipedia “Intel Management Engine” https://en.wikipedia.org/wiki/Intel_Management_Engine
- BSI warnt vor Risiko bei Intels Fernwartungstechnik AMT http://www.heise.de/newsticker/meldung/BSI-warnt-vor-Risiko-bei-Intels-Fernwartungstechnik-AMT-2792791.html
- Secret of Intel Management Engine by Igor Skochinsky http://de.slideshare.net/codeblue_jp/igor-skochinsky-enpub
- ME-Blockade - Linux-Tüftler schalten Intels Management Engine aus https://www.heise.de/ct/ausgabe/2017-4-Linux-Tueftler-schalten-Intels-Management-Engine-aus-3612223.html
- Intel-ME-Sicherheitslücke: Erste Produktliste, noch keine Updates https://www.heise.de/security/meldung/Intel-ME-Sicherheitsluecke-Erste-Produktliste-noch-keine-Updates-3703356.html
- Intel-Fernwartung AMT bei Angriffen auf PCs genutzt https://www.heise.de/security/meldung/Intel-Fernwartung-AMT-bei-Angriffen-auf-PCs-genutzt-3739441.html
5.8.3 Coreboot/Libreboot
Coreboot ist eine freie (open source) Firmware für Intel und ARM Rechner. Coreboot hiess früher LinuxBIOS.
5.9 SELinux - Policy Development
- Für dieses Kapitel arbeiten wir auf dem VM Maschinen
- Andere Web-Server (Apache/NGINX etc) auf der VM stoppen
- Für die Dauer dieser Übung die Firewall auf der VM deaktivieren
systemctl stop firewalld
5.9.1 SELinux Policy erweitern - Ein simpler HTTP-Server
- Schöne Erklärung:
https://debian-handbook.info/browse/de-DE/stable/sect.selinux.html
- C-Compiler installieren
dnf install gcc
- Pakete für die SELinux Policy-Entwicklung installieren
dnf install policycoreutils-python3 selinux-policy-devel
- 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 simple-server1.c
- Installieren
cp simple-server /usr/local/bin
- Server starten, 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
- `.te` (type enforcing) legt die Regeln fest
- `.fc` (file contexts) bestimmt die „Dateikontexte“ (Typen, die den auf diese Module bezogenen Dateien zugeordnet sind)
- `.if` (interfaces) Schnittstelle der Module: Satz „öffentlicher Funktionen“, die andere Module verwenden können
- `.spec` RPM Spec Datei fuer spaetere Pakete
- `.sh` Helfer-Shellscript, das Regel-Kompilation, Installation und Label-fixes automatisiert
- 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
5.9.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 dessimple-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"); + fflush(f); 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.10 DNSSEC DNS-Resolver
- Installation des Unbound DNS-Resolvers und des DNS-Kommandozeilen
Werkzeuge
dig
unter Debian
apt install unbound dnsutils
- DNSSEC Auflösung und Validierung testen
dig @localhost dnssec.works a
- DNSSEC Signaturen anzeigen (
+dnssec
) und Ausgabe auf 80-Zeichen formatieren (+multi
)
dig @localhost dnssec.works a +dnssec +multi
- DNSSEC defekte Domains geben den Status
SERVFAIL
zurück.SERVFAIL
kann aber auch andere Gründe (Serverfehler, Konfigurationsfehler) haben
dig @localhost fail01.dnssec.works a +dnssec +multi
- der Schalter
+cd
(Checking Disabled) setzt die DNSSEC Validierung des DNS-Resovlers für eine Anfrage ausser Kraft; die fehlerhaften Daten werden angezeigt
dig @localhost fail01.dnssec.works a +dnssec +multi +cd
- Um den neuen DNS Resolver auf dem System für alle Anwendungen
verfügbar zu machen, die loopback Addresse (IPv6 oder IPv4) in der
Datei
/etc/resolv.conf
an der ersten Stelle eintragen. - Online-Webseiten um DNS- und DNSSEC-Fehler zu finden