wenn's mal hakt
schreckliches beispiel: man verwendet irgendein blödes paket, das irgendwer auf der basis alter bibs gebaut hat (xephem-drama vom 10.09.2005). dann stell man fest, dass das upgrade auf die neuesten bibs nur zum teil ausgeführt wird. apt-get kann auch mit den ausgeklügelsten optionen nichts machen. lösung:
dpkg -r xephem
danach
apt-get -f install
repariert alles, versucht's zumindest.
fremdhandbuch
(c)Fabian Portmann - www.chupame.ch
(c)GFDL - www.gnu.org/licenses/fdl.html
Debian Paketverwaltung
======================
dpkg
----
dpkg -i package.deb Installiert ein Paket.
dpkg -r package.deb Löscht ein Packet, behält jedoch die
config-dateien.
dpkg -P package.deb Löscht ein Paket gänzlich.
dpkg -l Listet Pakete auf(/var/lib/dpkg/available)
dpkg-reconfigure Rekonfiguriert ein Paket.
dpkg --get-selections > out.txt Gibt Status der installierten Pakete an.
dpkg --set-selections < out.txt Stellt die Liste der installierten Pakete
wieder her. (z.B. auf einem anderen Rechner)
apt
---
apt-get dselect-upgrade Installiert die eben eingelesene Auswahl.
apt-setup basic setup von apt.
apt-get update lädt paketlisten von den quellen in
/etc/apt/sources.list herunter.
apt-get install installiert paket.(mit deps checking usw.)
apt-get remove
apt-get upgrade aktualisiert die installierten pakete.
apt-get dist-upgrade aktualisiert die ganze distro. löscht also
evt. pakete und installiert neue.
apt-get clean Löscht runtergeladene .deb files aus
/var/cache/apt/archives.
apt-get autoclean Löscht alte Pakete die in den Listen nicht
mehr vorkommen.
apt-get check Checkt dependencies.
apt-get dselect-upgrade Macht die Änderungen, die von dselect aus
gemacht wurden.
frontends
---------
aptitude
dselect
apt-setup
sources.list Beispiel
---------------------
#
# /etc/apt/sources.list
#
#
# sources.list file for the Debian GNU/Linux testing distribution.
#
#
# testing debian -> Debian testing pakete
# testing debian-non-US -> Debian testing non-US pakete
# testing debian-security -> Debian testing security updates
# testing debian-security-non-US -> Debian testing security-non-US updates
#
# testing debian
deb http://sunsite.cnlab-switch.ch/ftp/mirror/debian testing main contrib non-free
# testing debian-non-US
deb http://sunsite.cnlab-switch.ch/ftp/mirror/debian-non-US testing/non-US main contrib non-free
# testing debian-security
deb ftp://security.debian.org/debian-security testing/updates main contrib non-free
# testing security-non-US
deb ftp://security.debian.org/debian-non-US testing/non-US main contrib non-free
#
# EOF
#
(c)Fabian Portmann - www.chupame.ch
(c)GFDL - www.gnu.org/licenses/fdl.html
Debian GNU/Linux Hardening
==========================
Ein Beispiel dafür wie man die Debian-Distribution sicherer machen kann.
...unvollständig.
Installation
============
Quellmedium
-----------
Als Quellmedium für die Installation wird Debian 3.0r2 (latest) in CD-ROM-Form
benutzt. Dies ist sicherer als die Pakete direkt von Internet herunterzuladen.
Partitionierung
---------------
Nach den Standardeingaben wie Tastaturbelegung oder Sprache, kommt das
Partitionieren der Festplatte.
Beispielpartionierung:
/dev/hda1
/dev/hda2
/dev/hda3 250mb
/dev/hda5 /boot 100mb ext3
/dev/hda6 / 1000mb ext3
/dev/hda7 /usr 1250mb ext3
/dev/hda8 /var 500mb ext3
/dev/hda9 /home 500mb ext3
/dev/hda10 /tmp 500mb ext3
Netzwerkkonfiguration
---------------------
Hostname: 350z
Domainname: chupame.int
IP / Netzmaske: 192.168.0.125 / 255.255.255.0
Gateway: 192.168.0.13
DNS-Server: 192.168.0.15
Das statische Eintragen des Host- bzw. Domainnamens, der IP, des Gatways und
des DNS-Servers ist deshalb wichtig, weil so eine "man in the middle"-Attacke
eingeschränkt werden kann.
Weitere Konfigurationsschritte
------------------------------
LiLo - der Linux Loader, wird in den MBR geschrieben und nachträglich gegen
lokale Attacken abgesichert.
Nach dem Schreiben von LiLo in den MBR wird das System neu gebootet und die
CD-ROM entfernt. Danach werden bis zum ersten Login weitere
Konfigurationsschritte unternommen, welche immer noch zur Installation gehören:
- Passwörter werden in md5-Form(verschlüsselt) in der Datei /etc/shadow
gespeichert.
- Es wird ein neuer Benutzer "admin" angelegt, welcher alle Systemrelevanten
Informationen gemailt bekommt. Dazu sollte nur er und Benutzer in der
Gruppe "wheel" spezielle Berechtigungen erhalten, wie z.B. den Befehl "su"
auszuführen, oder das System runterzufahren.
Das Mailsystem(exim) wird vorläufig so konfiguriert, dass nur das lokale
Versenden von mails funktioniert:
MTA: exim
Konfiguration: local delivery only
Standardmail an: admin
Mailname: @350z.chupame.int
Die Installation ist nun abgeschlossen und es kann als root" eingeloggt werden.
Hardening
=========
Firewall
--------
Gleich nach der Installation wird eine sehr restriktive Firewall gestartet,
welche zum jetzigen Zeitpunkt einen ziemlich hohen Schutz bietet. Dies wird
_vor_ dem Einspielen von Security-Updates und zusätzlichen Paketen aus dem
Internet gemacht. Das iptables-Script hat grundlegend folgende Konfiguration:
Erlaubte ausgehende Verbindungen: TCP Ports 80 und 21. Port 53 UDP.
Erlaubte eingehende Verbindungen: related
Wichtig ist, dass die Firewall beim booten _vor_ den Netzwerkdiensten
gestartet, und beim Runterfahren _nach_ den Netzwerkdiensten gestoppt wird.
root# /etc/init.d/firewall start
Starting Firewall...done
root# cd /etc/rc0.d/
root# ln -s ../init.d/firewall K88firewall
root# cd /etc/rc1.d/
root# ln -s ../init.d/firewall K88firewall
root# cd /etc/rc2.d/
root# ln -s ../init.d/firewall S13firwall
root# cd /etc/rc3.d/
root# ln -s ../init.d/firewall S13firwall
root# cd /etc/rc4.d/
root# ln -s ../init.d/firewall S13firwall
root# cd /etc/rc5.d/
root# ln -s ../init.d/firewall S13firwall
root# cd /etc/rc6.d/
root# ln -s ../init.d/firewall K88firewall
Security-Updates
----------------
Als nächstes werden Security-Updates eingespielt. Dazu muss die Datei, welche
die Quellen der Pakete beinhaltet wie folgt aussehen:
root# vi /etc/apt/sources.list
deb ftp://security.debian.org/debian-security stable/updates main contrib non-free
deb ftp://security.debian.org/debian-non-US stable/non-US main contrib non-free
root# apt-get update
root# apt-get upgrade
Zusätzliche Pakete
------------------
Jetzt werden alle wichtigen Pakete mit "dselect" installiert. Dazu müssen noch
die Sourcen eines Debian-Spiegels in "/etc/apt/sources.list" eingetragen
werden.
root# vi /etc/apt/sources.list
deb ftp://security.debian.org/debian-security stable/updates main contrib non-free
deb ftp://security.debian.org/debian-non-US stable/non-US main contrib non-free
deb http://sunsite.cnlab-switch.ch/ftp/mirror/debian stable main contrib non-free
deb http://sunsite.cnlab-switch.ch/ftp/mirror/debian-non-US stable/non-US main contrib non-free
root# dselect
root# dselect -> 1. [U]pdate
root# dselect -> 2. [S]elect
root# dselect -> 3. [I]nstall
root# dselect -> 6. [Q]uit
Danach sind so genannte "important packages" wie z.B. "klogd" oder "cron"
installiert.
Pakete deinstallieren
---------------------
Pakete, die nicht gebraucht werden, sollten deinstalliert werden, denn sie
stellen immer eine potenzielle Sicherheitslücke dar. Dies gilt besonders für
Netzwerkpakete.
root# apt-get remove --purge ipchains setserial ed nano nvi cpio ftp rcs doc-debian doc-linux-text biff mpack mutt procmail vacation bc dc finger ipmasqadm lpr mime-support mtr-tiny nfs-common nfs-kernel-server pidentd portmap telnet mtools tcsh iamerican ienglish ispell wenglish dpkg-dev gnupg reportbug shareutils lynx base-config fdutils ppp pppconfig tasksel dhcp-client pppoe pppoeconf syslinux
Diese Pakete sind jetzt zwar deinstalliert, jedoch blieben trotz dem "--purge"
einige init-scripts auf der Platte:
root# update-rc.d -f lpd remove
root# update-rc.d -f ppp remove
root# update-rc.d -f nviboot remove
root# update-rc.d -f nfs-common remove
root# update-rc.d -f nfs-kernel-server remove
root# update-rc.d -f portmap remove
root# update-rc.d -f setserial remove
root# update-rc.d -f mountnfs.sh remove
root# update-rc.d -f umountnfs.sh remove
BIOS
----
Die Maschine wird jetzt neu gestartet. Vor dem starten wird das BIOS so
konfiguriert, dass nur das booten von Festplatte erlaubt ist und ein Passwort
benötigt wird um diese Einstellungen zu ändern.
Nach dem erfolgreichem Neustart und Login wird das Netzwerk präventiv
angehalten. In den nächsten Schritten werden keine hardening-Prozesse
angewendet, die Netzwerkfähigkeit voraussetzen.
root# rcnetworking stop
Benutzerumgebung
----------------
Die Benutzerumgebung sollte möglichst sicher sein. Werden Dateien angelegt,
sollten sie die Berechtigung -rw------- haben und nicht standardmässig
-rw-r--r--. Ich erhöhe ausserdem auch die Anzahl der eingegebenen Befehle,
die in der "History" gespeichert werden auf 100'000.
root# jed /etc/profile
#Eine umask von 077 bedeutet, dass Dateien mit den Berechtigungen
#0600 angelegt werden.
umask 077
#Die History-Datei
HISTFILE=~/.bash_history
#Die Anzahl Befehle, die in der Hiostory gespeichert werden
HISTSIZE=100000
#Die Grösse der History Datei $HISTFILE (1GB?) evt. 1000000
HISTFILESIZE=1000000000
#Damit die oben genannten Variablen nicht mit "unset" überschrieben
#werden können, mache ich sie "readonly".
readonly HISTFILE
readonly HISTSIZE
readonly HISTFILESIZE
export HISTFILE HISTSIZE HISTFILESIZE
Diese Massnahme schützt aber nicht vor Benutzern, welche die "History" mit
"history -c" oder "pidof bash | xargs kill -9" löschen können. Deshalb setzte
ich später ein Tool namens "snoopy" ein, um jeden ausgeführten Befehl auf dem
System zu protokollieren.
Präventiv werden auch "aliases" gesetzt, die vor ungewolltem Überschreiben von
Daten schützen. Dateien und Verzeichnisse etc. sollten auch unterschiedliche
Farben auf der shell haben, damit diese unterschieden werden können.
root# jed ~/.bashrc
#Einige Variablen, die ein sichereres und schöneres environment
#ermöglichen.
umask 077
export PS1='\h:\w\$ '
export LS_OPTIONS='--color=auto'
eval dircolors
alias ls='ls $LS_OPTIONS'
alias ll='ls $LS_OPTIONS -l'
alias l='ls $LS_OPTIONS -lA'
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
Cron
----
Damit nicht jeder "cron" benutzen kann, wird "cron" für jeden ausser "root"
verboten:
root# echo root > /etc/cron.allow
root# su - admin
admin@350z:~$ crontab -e
You (admin) are not allowed to use this program (crontab)
See crontab(1) for more information
Shutdown
--------
Auch der "shutdown" des Systems mit ++ kann nur getätigt
werden, wenn "admin" eingeloggt ist.
root# jed /etc/inittab
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
Das "-a" muss unbedingt dabei sein, damit gibt man "shutdown" die Anweisung
"/etc/shutdown.allow" zu lesen.
root# echo admin > /etc/shutdown.allow
root# exit
testuser@350z:~$ < ctrl > + < alt > + < del >
shutdown: no authorized users logged in.
Systembenutzer
--------------
Systembenutzer wie "daemon" oder "bin" brauchen keine echte "shell".
Deshalb wird "/bin/sh" in "/etc/passwd" durch "/bin/false" ersetzt.
Loginmeldungen und Banner
-------------------------
Loginmeldungen und Banner verraten Informationen über das System, die einem
Angreifer helfen können. Also deaktiviere ich diese, indem ich den
ursprünglichen Text in "/etc/motd" lösche. Diese Datei sollte auch bei einem
Reboot nicht neu generiert werden.
root# > /etc/motd
root# jed /etc/default/rcS
EDITMOTD=no
"tput clear" fügt ein "clear" in die angegeben Datei. Wenn jetzt also lokal
oder übers Netzwerk einloggt wird, kriegt man als Banner ein "clear" - sprich
ein leerer Bildschirm.
root# tput clear > /etc/issue; tput clear > /etc/issue.net
Dateisystemberechtigungen
-------------------------
Einige Berechtigungen sind unsicher und sollten wie folgt geändert werden:
root# chmod 0700 /home/admin
root# chmod 0700 /root
Jetzt kann nicht jeder in das Heimatsverzeichnis von root wechseln!
Das ganze Verzeichnis "/usr/local" gehört der Gruppe "staff" und hat das
"sgid"-Bit gesetzt. Wenn jetzt also eine Datei in diesem Verzeichnis angelegt
wird, gehört es automatisch der soeben genannten Gruppe. Das ist unsinnig und
wird verbessert:
root# chown -R root. /usr/local
root# chmod -R a-s /usr/local
Weitere "Fehler" mit Berechtigungen werden behoben:
root# cd /usr/
root# find -perm 0775 -exec chmod 0755 {} \;
root# chown root. /home
root# chmod a-s /home
root# chmod 0755 /home
root# chown root. /usr/src
root# chmod 0755 /usr/src
Benutzereinstellungen
---------------------
Einige Einstellungen, die angewendet werden, wenn ein neuer Benutzer angelegt
wird, sollten editiert werden.
Das Verzeichnis "/etc/skel" enthält Standarddateien, die ein Benutzer in seinem
Heimatsverzeichnis hat.
root# jed /etc/skel/.bash_profile
umask 077
Wenn ein neuer Benutzer angelegt wird, wird sein Heimatsverzeichnis
standardmässig mir den Berechtigungen 0755 angelegt, was bedeutet, dass jeder
andere Benutzer in sein Heimatsverzeichnis wechseln darf. Dies wird abgeändert:
root# jed /etc/adduser.conf
DIR_MODE=0700
Security-Check
--------------
Debian mach täglich per "cron" einen allgemeinen Sicherheitscheck. Die Ausgabe
dieses Scripts sollte an "admin" gemailt werden:
root# jed /etc/checksecurity.conf
CHECKSECURITY_EMAIL="admin"
Dateisystem
-----------
Partitionen können auf viele verschiedene Wege eingebunden werden. Ich binde
sie sicher ein, ohne dass der Komfort leidet:
root# jed /etc/fstab
/dev/hda3 none swap sw 0 0
/dev/hda5 /boot ext3 noauto,noatime 0 2
/dev/hda6 / ext3 noatime,errors=remount-ro 0 1
/dev/hda7 /usr ext3 noatime,nodev,ro 0 2
/dev/hda8 /var ext3 noatime,nodev 0 2
/dev/hda9 /home ext3 noatime,nodev,nosuid,noexec 0 2
/dev/hda10 /tmp ext3 noatime,nodev,nosuid,noexec 0 2
proc /proc proc defaults 0 0
Die Option "noauto" bedeutet, dass die Partition nicht automatisch eingebunden
wird. Durch "noatime" wird beim Lesen der Inode-Accesstime nicht auf das
Dateisystem geschrieben. Dadurch sollte das System schneller laufen. "nodev"
bedeutet, dass keine "character"- bzw "block"-devices angelegt oder gesehen
werden können. Bei "noexec" kann auf der betroffenen Partition keine Datei
ausgeführt werden. "nosuid" bewirkt, dass das "suid"-Bit nicht gültig ist und
"ro" heisst "read-only".
Danach muss neu gebootet werden.
Limiten
-------
Das System wird grundsätzlich als Multi-User System mit anonymen Zugriff
konfiguriert. Einige Veränderungen:
root# jed /etc/login.defs
# Anzeigen von unbekannten Benutzernamen wenn Login-Fehler
# aufgezeichnet werden.
LOG_UNKFAIL_ENAB yes
# Aufzeichnen von erfolgreichen Logins aktivieren.
LOG_OK_LOGINS yes
# Alle "su-Aktivitäten" in folgende Datei schreiben.
SULOG_FILE /var/log/sulog
# Eine standard-umask von 077 setzen.
UMASK 077
# Maximale Anzahl Tage, um das gleiche Passwort zu benutzen.
PASS_MAX_DAYS 30
# Der Login wird verboten, wenn nicht in das Heimatsverzeichnis
# gewechselt werden kann.
DEFAULT_HOME no
# Deaktiviert das anzeigen von "*" bei der Eingabe des Passwort am
# Login-Prompt.
GETPASS_ASTERISKS 0
root# jed /etc/pam.d/login
# Zugriffs-Limiten setzen.
account required pam_access.so
# Benutzer-Limiten setzen.
session required pam_limits.so
# Letzes Login Info anzeigen nach einem erfolgreichem Login.
# (Wenn kommentiert, dann deaktiviert)
#session optional pam_lastlog.so
# Das Passwort muss eine minimale und eine maximale Länge von
# 8 Charakter haben.
password required pam_unix.so nullok obscure min=8 max=8 md5
root# jed /etc/pam.d/passwd
# Das Passwort muss eine minimale und eine maximale Länge von
# 8 Charakter haben.
# Diese Einstellung muss übereinstimmen mit derjenigen in
# "/etc/pam.d/login"
password required pam_unix.so nullok obscure min=8 max=8 md5
root# jed /etc/pam.d/su
# Benutzer die "su" ausführen wollen, müssen der Gruppe "wheel"
# angehören.
auth required pam_wheel.so group=wheel
# Benutzer-Limiten setzen. (Diese Option überschreibt diejenige in
# "/etc/limits.conf")
session required pam_limits.so
Damit auch der Benutzer "admin" wirklich "su" machen darf, muss er wie
beschrieben in der Gruppe "wheel" sein:
root# groupadd wheel
root# usermod -G admin,wheel admin
Benutzerlimiten
---------------
Benutzerlimiten werden in der Datei "/etc/security/limits.conf" gesetzt.
FIXME: Weitere sinnvolle Limiten.
root# jed /etc/security/limits.conf
# Eine "soft" Limite bedeutet, dass wenn der Benutzer diese Zahl
# erreicht hat, eine Warnung vom System ausgegeben wird.
# Eine "hard" Limite bedeutet, dass wenn der Benutzer diese Zahl
# erreicht hat, die Limite erreicht ist.
# Eine Limite, das der Benutzer max. 150 Prozesse besitzen darf.
* soft nproc 100
* hard nproc 150
# Core-Dateien werden erzeugt, wenn ein Programm abstürzt. Das kann
# ein Angreifer ausnützen, indem er eine grosse Anzahl core-Dateien
# produziert und somit eine Partition überfüllen und somit ein System
# zum Absturz bringen kann.
# Ich schalte core-Dateien grundsätzlich ab:
* hard core 0
# Eine Limite, dass die maximale Dateigrösse 800MB betragen darf.
* soft fsize 700000
* hard fsize 800000
Login
-----
Das System ist sicherer, wenn nur Benutzer in der Gruppe "wheel" lokal
einloggen dürfen. In diesem Fall nur "admin".
root# jed /etc/security/access.conf
-:ALL EXCEPT wheel:ALL
Syslog
------
Syslog ist meiner Meinung nach bei Debian ziemlich gut konfiguriert. Nur das
loggen von cron-Aktivitäten ist ausgeschaltet, welches hiermit eingeschaltet
wird:
root# jed /etc/syslog.conf
cron.* /var/log/cron.log
Dynamische Kernelparameter
--------------------------
Es lohnt sich einige Parameter im "/proc" Verzeichnis zu ändern, vor allem um
DDoS Attacken zu stoppen. Nachfolgend sind hier die Veränderungen abgebildet
und kommentiert:
root# jed /etc/sysctl.conf
# IP forwarding deaktivieren.
net/ipv4/ip_forward=0
# tcp_syncookies aktivieren. Dient zum Schutz gegen DoS Attacken.
net/ipv4/tcp_syncookies=1
# gespoofte Pakete ausfiltern
net/ipv4/conf/default/rp_filter=1
# keine redirects zulassen
net/ipv4/conf/default/accept_redirects=0
# kein source-routing auf einem Server zulassen
net/ipv4/conf/default/accept_source_route=0
# keine Pakete mit der Source-Adresse 0.X.X.X annehmen
net/ipv4/conf/default/bootp_relay=0
# Pakete mit unbekannter Route loggen
net/ipv4/conf/default/log_martians=1
# Keine Echo-Requests zulassen - wir helfen nicht bei DDoS
# Dies wird aktiviert, um Missbrauch des hosts als exploder zu
# verhindern.
net/ipv4/icmp_echo_ignore_broadcasts=1
# Auf komische ICMP-Packete nicht reagieren.
net/ipv4/icmp_ignore_bogus_error_responses=1
Die Datei /etc/sysctl.conf wird beim booten durch das script procps.sh
ausgewertet.
SSH
---
Der OpenBSD SSH Daemon wird so konfiguriert, dass nur Personen in der Gruppe
"wheel" und mit gültigem private key einloggen können.
root# jed /etc/ssh/sshd_config
ListenAddress 192.168.0.125
Protocol 2
PermitRootLogin no
PasswordAuthentication no
Banner /etc/issue.net
AllowGroups wheel
root# rcsshd restart
Jetzt wird ein keypair mit 1024 bits im key kreiert. Der Typ "dsa" wird für das
Protokoll 2 gebraucht.
admin@350z$ ssh-keygen -b 1024 -t dsa
Enter Passphrase:
Danach wird der private Schlüssel auf eine Diskette und bei einem anderen
Rechner in das Verzeichnis ".ssh" verschoben. Wenn sich die Person am anderen
Rechner nun mit dem "350z" verbinden will, müssen der private und der
öffentliche Schlüssel zusammenpassen. Dazu muss sie noch das Passwort kennen.
admin@350z$ ls -l .ssh/*
-rw------- 1 admin admin 1264 Feb 24 16:50 .ssh/id_dsa
-rw-r--r-- 1 admin admin 1112 Feb 24 16:50 .ssh/id_dsa.pub
admin@350z$ cd .ssh
admin@350z$ mv id_dsa.pub authorized_keys
root# mount /floppy
root# mv /home/admin/.ssh/id_dsa /floppy
root# umount /floppy
admin@remote$ ssh -i .ssh/id_dsa 192.168.0.125
admin@350z$ exit
inetd
-----
Standardmässig laufen auf einer Debian-Installation einige Dienste, die nicht
gebraucht werden. Diese werden abgestellt, indem sie in der Datei
"/etc/inetd.conf" als Kommentar gekennzeichnet werden.
root# jed /etc/inetd.conf
Zusätzlich wird der TCP-wrapper so konfiguriert, dass alle Verbindungen, die
über ihn gehen verboten werden.
root# jed /etc/hosts.deny
ALL:PARANOID
root# rcinetd restart
root# chmod 0600 /etc/inetd.conf
exim
----
Exim wird so konfiguriert, dass er nur noch auf das interne interface "local"
horcht.
root# jed /etc/exim/exim.conf
local_interfaces = 127.0.0.1
root# rcexim start
Kernel
------
FIXME: monolith
Bei einem "Out of the Box" Kernel sind meistens alle möglichen Treiber
enthalten. In meinem Fall brauche ich 95% davon nicht. Sie machen das ganze
System nur unnötig langsamer und unsicherer. Deshalb wird ein neuer, schlanker
Kernel kompiliert, welcher nur das Nötigste enthält.
Hauptsächlich zum Schutz vor Buffer Overflows wird der "openwall"-patch
appliziert. Einer genauere Bedeutung jeder Option wird später erklärt.
root# mount -o remount,rw /usr
root# apt-get install ncurses-dev bzip2
root# cd /usr/src
root# wget --passive-ftp ftp://ftp.de.kernel.org/pub/linux/kernel/v2.4/ linux-2.4.25.tar.bz2
root# wget www.openwall.com/linux/linux-2.4.25-ow1.tar.gz
root# tar xjvf linux-2.4.25.tar.bz2
root# ln -s linux-2.4.25 linux
root# tar xzvf linux-2.4.25-ow1.tar.gz
root# mv linux-2.4.25-ow1/linux-2.4.25-ow1.diff linux
root# cd !$
root# patch -p1 < linux.2.4.25-ow1.diff
root# make menuconfig
root# time make dep clean bzImage modules modules_install
root# mount /boot
root# cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.25-ow1
root# cd /
root# ln -s boot/vmlinuz-2.4.25-ow1 vmlinuz-2.4.25-ow1
LILO
----
Jetzt muss nur noch LILO abgesichert, und der neue Kernel in das Menu
aufgenommen werden. Ich konfiguriere LILO so, dass wenn beim boot prompt
spezielle Parameter wie z.B. "init=/bin/sh" mitgegeben werden sollen, ein
Passwort benötigt wird. Wenn ich LILO so konfiguriert hätte, dass bei jedem
Boot ein Passwort eingegeben werden müsste, könnte man nicht mehr ohne vor
Ort zu sein einen Neustart machen.
root# jed /etc/lilo.conf
image=/vmlinuz
label=Linux.old
read-only
image=/vmlinuz-2.4.25-ow1
label=Linux
read-only
root# lilo -v 1
root# reboot
Alles hat geklappt und der neue Kernel bootet einwandfrei.
Jetzt kann der Alte gelöscht und eine LILO Passwort gesetzt werden:
root# rm -rf /lib/modules/2.4.18-bf2.4
root# mount /boot
root# rm -f /boot/*2.4.18*
root# jed /etc/lilo.conf
password=""
restricted
root# chmod 0600 /etc/lilo.conf
root# lilo -p -v 1
root# reboot
Snort/Apache-SSL/MySQL/ACID
---------------------------
FIXME: Aktuelle Version von Snort intsllieren.
Snort ist ein so genanntes "Network Intrusion Detection System" - kurz NIDS.
Es dient dazu, anhand von vordefinierten Signaturen Attacken zu erkennen und
zu loggen. Das geschieht durch die Analyse von Netzwerkpaketen.
ACID(Analysis Console for Intrusion Databases) ist eine grafische Oberfläche,
um die geloggten Ereignisse anzuzeigen und/oder zu modifizieren - sprich zu
löschen, archivieren oder sie per mail zu verschicken etc.
Bei Debian gibt es zum Glück schon die vorkompilierten Pakete "snort-mysql"
"apache-ssl" "acidlab" und "mysql-server", welche gut miteinander
harmonieren. Es gibt auch einen kleinen Dialog mit den wichtigsten
Konfigurationsfragen über snort:
root# mount -o remount,rw /usr
root# mount -o remount,exec /tmp
root# apt-get install snort-mysql apache-ssl acidlab php4-mysql mysql-server
listen: eth0
address range: 192.168.0.0/24
mail to: admin
mysqldb: snort_log
mysqluser: snort
passwd: secret
mysqlarchdb: snort_archive
mysqldb: snort
mysqluser: snort
passwd: secret
MySQL wird standardmässig ohne Netzwerkfähigkeit installiert und würde sowieso
von der Firewall geblockt werden; also muss eigentlich nur noch ein
root-Passwort gesetzt werden:
root# mysql
> USE mysql
> DELETE FROM user WHERE user='"";
> FLUSH PRIVILEGES;
> SET PASSWORD FOR root = PASSWORD('secret');
> EXIT;
Leider wird bei der Installation des Paketes "snort-mysql" die Datenbank für
snort logs nicht angelegt. Dies wird nachgeholt:
root# mysql -p
> CREATE DATABASE snort_log;
> GRANT INSERT,SELECT,DELETE,CREATE,UPDATE ON snort_log.* TO snort@localhost
> IDENTIFIED BY 'secret';
> EXIT;
Jetzt werden durch eine mit dem Paket mitgelieferten MySQL-dump Datei die
benötigten Tabellen in der Datenbank erstellt:
root# cd /usr/share/doc/snort-mysql/contrib
root# gunzip create_mysql.gz
root# mysql -p snort_log < create_mysql
root# wipe .mysql_history
"wipe" dient zum sicheren Löschen von Dateien.
Als nächstes müssen die Tabellen für die ACID-Datenbank erstellt werden. Das
geschieht durch einen Klick auf der ACID Setup Seite.
Nun muss noch in "/etc/snort/snort.conf" angebenen werden, dass als output
eine MySQL-Datenbank gewählt wurde:
root# jed /etc/snort/snort.conf
output database: alert, mysql, user=snort password=secret dbname=snort host=localhost
Apache wird möglichst sicher konfiguriert, d.h. Der Zugriff auf "ACID" wird
jedem ausserhalb der Domain "chupame.int" verweigert:
root# jed /etc/acidlab/apache.conf
order deny,allow
deny from all
allow from .chupame.int
In den Dateien "/etc/acidlab/acid_conf.php" und "/etc/snort/snort.conf" stehen
Passwörter für die Datenbank im Klartext. Deshalb muss ich sicher gehen, dass
diese nur vom Besitzer und sonst keinem gelesen werden kann:
root# chown www-data. /etc/acidlab/acid_conf.php
root# chmod 0400 !$
root# chown snort. /etc/snort/snort.conf
root# chmod 0400 !$
root# /etc/init.d/snort restart
Apache kann noch abgesichert werden, indem der Zugriff auf das "DocumentRoot"
für jedermann gesperrt wird:
root# jed /etc/apache-ssl/httpd.conf
Order deny,allow
Deny from all
Ausserdem werden Module wie "userdir" oder "cgi" nicht gebraucht und deshalb
auskommentiert.
root# /etc/init.d/apache-ssl restart
chkrootkit
----------
"Rootkits" werden von crackern oder "script-kiddies" meistens eingesetzt, um
nach einem erfolgreichem Einbruch ihre Aktivitäten zu verschleiern, ein
"Backdoor" zu installieren oder sich unsichtbar zu machen. Es gibt dutzende von
"rootkits". Die meisten basieren auf ladbaren Modulen. Deshalb ist auch ein
monolithischer Kernel sicherer. Eine Möglichkeit das System auf solche
"rootkits" zu überprüfen ist das Tool "chkrootkit", welches installiert und
wöchentlich ausgeführt wird(Kann nicht schaden...)
root# mkdir packages; cd packages
root# wget http://www.spenneberg.org/chkrootkit-mirror/files/chkrootkit.tar.gz
root# tar xzvf chkrootkit.tar.gz
root# cd chkrootkit-0.43
root# cp chkrootkit /usr/local/sbin
root# jed /etc/cron.weekly/chkrootkit
#! /bin/sh
recp=admin
mail=/sur/bin/mail
$chkrootkit | $mail -s "chkrootkit output `hostname`" $recp
tara
----
"tara" ist ein Tool um das System mittels einzelner scripts auf
Sicherheitsprobleme zu scannen. Dabei werden u.a. Berechtigungen,
Benutzeraccounts, cron-Einträge und mail-Aliase auf ihre Richtigkeit geprüft.
root# wget www-arc.com/tara/tara-3.0.3.tgz
root# tar xzvf tara-3.0.3.tgz
root# mv tara-3.0.3 /ust/local/sbin/tara
root# jed /etc/cron.daily/tara
#! /bin/sh
tara=/usr/local/sbin/tara
mail=/usr/bin/mail
recp=admin
cd $tara && ./tara > /dev/null 2>&1 && $mail -s "tara output `hostname`" $recp <
$tara/results/tara-data/security.report.`hostname`.`date +%y%m%d`-* && rm -f $tara/results/tara-data/*
logcheck
--------
"logcheck" prüft stündlich alle Logdateien in /var/log auf evt. Auffälligkeiten
wie z.B. "su"- oder "cron"-Aktivitäten. Diese werden "admin" gemailt.
root# apt-get install logcheck
Weitere Konfiguration wird nicht benötigt.
Berechtigungen
--------------
Das System sollte täglich auf ungewöhnliche Dateiberechtigungen gescannt
werden. Dies wird mit folgendem script erreicht:
root# jed /etc/cron.daily/perm
find=/usr/bin/find
mail=/usr/bin/mail
permfile=/tmp/perm
recp=admin
$find /*[!proc]* -type f \( -perm -04000 -o -perm -02000 \) \
-exec ls -l {} \; \ > $permfile # suid und sgid
$find /*[!proc]* -type f -perm -002 -exec ls -l {}\; >> $permfile # -rw-rw-rw-
$find /*[!proc]* -type d -perm -002 -exec ls -ld {}\; >> $permfile # drw-rw-rw-
$find /*[!proc]* -type f -perm -003 -exec ls -l {}\; >> $permfile # -rwxrwxrwx
$find /*[!proc]* -type d -perm -003 -exec ls -ld {}\; >> $permfile # drwxrwxrwx
$mail -s "perm output `hostname` " $recp < $permfile
rm -f $permfile
suid's entfernen
----------------
Die "suid's" von "mount" bzw. "umount", "ping", "at" und "crontab" werden
entfernt, weil es einem normalen Benutzer nicht gestattet sein sollte, diese
Programme zu benutzen. Ausserdem stellen Dateien die das "suid"-Bit gesetzt
haben, immer ein potentielles Sicherheitsrisiko dar.
root# chmod -s /bin/mount /bin/umount /bin/ping /usr/bin/at /usr/bin/crontab
Entwicklungstools
-----------------
Entwicklungstools wie "gcc" oder "make" könen jetzt ebenfalls deinstalliert
werden. Sie könnten einem Einbrecher behilflich sein, Programme zu kompilieren.
root# apt-get remove --pruge gcc libc6-dev flex make libcurses5-dev cpp
Letzte Berechtigungen
---------------------
root# chmod 0700 /etc/init.d/*[!README]*
Benutzerüberwachung
-------------------
"snoopy" ist eine Laufzeitbibliothek, die als Ummantelung für die
durch libc bereitgestellte execv()-Funktion dient, um jeden Aufruf per
syslog (authpriv) zu protokollieren.
root# apt-get install snoopy
root# chmod o-rwx /etc/ld.so.preload
Audits und Tests
================
nmap
----
Vor dem Scan wird die Firewall abgeschaltet, da sonst ein timeout ausgegeben
werden würde.
Es wird ein TCP Portscan mit "nmap" von Port 1 bis 1024 durchgeführt. Dabei
sollten die Ports 22 und 443 offen sein:
root@remote# nmap -p 1-1024 -T insane -O -v 192.168.0.125
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
No tcp,udp, or ICMP scantype specified, assuming SYN Stealth scan.
Use -sP if you really don't want to portscan (and just want to see what
hosts are up).
Host (192.168.0.125) appears to be up ... good.
Initiating SYN Stealth Scan against (192.168.0.125)
Adding open port 22/tcp
Adding open port 443/tcp
The SYN Stealth Scan took 2 seconds to scan 1024 ports.
For OSScan assuming that port 22 is open and port 1 is closed and neither
are firewalled
Interesting ports on (192.168.0.125):
(The 1021 ports scanned but not shown below are in state: closed)
Port State Service
22/tcp open ssh
443/tcp open https
Remote operating system guess: Linux Kernel 2.4.0 - 2.5.20
Uptime 1.088 days (since Tue Mar 2 13:22:27 2004)
TCP Sequence Prediction: Class=random positive increments
Difficulty=3212403 (Good luck!)
IPID Sequence Generation: All zeros
Nmap run completed -- 1 IP address (1 host up) scanned in 6 seconds
nessus
------
Beim Nessus-Scan werden natürlich nur die relevanten Plugins aktiviert. Ein
Scan beispielsweise auf SAMBA Schwachstellen ist ziemlich unsinnig.
Beim Scan kam raus, dass angeblich eine SSH- und Apache Version mit
Sicherheitslücken installiert sei. Das wäre auch korrekt, wenn diese Versionen
nicht gepatcht wären. Ausserdem wurde eine UDP Schwachstelle in der Firewall
entdeckt, die es ermöglicht, die Firewall zu umgehen. Da sie jedoch nicht
aktiviert war, ist dies irrelevant.
john
----
Der Passwort-cracker "john" wurde installiert und wird täglich ausgeführt.
Dabei wird jedoch nur eine Passwort-Liste durchgegangen, um wirklich schwache
Passwörter zu finden. Die Resultate werden an "admin" gemailt. In der
Konfigurationsdatei "/etc/john-mail.conf" muss ausserdem ein tempfile angegeben
werden.
iptraf
------
"iptraf" wurde installiert, um den Netzwerkverkehr zu überwachen. Dabei können
u.a. Statistiken, einfache- und sehr detaillierte Ausgaben ausgewählt werden.
Wenn "iptraf" ausgeführt wird, geht die Netzwerkkarte in den so genannten
"promiscous"-mode. Somit können alle Pakete im gleichen Subnetz bzw. in einem
nicht geswitchten Netz abgehört werden.
tcpdump
-------
"tcpdump" ist ein konsolen-tool, um jedes einzelne Paket, welches über das
gewählte interface durchläuft anzuzeigen. Der Vorteil von "tcpdump" liegt in
der hohen Flexibilität. Es können "expressions" angegeben werden. Da gibt es
"type" für: host, net, port. "dir" für: src und dst. "proto" für arp, tcp,udp,
ip6, fddi etc.
Wenn "tcpdump" ausgeführt wird, geht die Netzwerkkarte ebenfalls
"promiscous"-mode.
buffer overflows / openwall
---------------------------
Das Tool "stacktest" wird mit dem "openwall"-patch mitgeliefert. Es dient dazu,
"buffer overflows" zu simulieren bzw. die "non-executable user stack area"
zu testen.
root# stacktest -b
Attempting to call a trampoline...
Succeeded.
Attempting to simulate a buffer overflow exploit...
Segmentation fault
snort
-----
"ACID" wurde getestet, indem grosse ICMP-Pakete an die Maschine gesendet wurden.
Das NIDS hat diese als Angriff erkannt.
Firewall
--------
FIXME: Content
Handbuch
========
Neuer Benutzer
--------------
Neue Benutzer werden mit "adduser" angelegt. Das Passwort muss
aus min. 8 Zeichen mit Gross- und Kleinbuchstaben, Zahlen und Spezialzeichen
bestehen. Gelöscht wird er mit "userdel -r ". Der Benutzer darf nur
der Gruppe oder "wheel" angehören. In seinem Heimatsverzeichnis
"/home/" kann nichts ausgeführt werden.
Sollte ein neuer Benutzer einloggen müssen, muss er in die Gruppe "wheel"
aufgenommen werden. Benutzer in dieser Gruppe haben das Recht sich per SSH
einzuloggen, lokal einzuloggen, su auszuführen und das System runterzufahren.
Sollte der neue Benutzer nur eines dieser Rechte erhalten, muss dies in der
entsprechenden Konfigurationsdatei abgeändert werden.
Neues Paket
-----------
Wird ein neues Paket installiert, sollte das mit "dselect" geschehen. Davor
muss "/usr" als "rw" und "/tmp" als "exec" eingebunden werden.
root# mount -o remount,rw /usr
root# mount -o remount,exec /tmp
root# dselect
root# mount -o remount,ro /usr
root# mount -o remount,noexec /tmp
Ein Paket wird mit "apt-get --purge " gelöscht.
openwall
--------
FIXME: Genauer...
Die einzelnen Kerneloptionen aufgeführt:
Non-executable user stack area
Schützt vor Buffer Overflows.
Restricted links in /tmp.
Benutzer können keine "hard-links" auf Dateien machen, die ihnen nicht gehören.
Restricted FIFOs in /tmp.
Das Schreiben auf "FIFO's" beschränken.
Restricted /proc.
Die Option schränkt Berechtigungen auf /proc u.a. so ein, dass Benutzer nur ihre
eigenen Prozesse sehen können. Auch aktive Netzwerkverbindungen können als
"non-root" nicht mehr abgefragt werden.
Enforce RLIMIT_NPROC on execve(2)
Schützt davor, dass Benutzer nicht mehr Prozesse haben dürfen als sie mit
einfachen Limiten angegeben werden.
Firewall
--------
Hier ist das ganze Firewall-script abgebildet und kommentiert.
#!/bin/sh
# ------------------------------------------------------
# 1.0 INITALISIERUNG
# ------------------------------------------------------
#
# Variablen
#
IPTABLES=/sbin/iptables
FIREWALL=/etc/init.d/firewall
INT=eth0
p_high=1024:65535
#
# Verbindungen nach aussen.
#
p_ext_out_tcp_1="21"
p_ext_out_tcp_2="22"
p_ext_out_tcp_3="80"
p_ext_out_tcp_4=$p_high # FIXME: Unsicher
p_ext_out_tcp_all="$p_ext_out_tcp_1 $p_ext_out_tcp_2 $p_ext_out_tcp_3 $p_ext_out_tcp_4"
p_ext_out_udp_1="53"
p_ext_out_udp_all="$p_ext_out_udp_1"
#
# Verbindungen von aussen.
#
p_ext_in_tcp_1="22"
p_ext_in_tcp_2="443"
p_ext_in_tcp_all="$p_ext_in_tcp_1 $p_ext_in_tcp_2"
p_ext_in_udp_1=""
p_ext_in_udp_all="$p_ext_in_udp_1"
case "$1" in
start)
echo -e "\nStarting firewall...\n"
# ------------------------------------------------------
# 2.0 Default Policy, lokale Prozesse und ICMP-Regeln.
# ------------------------------------------------------
#
# Default Policy(alles verbieten!) und flushen(Regeln löschen).
#
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -F
$IPTABLES -X
#
# Lokale Prozesse
#
$IPTABLES -A OUTPUT -o lo -j ACCEPT
$IPTABLES -A INPUT -i lo -j ACCEPT
#
# ICMP immer erlauben
#
$IPTABLES -A OUTPUT -p ICMP -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -A INPUT -p ICMP -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
# ------------------------------------------------------
# 3.0 Verbindungen nach aussen.
# ------------------------------------------------------
#
# Verbindungen nach aussen: TCP
#
for a in $p_ext_out_tcp_all; do
$IPTABLES -A OUTPUT -o $INT -m state --state NEW,ESTABLISHED,RELATED -p TCP --dport $a --sport $p_high -j ACCEPT
done
#
# Verbindungen nach aussen: UDP
#
for a in $p_ext_out_udp_all; do
$IPTABLES -A OUTPUT -o $INT -m state --state NEW,ESTABLISHED,RELATED -p UDP --dport $a --sport $p_high -j ACCEPT
done
# ------------------------------------------------------
# 4.0 Verbindungen von aussen.
# ------------------------------------------------------
#
# Verbindungen von aussen: TCP
#
for a in $p_ext_in_tcp_all; do
$IPTABLES -A INPUT -i $INT -p TCP --sport $p_high --dport $a -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $INT -p TCP --sport $a --dport $p_high -m state --state ESTABLISHED,RELATED -j ACCEPT
done
#
# Verbindungen von aussen: UDP
#
for a in $p_ext_in_udp_all; do
$IPTABLES -A INPUT -i $INT -p UDP --sport $p_high --dport domain -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $INT -p UDP --sport domain --dport $p_high -m state --state ESTABLISHED,RELATED -j ACCEPT
done
# ------------------------------------------------------
# 5.0 Generische Regeln
# ------------------------------------------------------
#
# Eingehende Pakete bei bereits aufgebauter Verbindung akzeptieren.
#
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#
# Ausgehende Pakete bei bereits aufgebauter Verbindung akzeptieren.
#
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ------------------------------------------------------
# 6.0 Alles andere droppen
# ------------------------------------------------------
#
# Alle anderen Pakete sperren.
#
#$IPTABLES -A INPUT -j LOG --log-prefix "IPTABLES INPUT DENY: "
$IPTABLES -A INPUT -j DROP
#$IPTABLES -A OUTPUT -j LOG --log-prefix "IPTABLES OUTPUT DENY: "
$IPTABLES -A OUTPUT -j DROP
#$IPTABLES -A FORWARD -j LOG --log-prefix "IPTABLES FORWARD DENY: "
$IPTABLES -A FORWARD -j DROP
;;
stop)
echo -e "\nStopping firewall...\n"
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -F
$IPTABLES -X
;;
restart)
$FIREWALL stop && $FIREWALL start
;;
drop)
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -F
$IPTABLES -X
;;
*)
echo "Usage: firewall {start|stop|restart|drop}"
exit 1
;;
esac
Sollte die Firewall verbotene ein- oder ausgehende Verbindungen loggen, muss
dies im entsprechenden Abschnitt im script aktiviert werden. Die Ausgabe wird
automatisch in die Datei "/var/log/kern.log" geschrieben. Die Auswertung kann
mit folgendem script täglich an "admin" gemailt werden:
#! /bin/sh
grep IPTABLES /var/log/kern.log | mail -s "iptables log `hostname`" admin
Dazu muss das script "executable" gemacht werden und in "/etc/cron.daily"
verschoben werden.
--------------------------------------------
Was sonst noch gemacht werden könnte:
- Ein "chroot-environment" für Benutzer, Apache, MySQL, SSH etc.
- Das ext* Attribut "a" für Log-Dateien setzen. (append)
- Die ganze Distribution auf CD brennen und von dieser booten.
- Read-Only Distributionen einsetzen.
- Weitere Kernelpatches
- Alle Logdateien an einem lokalen Drucker ausgeben
- Einen entfernten log-host installieren
- Eine restriktivere Firewall. z.B. Ausgehende Verbindungen nur zu
"security.debian.org".
- Arp-Adressen fest in arp-table eintragen.
- IP-Adressen fest in /etc/hosts eintragen. Z.B. Debian Mirrors
- md5-Summen aller auf dem System installierten Pakete bilden, auf CD brennen
und periodisch mit dem aktuellen System vergleichen
- Mehr Benutzerlimiten setzen
- Alle Banner deaktivieren. (Apache, SSH etc.)
- md5-Summen aller mit wget runtergeladenen Pakete überprüfen.
- Backup
- Dateiintergrität(tripwire)
- ...
-- MatthiasWeiss - 03 Dec 2004