[ Aufbau eines IDS Systems mit Linux Boardmitteln ]

 

Inhalt

1. Theorie - Aufbau eines IDS Systems
1.1 Was ist ein IDS (Intrusion Detection System)?
1.2 Was wird benötigt?

2. Praxis - Aufbau eines IDS Systems
2.1 Firewalling - Entwerfen eines iptables Skrips und einbinden in das System
2.2 syslog-ng konfigurieren
2.3 Ausgabe mit tail

3. EOF
 

1. Theorie - Aufbau eines IDS Systems

1.1 Was ist ein IDS (Intrusion Detection System)?

Unter einem IDS versteht man ein System zum Erkennen von Eindringlingen (Intrusion Detection System). Unter einem Eindringling (Intruder) versteht man dabei eine Person, welche versucht in ein System einzubrechen um beispielsweise Daten zu stehlen oder das System für diverse bösartige Dinge zu missbrauchen. IDS Systeme überprüfen dabei den Netzverkehr um Angriffe zu erkennen. So könnte ein IDS System beispielsweise auf sehr häufige SYN Anfragen reagieren und eine entsprechende Meldung in den Logfiles hinterlassen bzw. den Administrator per Nachricht vor einem möglichen SYN Flood Angriff warnen. IDS Systeme können sich dabei relativ stark unterscheiden, je nach Verwendungszweck und gedachtem Aufgabenfeld. In diesem Text soll ein einfaches (!) IDS System mit Linux Boardmitteln erstellt werden. Unter 2. wird genannt was genau benötigt wird. Natürlich existieren bereits "fertige" IDS, welche nur entsprechend konfiguriert werden müssen. So besteht die Aufgabe des scanlog Daemon beispielsweise darin, Portscans zu melden und zu protokollieren. Snort hingegen ist ein "vollwertigeres" IDS System. Snort ermöglicht die Analyse des Netzwerkverkehrs in Echtzeit. Es können zahlreiche Attacken, wie beispielsweise CGI Attacken, SMB Probes, OS Fingerprinting, Portscans erkannt und gemeldet werden. Auf diese Programme soll in diesem Text aber wie bereits erwähnt nicht näher eingegangen werden.
 

1.2 Was wird benötigt?

iptables als Grundlage für das IDS System.
syslog-ng Daemon zum verarbeiten der von iptables erhaltenen Nachrichten.
tail zum Ausgeben der Logs.

Hinweis: In diesem Tutorial soll nicht näher auf das kompilieren der genannten Programme eingegangen werden. Den Source Codes liegen Readme's bei welche dies näher beschreiben.
 

iptables

iptables ist ein Administrations Tool zum Packet filtern und zur Network Address Translation (NAT) und ist seit dem 2.4 Kernel integraler Linux Bestandteil. Wer diesen Text verstehen will, sollte wenigstens schon einmal ein paar einfache Regeln mit iptables erstellt haben.
Wer von iptables möglicherweise noch nie was gehört hat, sollte sich vielleicht erstmal das hier...

Einführung in iptables
Mehr zu iptables...
 

...zu Gemüte führen.
Um iptables nutzen zu können, muss der Kernel iptables unterstützen und iptables als Modul installiert sein, desweiteren muss das Tool iptables vorhanden sein. Einen aktuellen Linux Kernel findet ihr hier, das Tool iptables gibts hier.
 

syslog-ng (syslog New Generation)

syslog-ng ist die "neue Generation" des syslog Daemons.
Der syslog Daemon ist für das Logging auf Linux Systemen zuständig. syslogd liest System Meldungen vom lokalen System als auch vom Netzwerk und verarbeitet diese bzw. bereitet diese auf. Dazu wird je nach Konfiguration beispielsweise /dev/log geöffnet und regelmäßig ausgelesen. Da der syslog aber relativ unflexibel ist was Logging angeht, wurde der syslog-ng entworfen. Dieser wird wahrscheinlich früher oder später (meiner Meinung nach) den syslog ersetzen und bietet wesentlich mehr Möglichkeiten was das Loggen betrifft.
Man sollte den syslogd deaktivieren, wenn der syslog-ng verwendet wird. Debian weist bei der Installation des syslog-ng daraufhin. Unter beispielsweise SuSE hingegen läuft der syslogd weiter, wenn dieser nicht deaktiviert wird. Des syslogd kann in den Runlevel Skripten deaktiviert werden.
Den syslog-ng gibt es hier.
 

tail

