SSH absichern

SSH

Der Root muss sich nicht per SSH einloggen können. Es ist besser, wenn sich nur Benutzer einloggen und hinterher zum Root machen. Um das zu ändern muss in der

/etc/ssh/sshd_config

der entsprechende Parameter von

PermitRootLogin yes

auf

PermitRootLogin no

geändert werden. Das kann man entweder von Hand machen oder zu Übung mit sed:

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak && sed -e 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new && cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config

Mit dieser Zeile wird die Originaldatei gesichert, der Parameter ersetzt und alles in eine neue Datei geschrieben. Diese neue Datei ersetzt dann durch Kopieren die Original-Datei. Hinterher sind folgende Dateien vorhanden:

# ls -alh /etc/ssh/sshd_config*
 -rw-r--r-- 1 root root 1,9K 13. Jun 13:42 /etc/ssh/sshd_config
 -rw-r--r-- 1 root root 1,9K 13. Jun 13:42 /etc/ssh/sshd_config.bak
 -rw-r--r-- 1 root root 1,9K 13. Jun 13:42 /etc/ssh/sshd_config.new

so dass jederzeit auf die gewünschte Konfiguration gewechselt/zurückgesetzt werden kann.

Jetzt noch ein

# /etc/init.d/ssh reload

damit die Konfiguration noch aktiv wird. Durch den Reload bleiben aktuell aufgebaute Sessions aktiv!

Grub absichern

Um sicherzustellen, dass ein Benutzer, der das System rebootet und Zugriff auf die Konsole hat, nicht einfach am Bootprompt

init=/bin/sh

eingibt und sich damit eine Single-User-Shell erschleicht und einfach in das System einbrechen kann, sollte man den Bootprompt absichern. Nichts einfacher als das.

Zuerst sollte man sich einen md5-Hash für das Grub-Passwort erzeugen. Schön, dass Grub dafür gleich das entsprechende Werkzeug mitbringt:

grub-md5-crypt
Password:
Retype password:
$1$Ki6fc/$TdYOWM/XokvdhZoF/B/8v.

Dazu also einfach den o.g. Befehl aufrufen, zwei Mal das gewünschte Passwort eingeben und man erhält einen md5-Hash, den Grub verwenden kann. Wer es gerne ausprobieren möchte, das Passwort ist „test“.

Jetzt zur Konfiguration. Die erfolgt in

/boot/grub/menu.lst

Hier unter dem Bereich

## password ['--md5'] passwd

folgende Zeile hinzufügen

password --md5 $1$Ki6fc/$TdYOWM/XokvdhZoF/B/8v.

Als MD5-Passwort-String ist der vorher generierte zu verwenden. Wie man der Beschreibung des Bereiches entnehmen kann, kann man das Passwort auch im Klartext setzen. Aber warum ein Sicherheitsrisiko eingehen, wenn es nicht notwendig ist.

Damit kann man die Boot-Prompt-Zeilen nicht mehr ohne Passwort editieren.

Schön und gut. Aber den Single-User-Modus, der automatisch von Grub immer mit eingerichtet wird kann immer noch gestartet werden. Um das zu verhindern, muss folgender Parameter geändert werden:

Von

# lockalternative=false

auf

# lockalternative=true

Damit muss dass Passwort auch für das Starten aller nicht-Default-Zeilen eingegeben werden.

Zum Schluss noch ein

update-grub

damit Grub, die lockalternative-Direktive übernimmt.

Webserver absichern

Ein Apache-Webserver gibt standardmäßig auftretende Fehler auf der Webseite aus. Dass kann durch provozierte Aufrufe zur Preisgabe von unerwünschten Informationen wie

  • lokaler Verzeichnispfad des Webservers
  • Apache-Version
  • PHP-Version
  • Patchlevel von Apache2/PHP

führen.

Daher sollten diese Informationen auf Produktivsystem nicht öffentlich angezeigt werden.

PHP

Dazu muss man nur in der entsprechenden php.ini (hier: /etc/php5/apache2/php.ini) das Anzeigen der Fehler abschalten (Off).

