Επόμενο Προηγούμενο Περιεχόμενα
Σε αυτή την ενότητα θα εξετάσουμε τις επιθέσεις DOS και
τα μέτρα που μπορούμε να πάρουμε για να αμυνθούμε.
Κατόπιν θα αναφέρουμε διάφορες βασικές αρχές για τις
δικτυακές σας περιπέτειες, που (ελπίζω) θα σας γλιτώσουν
από πολλές δυσάρεστες γνωριμίες...
Αυτές
οι επιθέσεις έχουν σαν σκοπό τους να μην επιτρέψουν
στο σύστημά μας να επιτελέσει τον στόχο του. Δηλαδή, αν
έχουμε κάποιον server που παρέχει υπηρεσίες email για μια
εταιρεία, ο σκοπός της επίθεσης DoS είναι να μη μπορεί
πλέον ο συγκεκριμένος server να παρέχει αυτές τις
υπηρεσίες. Οι επιθέσεις αυτές είναι ή μέρος μιας
ιδιαίτερα συντονισμένης και μελετημένης επίθεσης (οπότε
δε μας σώζει τίποτα), ή το τελευταίο στάδιο της
απογοήτευσης για έναν φιλόδοξο επιτιθέμενο που δεν μπορεί
να μπει στο σύστημά μας και απλά καταφεύγει στην επίδειξη
δύναμης, προσπαθώντας να μας "πετάξει έξω από το δίκτυο".
Υπάρχουν πολλές περιπτώσεις στις οποίες επιθέσεις DoS
έχουν χρησιμοποιηθεί για να επιτευχθεί κάποιος άλλος
σκοπός. Παράδειγμα: Ο επιτιθέμενος καταφέρνει προσωρινό
DoS ενός SSH server για 10 κρίσιμα λεπτά. Σε αυτά τα 10
λεπτά, κάποιος νόμιμος χρήστης προσπαθεί να συνδεθεί στον
SSH server, αλλά ο επιτιθέμενος δίνει στο μηχάνημά του
την IP του SSH server (που δεν μπορεί να απαντήσει), και
προσκαλεί τον χρήστη να συνδεθεί στο μηχάνημά του. Ο
χρήστης βλέπει ένα περίεργο
μήνυμα ότι το fingerprint του server έχει αλλάξει,
λέει "ώχου μωρέ τώρα" και επιλέγει να συνδεθεί, αγνοώντας
το μήνυμα. Ο επιτιθέμενος δέχεται την σύνδεση του
χρήστη-θύματος, σταματάει το DoS του πραγματικού SSH
server, και επιπροσθέτως του στέλνει όλα τα πακέτα του
θύματος. Αποτέλεσμα; Ο χρήστης κάνει κανονικά τη δουλειά
του στον server, και ο επιτιθέμενος βλέπει και καταγράφει
τα πάντα σε clear text, μαθαίνοντας συνθηματικά,
λογαριασμούς, άλλους κωδικούς, προσωπικά στοιχεία του
θύματος, κτλ. Συγχαρητήρια, μόλις λάβατε μέρος σε μια
επίθεση man-in-the-middle. Το συγκεκριμένο σενάριο μπορεί
να πραγματοποιηθεί πανεύκολα με παλιά SSH πρωτόκολλα και
το εκπληκτικό πακέτο dsniff.
Δυστυχώς δεν υπάρχει καμία καθολική λύση για το πρόβλημα
των DoS. Για την ακρίβεια, με την άνθιση των DDoS
(Distributed Denial of Service) επιθέσεων, τα πράγματα
γίνονται διαρκώς χειρότερα. Πάντως, μερικά βήματα που
μπορούμε να ακολουθήσουμε για να αντιμετωπίσουμε τις πιο
παραδοσιακές επιθέσεις DoS ( SYN
floods και ping floods) είναι τα εξής:
#!/bin/bash
# Ενεργοποιούμε προστασία έναντι επιθέσεων SYN flood
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# Μην απαντάς σε ICMP echo requests (προστατεύει έναντι ping floods)
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
Επίσης μπορούμε να χρησιμοποιήσουμε το module LIMIT που
παρέχει το netfilter,
το σύστημα που διαχειρίζεται τα πακέτα στο επίπεδο του
πυρήνα, με κάτι σαν:
iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT
Αυτός ο κανόνας λέει στον πυρήνα να δέχεται μόνο μία νέα
TCP σύνδεση ανά δευτερόλεπτο, και να αγνοεί τις
υπόλοιπες. Γενικά ο πυρήνας έχει αρκετές δυνατότητες
άμυνας έναντι DoS επιθέσεων μέσω του συστήματος netfilter
και των ρυθμίσεων στον κατάλογο /proc/sys/net/ipv4.
...ή, πόσο μεγάλο στόχο δίνουμε.
Εκτός από τις DoS, που έχουν έναν πολύ συγκεκριμένο
σκοπό, υπάρχουν και άλλες επιθέσεις, που συνήθως έχουν
σκοπό την εκμετάλλευση κάποιου bug σε ένα service του
υπολογιστή μας. Παράδειγμα: Υπάρχουν "εργαλεία" που
μπορεί να βρει ο καθένας στο Internet, και να δίνουν
άμεσο root access αν χρησιμοποιηθούν εναντίον συστημάτων
που τρέχουν παλιές εκδόσεις του HTTP server Apache. Όσο
γρήγορα και να αναβαθμίζουμε το σύστημά μας όταν ο
διανομέας βγάζει patches που κλείνουν αυτές τις τρύπες,
υπάρχει πάντα μια ακαθόριστη περίοδος προτού
γνωστοποιηθεί το bug, κατά την οποία το σύστημά μας είναι
ευάλωτο. Ό,τι και να κάνουμε, και όσα firewalls και να
έχουμε, κάποτε συμβαίνει σε όλους.
Οπότε εκτός από τα άμεσα patches, μια πολύ καλή
ιδέα είναι να μην έχετε κανένα ενεργό service στο σύστημά
σας, εκτός από τα τελείως απαραίτητα. Έτσι οι ευκαιρίες
για εκμετάλλευση bugs ελαχιστοποιούνται, επειδή κανείς
δεν μπορεί να εκμεταλλευτεί ένα πρόγραμμα που δεν τρέχει!
Αυτές οι επιθέσεις είναι πιο δύσκολες στον εντοπισμό από
τις DoS, μιας και δεν δημιουργούν άμεσα προβλήματα στο
σύστημά μας. Σχεδόν όλες ξεκινούν με αναγνωριστικές
κινήσεις, όπως portscans και προσπάθειες σύνδεσης σε
συνήθεις πόρτες (80-http, 22-ssh, 23-telnet, 25-smtp,
110-pop3 κτλ). Η καλύτερη άμυνα είναι να ρυθμίσουμε το
μηχάνημά μας ώστε να μη δίνει καν στόχο. Η κλασσική λύση
που ακούγεται παντού είναι ένα firewall, αλλά υπάρχει
κάτι πολύ πιο σημαντικό: το να κλείσουμε οποιαδήποτε
πόρτα / δικτυακό service δεν χρειαζόμαστε.
Μία default εγκατάσταση μιας μοντέρνας "φιλικής προς το
χρήστη" διανομής, συνήθως αφήνει πολλές περιττές πόρτες
ανοιχτές στον υπολογιστή μας. Μπορούμε να δούμε ποια
services έχουμε ενεργά με ένα
# lsof -i
ή, από την μεριά του επιτιθέμενου (χρήσιμο για να
καταλάβουμε τι μπορούν να δουν οι άλλοι για το μηχάνημά
μας):
# nmap <η_ΙΡ_μου>
Για να δούμε τι βλέπω για το σύστημά μου:
# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
privoxy 14769 privoxy 3u IPv4 173542 TCP localhost.localdomain:6969
(LISTEN)
# ifconfig wlan0
wlan0 Link encap:Ethernet HWaddr 00:20:E0:8D:01:2D
inet addr:192.168.1.106 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:58578 errors:0 dropped:0 overruns:0 frame:0
TX packets:69317 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:34820912 (33.2 MiB) TX bytes:2989402 (2.8 MiB)
# nmap -p1-65535 192.168.1.106
Starting nmap V. 3.10ALPHA4 ( www.insecure.org/nmap/ )
All 65535 scanned ports on 192.168.1.106 are: closed
Nmap run completed -- 1 IP address (1 host up) scanned in 100.306 seconds
Τί μας λένε τα παραπάνω; Με την εντολή lsof -i βλέπω μια
υπηρεσία (privoxy) να "ακούει" (LISTEN) για τοπικές
συνδέσεις TCP στην πόρτα 6969 (TCP
localhost.localdomain:6969). Αλλά το nmap μου λέει ότι
όλες οι πόρτες είναι κλειστές! Τι γίνεται εδώ;
Ο privoxy στην συγκεκριμένη περίπτωση "ακούει" μόνο για
συνδέσεις στη διεύθυνση localhost.localdomain:6969.
Επειδή αυτό το όνομα δεν είναι δυνατόν να χρησιμοποιηθεί
για απομακρυσμένες δικτυακές συνδέσεις (είναι alias για
το τοπικό μηχάνημα, και δεν μπορεί να χρησιμοποιηθεί σαν
δικτυακό όνομα με το παρόν σύστημα DNS), ο
privoxy φαίνεται σαν να μην υπάρχει όταν κάποιος εξετάζει
τις πόρτες μας από το δίκτυο (γι'αυτό χρησιμοποίησα την
εξωτερική μου IP στο nmap - αν είχα χρησιμοποιήσει την
127.0.0.1 θα είχα διαφορετικά αποτελέσματα). Για τις
χάρες του privoxy θα μιλήσουμε στην επόμενη ενότητα. Όπως
είδαμε, δεν φαίνεται καν να υπάρχει από το δίκτυο. Άρα
δεν το θεωρώ ευάλωτο σημείο.
Σε μια default εγκατάσταση κάποιας μοντέρνας διανομής,
δυστυχώς έχουμε μεγάλες πιθανότητες να δούμε μια ελαφρώς
διαφορετική εικόνα:
[root@helios root]# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
privoxy 14769 privoxy 3u IPv4 173542 TCP localhost.localdomain:6969
(LISTEN)
tcpserver 14781 root 3u IPv4 176623 TCP *:44444 (LISTEN)
tcpserver 14783 root 3u IPv4 176629 TCP *:2121 (LISTEN)
smbd 14793 root 9u IPv4 176648 TCP *:netbios-ssn (LISTEN)
xinetd 14814 root 5u IPv4 179758 UDP *:ntalk
httpd 14831 root 3u IPv4 185996 TCP *:http (LISTEN)
httpd 14886 apache 3u IPv4 185996 TCP *:http (LISTEN)
Όλα αυτά τα (LISTEN) δεν είναι καθόλου απαραίτητα, εκτός
κι'αν ξέρετε τι κάνετε. Αν δεν ξέρετε τι σημαίνει κάποια
καταχώρηση (όπως πχ. netbios-ssn), μπορείτε να την
αναζητήσετε στο αρχείο /etc/services για περισσότερες
πληροφορίες:
$ grep netbios-ssn /etc/services
netbios-ssn 139/tcp # NETBIOS session service
netbios-ssn 139/udp
Το μηχάνημα που δεν δείχνει τίποτα να ακούει (LISTENing),
είναι σχεδόν αόρατο στο δίκτυο. Είναι εξαιρετικά δύσκολο
για κάποιον επιτιθέμενο να το βρει και να του επιτεθεί.
Πώς ξεφορτωνόμαστε όλα αυτά τα LISTEN λοιπόν;
Ανάλογα με τη διανομή που χρησιμοποιούμε ( Debian, Slackware, Red Hat, Gentoo κτλ), υπάρχουν
διαφορετικοί τρόποι ελέγχου των υπηρεσιών (services) που
είναι ενεργές στον υπολογιστή μας. Οι περισσότερες
διανομές GNU/Linux χρησιμοποιούν System V init scripts,
δηλαδή αποθηκεύουν τα scripts που ελέγχουν τις υπηρεσίες
στους καταλόγους /etc/rcX.d, όπου Χ είναι μια τιμή από 0
έως 6. Αυτή η τιμή αντιστοιχεί στο runlevel του
συστήματος. Το runlevel στο οποίο λειτουργεί το σύστημα
αμέσως μετά την εκκίνησή του (boot) το βρίσκουμε με ένα
# grep default /etc/inittab
Στο δικό μου σύστημα αυτό δίνει:
# The default runlevel.
id:2:initdefault:
που σημαίνει ότι αν θέλω να κάνω κάποιες υπηρεσίες να μην
ενεργοποιούνται σε κάθε επανεκκίνηση, πρέπει να τις
απενεργοποιήσω από το φάκελο /etc/rc2.d .
Αν κάνουμε ένα
ls -l
μέσα σε αυτό το φάκελο, θα δούμε ότι υπάρχουν πολλά symbolic links με τα ονόματα
όλων των διαθέσιμων υπηρεσιών. Αν θέλουμε να μην ξεκινάει σε κάθε εκκίνηση ο http
daemon (httpd) (που είναι συνήθως ο
Apache), απλά σβήνουμε το link SXXhttpd (όπου ΧΧ η
προτεραιότητα με την οποία ενεργοποιείται κατά την εκκίνηση
αυτό το service).
Ωραία, ο web server δεν θα ξεκινάει σε κάθε εκκίνηση από
δω και στο εξής. Πώς όμως τον σταματάμε εδώ και τώρα;
Αν προσέξατε, όλα τα symbolic links στον κατάλογο που
είμαστε "δείχνουν" σε αρχεία του καταλόγου ../init.d
(δηλαδή στο /etc/init.d). Για να σταματήσουμε ή να
ξεκινήσουμε μια υπηρεσία αμέσως, καλούμε το script που
την ελέγχει με την παράμετρο stop ή start:
Αυτή η εντολή ενεργοποιεί άμεσα τον HTTP server:
# /etc/init.d/httpd start
Αυτή η εντολή τον σταματάει:
# /etc/init.d/httpd stop
Με αυτό τον τρόπο μπορούμε να ξεφορτωθούμε και
οποιεσδήποτε άλλες υπηρεσίες που είναι ενεργές χωρίς
λόγο. Υπενθύμιση: σε ένα home PC, η εντολή
# lsof -i
δεν πρέπει να δείχνει τίποτα που να "ακούει" (LISTEN) για
συνδέσεις από το δίκτυο (*:port_number).
ΣΗΜΕΙΩΣΗ: Υπάρχουν μερικές ειδικές περιπτώσεις, όπως το
port 6000 (X11), το οποίο είναι περιττό για το 99% των
συστημάτων για αποκλειστικά προσωπική χρήση, και έχει
γνωστά προβλήματα ασφάλειας (οποιοσδήποτε στο δίκτυο
μπορεί να δει τι πληκτρολογείτε). Οπότε είναι πολύ καλή
ιδέα να το κλείσετε, καλώντας τα X με την παράμετρο
-nolisten tcp:
$ startx -- -nolisten tcp
Tα firewalls είναι προγράμματα ή συσκευές που ελέγχουν τα
δεδομένα που ταξιδεύουν σε ένα δίκτυο. Σε προσωπικό
επίπεδο, μπορούμε να τα χρησιμοποιήσουμε για να ελέγξουμε
τις δικτυακές συνδέσεις του υπολογιστή μας και να
δυναμώσουμε την άμυνά μας έναντι δικτυακών επιθέσεων. Στο
GNU/Linux το firewalling
γίνεται από το σύστημα netfilter, που ελέγχεται
από το πρόγραμμα iptables.
Σε όλες τις μοντέρνες διανομές το σύστημα netfilter είναι
ενεργοποιημένο στον πυρήνα Linux και το πρόγραμμα
netfilter υπάρχει προεγκατεστημένο. Συνεπώς το μόνο που
έχουμε να κάνουμε είναι να δώσουμε τους κανονισμούς
σύμφωνα με τους οποίους θα διαχειρίζεται ο πυρήνας τα
δικτυακά δεδομένα που έρχονται και φεύγουν από τον
υπολογιστή μας.
Δεν θα μπούμε σε λεπτομέρειες, επειδή το firewalling
είναι αρκετά μεγάλο θέμα. Θα σας δείξω τα rules που
χρησιμοποιώ στο laptop μου, με σχόλια που θα εξηγούν τι
κάνει το κάθε rule. Το παρόν ruleset έχει βασιστεί στο
εξαιρετικό
tutorial του James C. Stephens.
#!/bin/bash
if [ -z $1 ]; then
# Δεν έχουμε command line argument, οπότε δεν αφήνουμε κανέναν να συνδεθεί με
SSH σε μας.
echo Disallowing SSH access...
NOSSH=1
else
# Έχουμε IP address στη γραμμή εντολών, που θέλουμε να συνδέεται σε μας με
SSH.
echo Allowing SSH access for $1...
fi
##############################
#### ΓΕΝΙΚΕΣ ΠΡΟΦΥΛΑΞΕΙΣ #####
##############################
## Μην απαντάς σε ping.
/bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
## Μην απαντάς σε broadcasts.
/bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
## Μη δέχεσαι source routed πακέτα.
/bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
## Μη κάνεις ICMP redirect.
/bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
## Προστασία έναντι περίεργων λαθών.
/bin/echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
## Ενεργοποίησε το reverse path filtering.
for interface in /proc/sys/net/ipv4/conf/*/rp_filter; do
/bin/echo "1" > ${interface}
done
## Σημείωσε στα system logs (/var/log/messages by default) τα πακέτα που
φαίνεται να έχουν ψεύτικες διευθύνσεις ή γενικώς να είναι ύποπτα.
/bin/echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
## Μην λειτουργείς σαν router (μην προωθείς πακέτα σε άλλες διευθύνσεις).
/bin/echo "0" > /proc/sys/net/ipv4/ip_forward
##################
#### FIREWALL ####
##################
## Φόρτωσε τα connection-tracking modules.
/sbin/modprobe ipt_state
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp #ports=2121
#/sbin/modprobe ipt_owner
## Καθάρισε τυχόν ενεργά rules
/sbin/iptables -F
## Διέγραψε τυχόν custom tables
/sbin/iptables -X
## Μηδένισε όλους τους μετρητές πακέτων
/sbin/iptables -Z
## By default κάνουμε DROP (αγνοούμε) όλα τα πακέτα (ώστε να περνάνε μόνο αυτά
που έχουν λόγο να περνάνε)
/sbin/iptables -P INPUT DROP
/sbin/iptables -P FORWARD DROP
/sbin/iptables -P OUTPUT DROP
#####################
#### ΕΙΣΕΡΧΟΜΕΝΑ ####
#####################
## Δεχόμαστε όλες τις τοπικές συνδέσεις
/sbin/iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -i lo -j ACCEPT
## Δεχόμαστε πακέτα από όλες τις ήδη υπάρχουσες συνδέσεις (λόγω των υπολοίπων
rules, αναγκαστικά τις έχουμε ξεκινήσει εμείς οπότε υποθέτουμε ότι είναι
ασφαλείς)
/sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
if [ $NOSSH ]; then
#Καθόμαστε.
echo
else
## Επέτρεψε συνδέσεις SSH από τη διεύθυνση που παρέχουμε στη γραμμή εντολών
/sbin/iptables -A INPUT -p tcp -s $1 --sport 1024: --dport 22 -j ACCEPT
fi
######################
##### ΕΞΕΡΧΟΜΕΝΑ #####
######################
## Δεχόμαστε τοπικές συνδέσεις
/sbin/iptables -A OUTPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
## SSH
/sbin/iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
## HTTP
/sbin/iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
## HTTPS
/sbin/iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
## POP3
/sbin/iptables -A OUTPUT -p tcp --dport 110 -j ACCEPT
## SMTP
/sbin/iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
## DNS
/sbin/iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
## FTP (command)
/sbin/iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j
ACCEPT
## FTP (data::Active)
/sbin/iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISHED -j
ACCEPT
## FTP (data::Passive)
/sbin/iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state
ESTABLISHED,RELATED -j ACCEPT
if [ $NOSSH ]; then
echo
else
## Επιτρέπουμε στον SSH server μας να απαντήσει.
/sbin/iptables -A OUTPUT -p tcp --sport 22 --dport 1024: -m state --state
ESTABLISHED,RELATED -j ACCEPT
fi
## ICMP
/sbin/iptables -A OUTPUT -p icmp -j ACCEPT
## dict.org:2628
/sbin/iptables -A OUTPUT -p tcp -d 66.111.36.30 --dport 2628 -j ACCEPT
## Importing OpenPGP keys από pgp.mit.edu:11371
/sbin/iptables -A OUTPUT -p tcp -d 18.7.14.139 --dport 11371 -j ACCEPT
## JETDIRECT printing
/sbin/iptables -A OUTPUT -p tcp --dport 9100 -j ACCEPT
## Whois queries
/sbin/iptables -A OUTPUT -p tcp --dport 43 -j ACCEPT
## NTP updates
/sbin/iptables -A OUTPUT -p tcp -d 128.2.4.21/16 --dport 123 -j ACCEPT
/sbin/iptables -A OUTPUT -p udp --sport 123 -d 128.2.4.21/16 --dport 123 -j
ACCEPT
#################
#### LOGGING ####
#################
## Αυτά τα μηνύματα καταχωρούνται στο /var/log/messages
## Με ένα tail -f /var/log/messages σαν root τα παρακολουθούμε
## Log εισερχόμενα TCP πακέτα που απορρίφθηκαν.
/sbin/iptables -A INPUT -p tcp -j LOG --log-prefix "iptables:IN-TCP DROPPED:"
## Log εξερχόμενα TCP πακέτα που απορρίφθηκαν.
/sbin/iptables -A OUTPUT -p tcp -j LOG --log-prefix "iptables:OUT-TCP DROPPED:"
## Log οτιδήποτε άλλο που δεν πέρασε
#/sbin/iptables -A INPUT -j LOG --log-prefix "iptables:INCOMING DROPPED:"
/sbin/iptables -A OUTPUT -j LOG --log-prefix "iptables:OUTGOING DROPPED:"
## Τέλος του iptables script
Μπορείτε να κατεβάσετε αυτό το script και σε ASCII μορφή για πιο εύκολη χρήση. Το
script πρέπει να ανήκει στον root και να είναι
executable:
# chown root:root fw.rules
# chmod 770 fw.rules
...και το εκτελείτε. Τα αποτελέσματα τα βλέπετε με ένα
# iptables -L
Επόμενο Προηγούμενο Περιεχόμενα