Wer mit der Konsole arbeitet, kennt auch tail (wer ersteres tut und letzteres nicht kennt, der lügt... :) ). tail ermöglicht es den letzten Teil von Dateien auszugeben. tail ohne weitere Option gibt dabei immer die letzten 10 Zeilen einer Datei aus.
Uns interessiert besonders die tail Option -f  bzw. --follow. Diese erlaubt es neu hinzukommende Einträge in das Logfile, auf der Konsole zu präsentieren auf der tail läuft.
 

Aus diesen 3 Programmen soll am Ende ein einfaches IDS System werden. iptables wird dabei als Firewall benutzt, welche Packete filtert und nach definierten Regeln loggt. syslog-ng liest die von iptables erzeugten Kernelnachrichten, verarbeitet und speichert sie in einem Logfile. tail gibt uns das entstandene Logfile aus.
 

2. Praxis - Aufbau eines IDS Systems

2.1 Firewalling - Entwerfen eines iptables Skripts und einbinden in das System

Nach dem alles hoffentlich ordnungsgemäß installiert wurde und läuft, kann es jetzt ans erstellen des Firewall Skripts gehen.
Dieses Skript soll dabei die Grundlage für das Tutorial bilden. Das Skript wurde mit ausreichend Kommentaren versehen und relativ einfach gehalten. Das Logging wird im Anschluss erklärt.
 
#! /bin/bash

echo "Running iptables firewall script ..."

# laden wichtiger Module - iptables Modul und Logging Modul
modprobe ip_tables ipt_LOG

#Alle TCP Packete die nicht über eth0 kommen und als Zielport einen der Ports aus der Range
#1-1023 besitzen, werden geloggt.
iptables -A INPUT -i ! eth0  -p TCP --dport 1:1023 -j LOG --log-prefix " Alert! PrivPort "

#Alle TCP und UDP Packete die nicht über eth0 kommen und als Zielport einen der Ports aus der Range
#1-1023 besitzen, werden veworfen.
iptables -A INPUT -i ! eth0 -p TCP --dport 1:1024 -j DROP
iptables -A INPUT -i ! eth0 -p UDP --dport 1:1024 -j DROP

#Alle TCP Packete mit gesetztem SYN,FIN Flags werden geloggt 
# --> es könnte sich um einen SYN,FIN Scan handeln
iptables -A INPUT -p tcp --tcp-flags ALL SYN,FIN -j LOG --log-prefix " Alert! SYNFINSCAN "

#Alle TCP Packete ohne gesetzten Flag werden geloggt
# --> es könnte sich um einen Nullscan handeln
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j LOG --log-prefix " Alert! NULLSCAN "

#Alle TCP Packete mit gesetzten FIN,PSH,URG Flags werden geloggt
# --> es könnte sich um einen XMAS Scan handeln
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j LOG --log-prefix " Alert! NMAPXMAS "

#Alle fragmentierten ICMP Packete werden geloggt
iptables -A INPUT -p icmp  -f -j LOG --log-prefix " Alert! ICMPFRAG "

#Alle TCP Packete mit dem Zielport 1080 bzw. 8080 werden geloggt
#--> möglicherweise wird nach einem Proxy gescannt
iptables -A INPUT -p tcp  -d 0/0 --dport 1080        -j LOG --log-prefix " Alert! PROXYSCAN "
iptables -A INPUT -p tcp  -d 0/0 --dport 8080        -j LOG --log-prefix " Alert! PROXYSCAN "

#Falls mehr als 40 Packete pro Minute mit gesetztem SYN Flag (connection request) eingehen
#so werden diese geloggt
iptables -A INPUT -p TCP -s ! 127.0.0.1 --tcp-flags ALL SYN -m limit --limit 40/minute -j LOG --log-prefix " Alert! SYNFLOOD "

exit 0

Nehmen wir uns eine der Regeln:
iptables -A INPUT -i ! eth0  -p TCP --dport 1:1024 -j LOG --log-prefix " Alert! PrivPort "

Was passiert?
Es wird eine Regel gesetzt, welche alle TCP Packete die nicht über eth0 kommen und als Zielport einen der Ports aus der Range 1-1024 (privilegierte Ports) besitzen, loggt, da als Ziel "LOG" angegeben wurde (-j = jump). So würde z.B. ein TCP Packet mit dem Zielport 80, welches über ein PPP Interface kommt, wie beispielsweise ppp0 (z.B. ein Modem) geloggt werden.

