23.9 Snort
Snort ist ein sehr populäres Intrusion-Detection-System für Windows-, Linux- und Unix-Systeme.
Es hat eine ganze Reihe von Features und kann – von neuronalen Fähigkeiten einmal abgesehen – eigentlich alles, was man von einem Intrusion-Detection-System erwarten kann:
- Die Fehlerdiagnose und Überwachung des Netzwerkes bei der Netzwerkprogrammierung und Netzwerkadministration ist durch den integrierten Sniffer-Code möglich.
- Der Netzwerk-Traffic kann auf der Basis von Regelwerken überwacht werden.
- Es verfügt über eine Logging-Funktionalität.
- Es ist unter Linux, Unix und Windows einsetzbar.
Installation
Im Folgenden beziehen wir uns auf die Snort-Version 2.2.0. Sie war aktuell, als wir dieses Kapitel geschrieben haben. Da das Snort-Paket ein Bestandteil aller gängigen Distributionen und Derivate ist, werden wir hier nicht näher auf die Installation von Hand eingehen. Sie können den Quellcode von Snort jedenfalls von snort.org beziehen.
Traffic-Analyse mit Snort
Integrierter Sniffer
Ein wesentliches Feature von Snort ist der integrierte Sniffer. Dieser kann gut zur Analyse des Traffics und als Hilfe bei der Netzwerkprogrammierung herhalten. Jedoch erscheint das Feature trotzdem überflüssig, wenn man bedenkt, dass die meisten Systeme ihre eigenen Programme für diesen Zweck mitbringen. Unter Linux- und BSD-Systemen ist dies beispielsweise das Tool tcpdump. Weiterhin zu empfehlen ist ethereal.
Ein Blick in die Manpage verrät uns, dass Snort mithilfe des Verbose-Modes (also des -v Parameters) dazu gebracht werden kann, die im Linklayer empfangenen Pakete auszugeben.
Mittels des -i-Parameters wird die Schnittstelle angegeben, auf der gesnifft werden soll.
linux# snort -v -i lo Running in packet dump mode Log directory = /var/log/snort Initializing Network Interface lo --== Initializing Snort ==-- Initializing Output Plugins! Decoding Ethernet on interface lo --== Initialization Complete ==-- -*> Snort! <*- Version 2.2.0 (Build 30) By Martin Roesch (roesch@sourcefire.com,www.snort.org) 08/12-15:10:59.442523 127.0.0.1:32771 -> 127.0.0.1:22 TCP TTL:64 TOS:0x10 ID:51067 IpLen:20 DgmLen:60 DF ******S* Seq: 0xB3D42D7E Ack: 0x0 Win: 0x7FFF TcpLen: 40 TCP Options (5) => MSS: 16396 SackOK TS: 125445 0 NOP WS: 0 =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 08/12-15:10:59.442556 127.0.0.1:22 -> 127.0.0.1:32771 TCP TTL:64 TOS:0x0 ID:0 IpLen:20 DgmLen:60 DF ***A**S* Seq: 0xB43DF41C Ack: 0xB3D42D7F Win: 0x7FFF TcpLen: 40 TCP Options (5) => MSS: 16396 SackOK TS: 125445 125445 NOP WS: 0 =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 08/12-15:10:59.442576 127.0.0.1:32771 -> 127.0.0.1:22 TCP TTL:64 TOS:0x10 ID:51068 IpLen:20 DgmLen:52 DF ***A**** Seq: 0xB3D42D7F Ack: 0xB43DF41D Win: 0x7FFF TcpLen: 32 TCP Options (3) => NOP NOP TS: 125445 125445 =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 08/12-15:10:59.443671 127.0.0.1:22 -> 127.0.0.1:32771 TCP TTL:64 TOS:0x0 ID:7704 IpLen:20 DgmLen:77 DF ***AP*** Seq: 0xB43DF41D Ack: 0xB3D42D7F Win: 0x7FFF TcpLen: 32 TCP Options (3) => NOP NOP TS: 125445 125445 =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ ....
Listing 23.12 Snort-sniff
Mittels des -d-Parameters kann zusätzlich ein Dump der Pakete erreicht werden. Wir mussten die etwas breite Ausgabe jedoch umbrechen, was durch die Backslash-Zeichen signalisiert wird. Der bereits durch das obige Listing bekannte Initialisierungsoutput wurde der besseren Übersichtlichkeit halber entfernt.
linux# snort -v -d -i lo
....
08/12-15:14:07.944698 127.0.0.1:32772 -> 127.0.0.1:22
TCP TTL:64 TOS:0x10 ID:27392 IpLen:20 DgmLen:52 DF
***A**** Seq: 0xBEFA5959 Ack: 0xBF6138FF Win: 0x7FFF
TcpLen: 32
TCP Options (3) => NOP NOP TS: 144295 144295
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
08/12-15:14:07.945803 127.0.0.1:22 -> 127.0.0.1:32772
TCP TTL:64 TOS:0x0 ID:2904 IpLen:20 DgmLen:77 DF
***AP*** Seq: 0xBF6138FF Ack: 0xBEFA5959 Win: 0x7FFF
TcpLen: 32
TCP Options (3) => NOP NOP TS: 144295 144295
53 53 48 2D 31 2E 39 39 2D 4F 70 65 6E 53 53 48
SSH-1.99-OpenSSH
5F 33 2E 37 2E 31 70 32 0A
_3.7.1p2.
^{C}
======================================================
Snort received 24 packets
Analyzed: 24(100.000%)
Dropped: 0(0.000%)
======================================================
Breakdown by protocol:
TCP: 12 (50.000%)
UDP: 0 (0.000%)
ICMP: 0 (0.000%)
ARP: 0 (0.000%)
EAPOL: 0 (0.000%)
IPv6: 0 (0.000%)
IPX: 0 (0.000%)
OTHER: 0 (0.000%)
DISCARD: 0 (0.000%)
======================================================
Action Stats:
ALERTS: 0
LOGGED: 0
PASSED: 0
======================================================
Snort exiting
Listing 23.13 Snort-sniff mit Package-Dump
Wie Sie sehen, wird Snort (sofern es nicht im Daemon-Modus betrieben wird) durch die Tastenkombination Strg+C abgebrochen.
23.9.1 Aufbau der Intrusion Detection
Doch kommen wir nach dieser kleinen Exkursion nun zur Hauptaufgabe von Snort, der Intrusion Detection. Zunächst sollte das Logverzeichnis /var/log/snort angelegt werden.
Vorgefertigte Konfiguration
Anschließend kann die im Subverzeichnis etc/ mitgelieferte Konfigurationsdatei nach /etc/snort.conf verschoben werden. <Wurde Snort als Paket installiert, wird dies in den meisten Fällen bereits erledigt sein.>
# mkdir /var/log/snort # cp etc/snort.conf /etc/
23.9.2 snort.conf
Sehen wir uns den Aufbau der Konfigurationsdatei einmal an. Kommentare werden – wie auch in Shellskripten – mit einer Raute eingeleitet.
Zudem können, ähnlich wie in C, C++ oder in Makefiles, weitere Dateien eingebunden, also »includiert« werden. Hier wird das Schlüsselwort include: plus einer entsprechenden Pfadangabe verwendet.
Variablen
Zur Kreierung einer Variablen verwendet man das Schlüsselwort var, also etwa:
var ROUTER 192.168.0.2
Variablen können in den Regeldateien via $<Variable>, also etwa mit $ROUTER, angesprochen werden.
Die Variable HOME_NET wird zur Angabe des Inhouse-Netzes verwendet, wogegen EXTERNAL_NET für die Gegenseite steht (die Konfiguration kann folglich problemlos auf einem Gateway eingesetzt werden).
Variablen nutzen
Es folgen die Variablen zur Angabe der Dienste des Netzwerkes, also etwa die Variable SMTP_SERVERS für die Liste der Mailserver im Netz oder TELNET_SERVERS für die Telnet-Server und so weiter. Darauf folgen Portangaben und spezielle Variablen, etwa AIM_SERVERS zur Angabe der Server für den Instant-Messenger. An diesem Beispiel ist sehr gut zu sehen, wie eine Separierung von Werten (nämlich durch Kommas) und die Verwendung von Netz-Klassen (nämlich durch Angabe der Net-ID-Bits hinter einem Slash) auszusehen hat.
var AIM_SERVERS [64.12.24.0/24, 64.12.25.0/24, 64.12.26.14/24, 64.12.28.0/24, 64.12.29.0/24, 64.12.161.0/24, 64.12.163.0/24, 205.188.5.0/24, 205.188.9.0/24]
Wie der Kommentar zur Angabe des Pfades der Regeldateien verrät, ist es möglich, diesen als relativen Pfad anzugeben. Doch auch eine absolute Pfadangabe hat noch niemandem geschadet.
var RULE_PATH /etc/snort/rules
Listing 23.14 RULE_PATH
Das config-Schlüsselwort
Mit dem config-Schlüsselwort können Sie das Verhalten von Snort, etwa bei bestimmten Situationen, konfigurieren. Da man an der Praxis bekanntlich am einfachsten lernt, werden wir uns nun einfach weiter der Analyse der Konfigurationsdatei widmen.
Analyse
Als Erstes wird man mit dem »decoder«-Bereich des NIDS <Network Intrusion Detection System(s)> konfrontiert. Wir sehen, dass das config-Schlüsselwort immer an erster Stelle steht. Anschließend wird ein Parameter übergeben, mit dem die eigentliche Aktion bestimmt wird. Optional können auch Parameter übergeben werden.
Beim Listing ist zu beachten, dass zur Aktivierung der beschriebenen config-Operationen die Auskommentierung erfolgen muss.
# Stop generic decode events: # # config disable_decode_alerts # # Stop Alerts on experimental TCP options # # config disable_tcpopt_experimental_alerts # # Stop Alerts on obsolete TCP options # # config disable_tcpopt_obsolete_alerts # # Stop Alerts on T/TCP alerts # # config disable_tcpopt_ttcp_alerts # # Stop Alerts on all other TCPOption type events: # # config disable_tcpopt_alerts # # Stop Alerts on invalid ip options # # config disable_ipopt_alerts
Listing 23.15 Snort-Decoder
Nachfolgend sollen die oben aufgelisteten sowie die wichtigsten nicht aufgelisteten Parameter besprochen werden.
- »disable_decode_alerts« stellt die Meldungen des Decoders ab.
- »disable_tcpopt_experimental_alerts« gibt keine Warnungen beim Eintreffen von TCP-Paketen mit experimentellen Optionen aus.
- »disable_tcpopt_obsolete_alerts« gibt keine Warnungen beim Eintreffen von TCP-Paketen mit veralteten Optionen aus.
- »disable_tcpopt_ttcp_alerts« stellt Warnungen beim Eintreffen von TCP-Paketen aus.
- »disable_tcpopt_alerts« stellt generell alle Warnungen ab, die durch TCP-Optionen hervorgerufen werden.
- »disable_ipopt_alerts« gibt keine Warnungen aus, wenn IP-Pakete mit abnormalen Optionen gefunden werden.
- »set_gid« ändert die Gruppen-ID, unter der snort läuft, auf die angegebene. »set_uid« erfüllt die gleiche Funktionalität bezüglich der User-ID.
- »daemon« versetzt snort in den Daemon-Modus, womit es also als Hintergrundprozess sein Dasein fristet.
- »interface« legt das Interface, auf dem snort agieren soll, fest, etwa config interface:eth1.
- »logdir« spezifiziert das Verzeichnis, in dem die Logdateien untergebracht werden.
Dieses Verzeichnis kann sehr groß werden. In der Regel wird hierzu das Verzeichnis /var/log/snort verwendet, daher sollte immer darauf geachtet werden, dass der /var-Partition genügend Speicherplatz zur Verfügung steht.
- »umask« legt unter Unix die umask-Werte zur Erstellung neuer Dateien fest.
- »no_promisc« setzt das Netzwerk-Interface, auf dem snort agiert, nicht in den Promiscuous-Modus. In der Regel ist diese Option nicht von Bedeutung.
- »chroot« funktioniert zumindest unter Unix und legt mithilfe des chroot(2)-Syscalls ein neues Wurzelverzeichnis für snort fest. Dies erschwert Angriffe auf snort und findet auch bei anderen Diensten, etwa dem Apache-Webserver und Bind unter OpenBSD, Verwendung.
- »checksum_mode« legt die Überprüfung der Prüfsummen fest. Mit notcp können beispielsweise die Berechnungen der Prüfsummen von TCP-Paketen unterbunden werden. Auf langsamen Maschinen kann das Abstellen der Checksum-Prüfung (»none«) eine kleine Steigerung der Performance mit sich bringen.
Das Schlüsselwort preprocessor
Mit der Einführung von preprocessor-Extensions bekam snort die Möglichkeit der modularen Weiterentwicklung. So wurde beispielsweise ein Portscan-Detection-Modul entwickelt, das über die Anweisung preprocessor in snort Verwendung findet.
PortscanDetection
Zunächst wenden wir uns der Portscan-Detection zu. Mit ihr kann bestimmt werden, wie viele TCP- aber auch UDP-Ports eine Quelle innerhalb welcher Zeit anfragen muss, um als Portscan erkannt zu werden.
Es werden hierbei auch spezielle Techniken wie der X-Mas-, NULL-, FIN- und Stealth- Scan erkannt.
Die preprocessor-Anweisung schaltet diese Funktionalität folgendermaßen ein:
Das erste Argument ist die Angabe des Netzwerks, das überwacht werden soll, und an zweiter Stelle folgt die Anzahl der Ports, die in der an der dritten Stelle festgelegten Zeit vom Angreifer gescannt werden sollen. Die Zeitspanne wird dabei in Einheiten von jeweils einer Sekunde angegeben. Der letzte Parameter legt die Logdatei fest, in der die Protokollierung Portscans ablegen soll (wobei diese zusätzlich in die alert-Datei von snort geschrieben werden):
# Form preprocessor portscan: <Netzwerk> <Anzahl der Ports> <Zeitlimit> <Logdatei> # Beispielsweise preprocessor portscan: 10.34.53.0/24 5 10 /var/log/snort/scans
Listing 23.16 preprocessor portscan
Regel überlisten
Hier muss also innerhalb von 10 Sekunden ein Bereich von mindestens 5 Ports abgescannt werden, bevor ein Portscan erkannt wird, was uns zu einer ganz anderen Problematik bringt: Einige Tools scannen absichtlich Portbereiche äußerst langsam ab. Zwar dauert dies länger, es ist aber auf obige Art und Weise sehr schwer zu entdecken. Für den Angreifer bedeutet diese Scan-Technik nicht einmal eine zu große Wartezeit, denn ein auf wenige ausgesuchte Ports ausgerichteter Scan reicht oftmals aus, um eine Sicherheitslücke zu erkennen.
ignorehosts
Mit der Anweisung »portscan-ignorehosts« können aus einer Portscan-Liste gezielt Hosts ausgetragen werden, bei denen keine Benachrichtigung bei TCP-SYN- oder UDP-Portscans erfolgen soll.
preprocessor portscan-ignorehosts: 192.168.0.3
Listing 23.17 portscan-ignorehosts
frag2
Es gibt noch weitere Preprocessor-Module, etwa frag2, das einige Features bezüglich der Fragmentierung von IP-Paketen bietet. Lädt man es ohne weitere Angabe von Parametern (etwa der seiner Speicherbegrenzung (memcap) oder der minimalen TTL eines Paketes (min_ttl)), werden maximal 4 Megabyte Hauptspeicher für diese Funktionalität verschlungen, und Pakete, deren Fragmente nicht innerhalb von 60 Sekunden eintreffen, werden verworfen. In der Default-Konfiguration ist frag2 ohne weitere Parameter eingebunden.
preprocessor frag2
Listing 23.18 Nutzung von frag2
arpspoof
Die zum Zeitpunkt des Schreibens noch experimentelle Erkennung von ARP- Spoofing könnte so einige Administratoren erfreuen.
Weitere Möglichkeiten
Dem interessierten Administrator bietet Snort noch einige weitere Module für die preprocessor-Anweisung, etwa stream4, flow (flow-port-scan), telnet_decode, rpc_decode, den Performance-Monitor oder auch http_inspect, doch sollen diese im Rahmen dieses Buches nicht näher erläutert werden.
Das output-Schlüsselwort
Mittels des Schlüsselwortes output ist es möglich, das Logging der Meldungen von snort auf verschiedenen Wegen geschehen zu lassen. Beispielsweise kann via syslog oder in Form einer binären Datei im tcpdump-Format protokolliert werden. Zudem können die Meldungen in Datenbanken geschrieben werden.
output database: log, mysql,user=admin password=pass dbname=snort host=eygo.sun
Listing 23.19 Datenbank output
Nicht nur MySQL!
Wie Sie vielleicht sogar schon durch Angabe des Wortes mysql erahnen werden, ist es möglich, Snort auf verschiedenste Datenbanken zugreifen zu lassen.
In der aktuellen Version 2.2.0 sind dies:
- Oracle
- MySQL
- PostgreSQL
- unixODBC
- MS SQL
Weitere Informationen zur Nutzung dieser Datenbank-Anbindung finden Sie in der im Snort-tarball enthaltenen Dokumentationsdatei README.database im Verzeichnis doc.
Aufbau der Snort-Regeln
Sehr wichtig – und daher bekommt sie auch einen Platz in diesem Kapitel – ist die Erstellung von Snort-Regeln. Ein Blick in die mitgelieferte Konfiguration verrät uns, wo die Regeldateien liegen und wie diese übersichtlich und komfortabel in die snort.conf eingebunden werden können.
include $RULE_PATH/local.rules include $RULE_PATH/bad-traffic.rules include $RULE_PATH/exploit.rules include $RULE_PATH/scan.rules include $RULE_PATH/finger.rules include $RULE_PATH/ftp.rules include $RULE_PATH/telnet.rules include $RULE_PATH/rpc.rules include $RULE_PATH/rservices.rules include $RULE_PATH/dos.rules include $RULE_PATH/ddos.rules ....
Listing 23.20 Einbinden der Regeldateien in snort.conf
Im Subverzeichnis rules finden sich dann auch schließlich diese Dateien. Nicht nur konfigurieren kann man mit diesen, nein, auch lernen. Denn in diesen Dateien sind hin und wieder einige Techniken versteckt, die einem vielleicht noch nicht bekannt gewesen sind.
Am besten erlernt man diese in der Regel sehr einfach zu verstehenden Inhalte, indem man sie sich anhand von Beispielen verdeutlicht. In der Datei shellcode.rules finden Sie beispielsweise die Regeln zur Erkennung von im Netzwerk übertragenen Shellcodes für verschiedenste Plattformen. <Shellcodes dienen dem Angreifer zum Starten von Programmen (meist einer Shell) über Netzwerkverbindungen. Jedoch ist es entgegen der weit verbreiteten Meinung nicht notwendig, eine Shell zu starten. Dem Angreifer ist es im Prinzip selbst überlassen, welchen Code er ausführen möchte. Mehr zu diesem Thema erfahren Sie in unserem Buch »Praxisbuch Netzwerksicherheit«.>
alert ip $EXTERNAL_NET $SHELLCODE_PORTS -> $HOME_NET any (msg:"SHELLCODE sparc setuid 0"; content:"|82 10| |17 91 D0| |08|"; reference:arachnids,282; classtype:system-call-detect; sid:647; rev:6;) alert ip $EXTERNAL_NET $SHELLCODE_PORTS -> $HOME_NET any (msg:"SHELLCODE x86 setgid 0"; content:"|B0 B5 CD 80|"; reference:arachnids,284; classtype:system-call-detect; sid:649; rev:8;) alert ip $EXTERNAL_NET $SHELLCODE_PORTS -> $HOME_NET any (msg:"SHELLCODE x86 setuid 0"; content:"|B0 17 CD 80|"; reference:arachnids,436; classtype:system-call-detect; sid:650; rev:8;)
Listing 23.21 Auszug aus shellcode.rules
Regelwörter
Regeln beginnen mit einem Regelwort, etwa alert oder log.
Diese Schlüsselwörter haben verschiedene Verhaltensweisen, zudem können eigene Regelwörter in der Konfigurationsdatei spezifiziert werden. In der mitgelieferten Konfigurationsdatei wird (auskommentiert) folgendes Beispiel mitgeliefert:
ruletype redalert { type alert output alert_syslog: LOG_AUTH LOG_ALERT output database: log, mysql, user=snort dbname=snort host=localhost }
Listing 23.22 Auszug aus snort.conf
Der Regeltyp redalert verhält sich in diesem Fall wie alert und loggt mithilfe des syslog-Daemons und der MySQL-Datenbank die mit ihm konfigurierten Meldungen.
Doch nun zurück zu den eigentlichen Regelwörtern und ihrer Bedeutung:
- alert
- Warnung ausgeben und Paket loggen
- log
- Paket loggen
- pass
- Paket nicht weiter beachten
- activate
- wie alert verhalten, jedoch zusätzlich eine dynamische Regel verwenden
- dynamic
- wie log verhalten; wird von activate aktiviert <Exzellente, weiterführende Hinweise finden Sie im »Snort-Manual«.>
Protokoll
Darauf folgt das Protokoll, im obigen Fall ist dies ip. (Shellcodes können sowohl über TCP als auch über andere Protokolle übermittelt werden. Durch Angabe von ip, einem cleveren Schachzug, spielt dies keine Rolle mehr, da jedes IP-Paket auf einen bestimmten Content untersucht werden kann.) Selbstverständlich können auch andere Protokolle, etwa tcp, angegeben werden.
Quelle und Ziel
Die Angabe einer Netzwerkadresse und eines Ports in Bezug auf die Quelle des Paketes mit anschließender Angabe der Destination erfolgt vor bzw. nach dem Pfeil. Dabei steht any für einen beliebigen Wert.
msg, content und reference
msg gibt die Logmeldung aus, und content legt die Werte, die im Paket enthalten sein müssen, fest, wobei entweder auf in Pipes gestellte Hex-Werte (wie oben zu sehen) oder auch direkt auf ASCII-Zeichen, also etwa "HEAD / HTTP/1.0", zurückgegriffen werden kann. Referenzen bieten Ihnen die Möglichkeit, sich über eine Angriffsform zu informieren. Diese Referenzen werden explizit in den Logmeldungen, in der Regel durch Links zu den Problembeschreibungen in Bugtraq o. Ä., ausgegeben.
classtype
classtype spezifiziert die Priorität der Regel, wobei eine ganze Menge von möglichen Angaben mit verschiedenen Zwecken und der Priorität high, medium oder low existieren. Diese Angaben sind in einer recht langen Tabelle im Snort-Manual zu finden.
sid und rev
sid spezifiziert einen Eintrag in der Snort Signature Database (SID), die auf http://snort.org zu finden ist. rev legt die zugehörige Version dieser SID fest.
Es gelten auch hier wieder einige Besonderheiten bei der Erstellung der Regeln. Die wichtigsten sind:
- Ausrufezeichen haben eine logische Verneinung zur Folge. Wenn also alle Pakete mit einer IP-Adressangabe außer 192.168.0.1 auf eine Regel zutreffen sollen, können Sie Folgendes schreiben: !192.168.0.1.
- Gruppierungen werden (wie bereits oben erwähnt) durch eckige Klammern gebildet. Die Separierung von Werten erfolgt durch Kommas.
- Strings werden in Anführungszeichen eingeschlossen.
- Zeilenumbrüche können über einen Backslash (\) realisiert werden.
Weiteres hierzu finden Sie in der Datei README.alert_order.