; Print out errors (as a part of the output). For production web sites,
; you're strongly encouraged to turn this feature off, and use error logging
; instead (see below). Keeping display_errors enabled on a production web site
; may reveal security information to end users, such as file paths on your Web
; server, your database schema or other information.
;
display_errors = Off

Für den Administrator sind diese Fehler natürlich trotzdem wichtig. Daher sollte man das Logging der Fehler einschalten (On).

; Log errors into a log file (server-specific log, stderr, or error_log (below))
; As stated above, you're strongly advised to use error logging in place of
; error displaying on production web sites.
;
log_errors = On

Die Fehlermeldungen werden in das error-Log der jeweiligen vHost- oder Standard-Konfiguration geschrieben.

Apache2

Auch der Apache2 kann noch etwas schweigsamer konfiguriert werden. Und damit das nicht so schwer fällt, ist es sogar schon vorbereitet.

Im Pfad „/etc/apache2/conf.d/“ existiert in Debian die Datei „security“. In dieser sind bereits die wichtigsten Einstellung vorhanden und müssen für Produktivsysteme nur noch aktiviert werden.

# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of:  Full | OS | Minimal | Minor | Major | Prod
# where Full conveys the most information, and Prod the least.
#
ServerTokens Minimal
#ServerTokens Full
#ServerTokens Prod
#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (internal error documents, FTP directory
# listings, mod_status and mod_info output etc., but not CGI generated
# documents or custom error documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of:  On | Off | EMail
#
ServerSignature Off

iptables personal firewall

Personal Firewall einrichten

Die angegebenen Werte sind nur Beispiel-Werte und müssen natürlich angepasst werden.

Hier mal eine Beispiel-Konfiguration:

#!/bin/sh
# Variablen
LAN_IFACE="eth0"
LAN_IP="192.168.XXX.XXX"
LAN_NET="192.168.XXX.0/24"
 