Wozu soll diese Regel gut sein?
Solch eine Regel wäre z.B. sinnvoll wenn auf unserem Linux Rechner ein Apache Webserver läuft und wir wöllten, das auf diesen nur vom lokalen Netzwerk aus Zugriff besteht. Ein Versuch vom Internet aus auf den Apache zuzugreifen wäre erfolglos und würde geloggt werden. So verhält es sich mit allen Service die auf unserem Linux Rechner laufen und auf den Ports 1-1024 "lauschen".
Wie man bei den ersten 3 Regeln sieht, kann man erst verdächtigen Traffic loggen lassen und anschließend unterbinden.
Würde man hingegen den Traffic erst unterbinden und dann versuchen zu loggen, würde logischerweise kein Logging stattfinden, da diese Regel nie zutreffen würde, da die entsprechenden Packete bereits vorher verworfen wurden wären.
Die anderen Regeln sind gleich aufgebaut. Das Script sollte natürlich an die Bedürfnisse angepasst werden.

Wie wir bei der Konfiguration des syslog-ng sehen werden, nützt es uns nicht viel wenn wir nur einfach Loggen lassen würden, ohne ein log-prefix anzugeben (--log-prefix). Der log-prefix ist nichts anderes als eine String der unseren Logeintrag ergänzt.
Normalerweise bestehen die Logs aus: Datum, Uhrzeit, Hostname und einer Nachricht (eine Warnung, ein Fehler..., Beispiele sind unter /var/log/messages zu finden). Wenn wir aber einen Log Prefix angeben, bestehen unsere Logs aus: Datum, Uhrzeit, Hostname UND Log-Prefix, sowie der Nachricht. Wie wir bei der Konfiguration des syslog-ng sehen werden, ist dieser Log Prefix notwendig um die Firewall Logs von anderen zu trennen und diese in ein seperates Logfile zu schreiben.
Doch bevor wir mit der Konfiguration des syslog-ng beginnen, soll unser Firewall Skript bei jedem Neustart des Systems ausgeführt werden. Damit unser firewall skript bei jedem Neustart ausgeführt wird, müssen wir unser System entsprechend anpassen. Wir machen folgendes:

chown root firewall.sh
chgrp root firewall.sh
chmod 700 firewall.sh

Besitzer, Gruppe und Rechte des Firewall Skript werden gesetzt. Als nächstes soll das Skript in eines der Startskripte hinzugefügt werden.

Debian/GNU Linux: Kopieren von firewall.sh nach /etc/rc.boot/
SuSE 8.1: Kopieren von firewall.sh nach /usr/sbin/, /usr/sbin/firewall.sh in /etc/rc.d/boot.local eintragen
RedHat und MDK: Kopieren von firewall.sh nach /usr/sbin/, /usr/sbin/firewall.sh in /etc/rc.d/rc.local eintragen

Unser Skript wird nun bei jedem Neustart ausgeführt und meldet sich mit "Running iptables firewall script ...".
 
 

2.2 syslog-ng konfigurieren

Unser Firewall Skript wurde nun erstellt und ins System eingebunden. Eigentlich sind wir damit schon fast am Ende.
Es muss lediglich noch der syslog-ng korrekt konfiguriert werden. Die Konfigurationsdatei des syslog-ng befindet sich unter /etc/syslog-ng/syslog-ng.conf . Ihr öffnet diese in eurem Lieblingseditor und fügt die rot markierten Zeilen hinzu:
 
#
# /etc/syslog-ng/syslog-ng.conf 
#
# File format description can be found in syslog-ng.conf(5).
#

options { long_hostnames(off); sync(0); };

source src { unix-dgram("/dev/log"); file("/proc/kmsg"); internal(); };
 

# own code ---begin---
destination d_firewall {file ("/var/log/ids"); };
filter firewall_filter { match("Alert!"); };
log {source(src); filter(firewall_filter); destination(d_firewall);};
# own code ---end---

filter f_newsnotice { level(notice) and facility(news); };
filter f_newscrit   { level(crit)   and facility(news); };
filter f_newserr    { level(err)    and facility(news); };
filter f_news       { facility(news); };
filter f_mail       { facility(mail); };
filter f_cron       { facility(cron); };
filter f_warn       { level(warn, err, crit); };
filter f_alert      { level(alert); };

[...]

Konfiguration des syslog-ng Daemon ist ein relativ komplexes Thema, deswegen werden hier nur die benötigten Zeilen näher erklärt.
Mehr Informationen zum syslog-ng liefert der man page zum syslog-ng bzw. das FAQ zum syslog-ng.

