Magaz, The Greek Linux Magazine
Magaz Logo

Επόμενο  Προηγούμενο  Περιεχόμενα

2. Δικτυακή ασφάλεια

Σε αυτή την ενότητα θα εξετάσουμε τις επιθέσεις DOS και τα μέτρα που μπορούμε να πάρουμε για να αμυνθούμε. Κατόπιν θα αναφέρουμε διάφορες βασικές αρχές για τις δικτυακές σας περιπέτειες, που (ελπίζω) θα σας γλιτώσουν από πολλές δυσάρεστες γνωριμίες...

2.1 Επιθέσεις Denial of Service (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.

2.2 Network Visibility

...ή, πόσο μεγάλο στόχο δίνουμε.

Εκτός από τις 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

2.3 Firewalls

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

Επόμενο  Προηγούμενο  Περιεχόμενα


Valid HTML 4.01!   Valid CSS!