von http://www.chupame.ch/file.php?file=hardening.txt
Netzwerkkonfiguration
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: <user>@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 <Ctrl>+<Alt>+<Delete> 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
<DirectoryMatch /usr/share/acidlab/> order deny,allow deny from all allow from .chupame.int </DirectoryMatch>
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
<Directory /var/www>
- Order deny,allow Deny from all
</Directory>
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 <username>". Der Benutzer darf nur der Gruppe <Benutzername> oder "wheel" angehören. In seinem Heimatsverzeichnis "/home/<Benutzername>" 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 <paketname>" 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
- --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
- --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) - ...
Linux/HarDening (last edited 2009-06-06 20:42:25 by DetlevLengsfeld)