
Portscan mit PortSentry unterbinden
30. Aug 2009, 01:35
Jedes System, das ins Netz Dienste anbieten möchte, muss geöffnete Ports bereithalten, und somit besteht die Gefahr, dass Angreifer über diese offenen Tore in das System eindringen können. Als erste Instanz des Eindringens, muss der Aggressor jedoch wissen, welche Dienste ihre Services über welche Ports offerieren, um einen Überblick über mögliche Angriffspunkte zu erhalten.
Um diese offenen Ports zu finden, gibt es Portscanner. Nmap ist der wohl bekannteste. Wie der Name verrät, scannen diese Tools die Ports eines Rechners und prüfen ob der jeweilige Port offen ist.
Dies geschieht über verschiedene Methoden, meist wird ein Paket an den Port geschickt, und auf eine Antwort gewartet. Ist diese positiv, ist der Port offen, wird ein negatives Antwortpaket gesendet ist der Port geschlossen, kommt keine Antwort zurück, hat eine Firewall das Paket verworfen.
In der Regel wird weitere Kommunikation benötigt um eine Verbindung aufzubauen, da der Portscanner diese Verbindung aber gar nicht aufbauen möchte, bricht er nach dem ersten Paket ab, und die Software auf dem Server bekommt von dem Verbindungsversuch gewöhnlich nichts mit, so dass auch kein Log geschrieben werden kann. Firewalls oder Intrusion Detection Systeme (IDS) wie Snort sind aber in der Lage, diese Scans auf Netzwerkeben aufzuspüren.
Ich werde euch jetzt zeigen wie man das Tool PortSentry der Firma Psionic Technologies (aufgekauft von Cisco) für diese Aufgabe einrichtet. PortSentry lauscht an einer Menge Ports und wartet auf solche Pseudo-Connections, welche auf Portscans hinweisen (natürlich ist das Verfahren ein wenig komplizierter). PortSentry bietet dem Administrator eine Reihe von Vorteilen, unter anderem der Überwachen von UDP-Verbindungen, oder eine Vielzahl von Reaktionsmöglichkeiten durch aktive Intrusion Detection.
Wie immer gibt's im Vorfeld etwas zu installieren:
Unkonfiguriert reagiert PortSentry auf Scans nur mit einem Logeintrag in die syslog
.
Beginnen wir mit der Konfiguration der Datei /etc/portsentry/portsentry.conf
. Mit den Variablen TCP_PORTS
und UDP_PORTS
kann man festlegen, an welchen Ports das Tool lauschen soll. Es sind schon drei Konfigurationen vorhanden, je nach dem wie paranoid man sich gerade fühlt, können diese genutzt und bei Bedarf angepasst werden.
PortSentry kann auch im Stealth-Mode lauschen, damit sieht der Scanner die Ports hinter denen das Tool arbeitet nicht als offen. In diesem Fall werden die Variablen TCP_PORTS
und UDP_PORTS
ignoriert und man kann mit ADVANCED_PORTS_TCP
und ADVANCED_PORTS_UDP
eine obere Grenze festlegen, bis zu dieser werden dann alle Ports überwacht. Mit ADVANCED_EXCLUDE_TCP
und ADVANCED_EXCLUDE_UDP
hat man die Möglichkeit bestimmte Ports von dieser Range auszuschließen. Es ist recht sinnvoll die vorkonfigurierten Ports stehen zu lassen, da wir sonst Gefahr laufen nützliche Services als false positives weg zu sperren.
Mit den drei Variablen IGNORE_FILE
,HISTORY_FILE
und BLOCKED_FILE
werden Files definiert, welche zum ersten IP's/Netze enthalten die ignoriert werden sollen, zum zweiten ein Log mit den IP's die gesperrt wurden enthalten, und zum dritten ein Log mit den Rechnern die in der aktuellen Sitzung geblockt wurden.
Mit RESOLVE_HOST = "1"
werden DNS-Informationen über den angreifenden Host bezogen und mit
2
BLOCK_TCP="1"
überwachen wir sowohl den TCP- als auch UDP-Verkehr. Mit der Variablen KILL_ROUTE
legen wir fest, wie wir auf einen Scan reagieren. Es gibt einige vorgeschlagenen Kommandos, ich setze einfach eine itables-Regel, die alle Pakete von diesem Host verwirft:
Das war es im Prinzip schon. Mit SCAN_TRIGGER
kann man noch einen Wert setzen, ab diesem erst eine Reihe von Port-Connects als Scan eingestuft wird. Ich lasse den Wert bei 0, wenn man ihn erhöht verringert man aber das Risiko eines falsch Positiv's.
In der Datei /etc/default/portsentry
legt man nun fest, wie der Dient gestartet wird. Im Auslieferungszustand bindet sich das Tool an die Ports wie unter TCP_PORTS
und UDP_PORTS
festgelegt. Möchte man es jedoch im Stealth-Modus laufen lassen, ändert man die Werte indem man ein 's'
davor schreibt:
2
UDP_MODE="sudp"
Jetzt noch neu starten (/etc/init.d/portsentry restart
) und schon läuft unser IDS in Verbindung mit iptables.
Versucht man nun den Rechner zu scannen, wird folgendes in die syslog
geloggt:
2
3
4
Aug 30 01:57:21 siduxbox portsentry[2799]: attackalert: TCP SYN/Normal scan from host: 192.168.0.55/192.168.0.55 to TCP port: 80
Aug 30 01:57:21 siduxbox portsentry[2799]: attackalert: Host 192.168.0.55 has been blocked via wrappers with string: "ALL: 192.168.0.55 : DENY"
Aug 30 01:57:21 siduxbox portsentry[2852]: attackalert: Host 192.168.0.55 has been blocked via dropped route using command: "/sbin/iptables -A INPUT -s 192.168.0.55 -j DROP"
und dann für jeden weiteren gescannten Port:
2
Aug 30 01:57:21 siduxbox portsentry[2799]: attackalert: Host: 192.168.0.55/192.168.0.55 is already blocked Ignoring
Mit iptables -L
können wir jetzt eine neue DROP-Regel lesen:
2
3
4
5
6
7
8
9
10
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 192.168.0.55 anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Und wie erwartet liefert ein erneuter Portscan nichts brauchbares:
2
All 1000 scanned ports on 192.168.0.111 are filtered
Dieser Rechner ist nun disqualifiziert. Man sollte natürlich vorsichtig sein, denn man sperrt sich selbstverständlich auch ganz leicht mal selbst bei einem Test auf Funktionstüchtigkeit aus!
Um dies auszuschließen gibt es die Datei /etc/portsentry/portsentry.ignore.static
. Hier kann man einzelne IP's oder ganze Netze von der Sperrung ausschließen. Danach Neustarten nicht vergessen!
Wie bei iptables üblich, sind alle Regeln nach einem Neustart futsch und die Angreifer dürfen nochmal ihr Glück probieren. Um dies zu unterbinden, habe ich mir ein kleines Start/Stop-Skript geschrieben, welches mir die Regeln sichert und wieder einließt (/etc/init.d/iptables.sh (1,43 KB) ):
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
### BEGIN INIT INFO
# Provides: iptables
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: save und restore iptable-rules
# Description: save und restore iptable-rules
### END INIT INFO
# Ordner in dem die IP-Tables
# gescpeichert werden sollen
IPT_DIR=/root/iptables/
# Name unter dem die Tables
# gespeichert werden sollen
IPT_NAME=ip.tables
RETVAL=1
# Einlesen der Regeln
start ()
{
echo "Restoring iptables..."
/sbin/iptables-restore ${IPT_DIR}${IPT_NAME}
echo "Done"
RETVAL=0
}
# Speichern der Regeln
stop ()
{
echo "Backing up iptables..."
newname=${IPT_DIR}${IPT_NAME}.`date +"%F_%H-%M-%S"`
/sbin/iptables-save > $newname
rm ${IPT_DIR}${IPT_NAME} && ln -s $newname ${IPT_DIR}${IPT_NAME}
echo "Cleaning iptables..."
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -P FORWARD ACCEPT
/sbin/iptables -P OUTPUT ACCEPT
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P POSTROUTING ACCEPT
/sbin/iptables -t nat -P OUTPUT ACCEPT
/sbin/iptables -F
/sbin/iptables -t nat -F
/sbin/iptables -X
/sbin/iptables -t nat -X
echo "Done"
RETVAL=0
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
/sbin/iptables -L
/sbin/iptables -t nat -L
RETVAL=0
;;
*)
echo “Usage: iptables.sh {start|stop|restart|status}â€
RETVAL=1
esac
exit
Das Script schreibt bei jedem stop
die aktuellen Regeln in iptables-Syntax in eine Datei in /root/iptables
und setzt einen Link darauf. Eventuell sollte man sich überlegen ob man dieses Verzeichnis per Cronjob sauber hält wenn der Rechner oft neu gestartet wird. Noch kurz in die Runlevel eintragen:
Fertig. Damit haben wir ein wenig mehr Schutz. Zumindest vor dem Gros der Script-Kiddies, denn den 100%igen Schutz gibt es bekanntlich nicht, man kann nur das Risiko vermindern. Jeder der sich ein wenig mehr mit Portscanns beschäftigt weiß sofort wie er diese Maßnahme umgeht.
Das werde ich aber hier nicht erläutern ;-)
Zum Schluss ein Link zum iptables-HowTo.
Kategorien: Betriebssystem Linux Netzwerk Software Unix