Source

source <identifier> { source-driver(params); source-driver(params); ... };

Vom source erhält syslog-ng seine Log Nachrichten. Nachrichten, die von Programmen erstellt wurden, werden an ein solchen Source geschickt, wo syslog-ng sie dann abfängt und weiterverarbeitet. Dabei existiert ein Standardsource wo die System Nachrichten hingeschickt werden, normalerweise ist das /dev/log. Die source Zeile wird bereits in der syslog-ng.conf schon vorhanden sein und kann beibehalten werden, wichtig ist aber das file("/proc/kmsg") hinzugefügt wird,  da über diese Datei Kernelmeldungen gelesen werden können (unsere von iptables erstellten Meldungen).

Der Identifier gibt dem Source eine eindeutige Identfikation. In unserem Fall heißt der Identifier "src". Dieser wird im weiteren Konfigurationsfile benötigt. Geholt werden die Logs von /dev/log (System Meldungen)bzw. /proc/kmesg (Kernel Meldungen).   Mit Hilfe des source-driver kann man genau festlegen welcher Treiber benutzt werden soll um zwischen Client und syslog zu kommunizieren. Der "unix-dgram" Treiber erlaubt ein Zugriff auf /dev/log über Unix Sockets, mit Hilfe des "file" Treibers können Nachrichten von der angegebenen Datei, in unserem Fall /proc/kmsg, gelesen werden.

Destination

destination <identifier> { destination-driver(params); destination-driver(params); ... };

Destination ähnelt Source. Es gibt wieder eine Identifier, in unserem Fall  "d_firewall". Das Destination gibt an wohin die Meldungen geloggt werden sollen. Dies ist bei uns die Datei /var/log/ids, welche von root im Verzeichnis /var/log/ erstellt werden sollte, z.B. mit

touch /var/log/ids
 

Filter

 filter <identifier> { expression; };

Auch hier existiert wieder ein Identifier in unserem Beispiel ist das "firewall_filter". Filter führen das "log routing" in syslog-ng aus. Sobald eine Nachricht auf einen Filter passt, sagt der Filter was mit dieser geschehen soll und wie sie weitergeleitet wird.
Es existieren folgende Filterfunktionen: facility(), level() oder priority(), program(), host(), match(). Wobei uns nur match() interessieren soll. Per match() ist es möglich die erhaltene Nachricht auf einen bestimmten Ausdruck zu überprüfen. Bei uns ist dieser Ausdruck der String "Alert!". Spätestens hier sollte klar werden wozu der Log-Prefix beim setzten der Log Regeln im Firewall Skript gebraucht wurde.
Unser Filter "firewall_filter", wird jede erhaltene Nachricht auf den String "Alert!" durchsuchen.
 

Log

log { source(source-identifier);  filter(filter-identifier);  destination(destination-identifier); };

Log ist dafür zuständig Source, Destination und Filter zusammenzuführen. Alle Nachrichten die von Source "src" kommen (in unserem Beispiel /dev/log und /proc/kmsg) und auf den Filter "firewall_filter" (in unserem Beispiel alle Nachrichten die den String "Alert!" enthalten) passen, werden nach Destination "d_firewall" (bei uns /var/log/ids) geschrieben.
 

2.3 Ausgabe mit tail

Wie bereits zu Beginn erwähnt,  können jetzt die nach /var/log/ids geschriebenen Logs unter Zunahme von tail angezeigt werden.
tail /var/log/ids würde dabei nur die letzten 10 Zeilen des Logfiles ausgeben. Ein tail -f /var/log/ids hingegen, gibt aktuelle von syslog-ng nach /var/log/ids geschriebenen Logs aus.
Ein Eintrag kann beispielsweise so aussehen:

Datum   Uhrzeit   Hostname  Log Prefix      Nachricht
Mar 27 18:02:47 deepblack Alert! PrivPort IN=lo OUT= MAC=****** SRC=192.168.0.1 [...]
 
 
 

3. EOF
Nun sind wir am Ende dieser Einführung ins Thema "Selbstbau IDS" angekommen. Verbesserungsvorschläge und Hinweise bzw. Fehler jeglicher Art bitte an die unten genannte Addresse.
 

So long....
unex
 

Autor: unex (www.yassp.de)
Kontakt/Verbesserungsvorschläge: unex at gmx dot de
Version: Version 1.0 - 3/2003