# Setzen von Kernelparametern
for i in /proc/sys/net/ipv4/conf/*/{accept_source_route,accept_redirects,send_redirects}; do
    echo 0 > $i
done
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
 
### Firewall initialisieren ###
echo "Initialisiere Firewall ..."
iptables -F                                  # Regeln aller Chains löschen
iptables -X                                  # Alle selbst erstellten Chains löschen
iptables -P INPUT DROP                       # Alles was nicht explizit erlaubt ist ...
iptables -P OUTPUT DROP                      # ... wird gedroppt.
iptables -P FORWARD DROP                     #
iptables -Z                                  # Zähler zurücksetzen
iptables -N OWNDROP                          # Eigene Chain für separate Verarbeitung erstellen
iptables -N OWNACCEPT                        # ...
iptables -N SYN-FLOOD                        # DoS-Attacken eingrenzen
 
### Lokale Kommunikation ###
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
 
### Stateful Inspection Regeln ###
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state INVALID -j OWNDROP
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
 
### Eigene Chains OWNDROP und OWNACCEPT konfigurieren (Logging) ###
iptables -A OWNDROP -j LOG --log-prefix "FW-DROP: "
iptables -A OWNDROP -j DROP
iptables -A OWNACCEPT -j LOG --log-prefix "FW-ACCEPT: "
iptables -A OWNACCEPT -j ACCEPT
 
### Schutz vor Syn-Flooding ###
# limits incoming packets
iptables -A SYN-FLOOD -m limit --limit 10/second --limit-burst 50 -j RETURN
# log attacks
iptables -A SYN-FLOOD -j LOG --log-prefix "SYN flood: "
# silently drop the rest
iptables -A SYN-FLOOD -j DROP
 
### Ports und Dienste nach aussen freischalten ###
# Eingehende SSH-Verbindungen
iptables -A INPUT -p tcp --dport 22 -j OWNACCEPT
# Ausgehende SSH-Verbindungen
iptables -A OUTPUT -p tcp --dport 22 -j OWNACCEPT
# PING
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT
# ausgehende DNS-Anfragen
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
# WWW
iptables -A INPUT -p tcp --dport 80 -j OWNACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j OWNACCEPT
iptables -A INPUT -p tcp --dport 443 -j OWNACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j OWNACCEPT
# Mails
iptables -A OUTPUT -p tcp --dport 25 -j OWNACCEPT
iptables -A OUTPUT -p tcp --dport 110 -j OWNACCEPT
iptables -A OUTPUT -p tcp --dport 143 -j OWNACCEPT
# Samba
iptables -A INPUT -p udp -m multiport --destination-port 137,138 -s $LAN_NET -j ACCEPT
iptables -A INPUT -p tcp -m multiport --destination-port 139,445 -s $LAN_NET -j ACCEPT
iptables -A OUTPUT -p udp -m multiport --destination-port 137,138 -d $LAN_NET -j ACCEPT
iptables -A OUTPUT -p tcp -m multiport --destination-port 139,445 -d $LAN_NET -j ACCEPT
iptables -A INPUT -p udp --sport 137 -s $LAN_NET -j OWNACCEPT
# NTP
iptables -A INPUT -p udp --dport 123 -s $LAN_NET -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
# SNMP
iptables -A INPUT -p udp --dport 161 -s $LAN_NET -j ACCEPT
iptables -A INPUT -p tcp --dport 161 -s $LAN_NET -j ACCEPT
iptables -A OUTPUT -p udp --dport 161 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 161 -j ACCEPT
 
# Protokollierung aller übriggebliebenen Pakete, die verworfen werden
iptables -A INPUT -j LOG --log-prefix "FW-LAST-DROP: "
 
### Fertig ###
echo "Firewall ist konfiguriert und aktiv"

Eigene Logdateien

Log-Präfix einstellen

Damit man die Logs, die iptables erzeugt, vom normalen syslog trennen kann, muss man die Logging-Einträge erst einmal eindeutig kennzeichnen. Dazu am besten eigene Ketten erstellen:

# Eigene Chains MYDROP und MYACCEPT konfigurieren (Logging)
iptables -A OWNDROP -j LOG --log-prefix "FW-DROP: "
iptables -A OWNDROP -j DROP
iptables -A OWNACCEPT -j LOG --log-prefix "FW-ACCEPT: "
iptables -A OWNACCEPT -j ACCEPT

oder die vorhandenen anpassen:

iptables -A DROP -j LOG --log-prefix "FW-DROP: "
iptables -A DROP -j DROP
iptables -A ACCEPT -j LOG --log-prefix "FW-ACCEPT: "
iptables -A ACCEPT -j ACCEPT

Der entsprechende Präfix ist natürlich frei wählbar.

rsyslogd konfigurieren

Jetzt muss man nur noch eine entsprechende Konfigurations-Datei unter /etc/rsyslog.d/iptables.conf anlegen und folgende Zeilen einfügen:

:msg, contains, "FW-ACCEPT: " /var/log/iptables/accept.log
& ~
:msg, contains, "FW-DROP: " /var/log/iptables/drop.log
:msg, contains, "FW-LAST-DROP: " /var/log/iptables/drop.log
& ~

Damit werden alle Einträge die „FW-ACCEPT: „, „FW-DROP: “ oder „FW-LAST-DROP: “ enthalten in separate Logdateien geschrieben. Man muss sich auch keine Gedanken um das Anlegen der Dateien machen. Das erledigt der RSyslog-Daemon bei dem obligatorischen Neustart von alleine:

/etc/init.d/rsyslogd restart

Die letzte Zeile mit dem Inhalt „& ~“ bedeutet, dass diese Nachrichten nicht mehr in das Standard-Log geschrieben werden.

In neueren rsyslog-Versionen ist die Tilde „~“ deprecated, weshalb man sie ersetzen sollte. Die neue Schreibweise sieht so aus:

:msg, contains, "FW-ACCEPT: " /var/log/iptables/accept.log
& stop
:msg, contains, "FW-DROP: " /var/log/iptables/drop.log
:msg, contains, "FW-LAST-DROP: " /var/log/iptables/drop.log
& stop

Logs rotieren

Damit die Logdateien nicht irgendwann die Festplatte zulaufen lassen, sollte auch eine entsprechende logrotate-Konfiguration nicht fehlen. Siehe Logrotate/iptables.