Think Simple! (was: Re: stateful firewall security holes)

Giorgos Keramidas keramida at ceid.upatras.gr
Tue Aug 29 05:55:43 EEST 2006


On 2006-08-28 16:54, zakinthinos at freemail.gr wrote:
>>On 2006-08-26 19:36, zakinthinos at freemail.gr wrote:
>>>
>>> εχει το παρακατω καποιες πιθανες τρυπες ασφαλειας ?
>>> [snip iptables setup]
>> 
>> Η ερώτηση δεν έχει νόημα, αν δεν μας πεις πρώτα τι θεωρείς "τρύπα
>> ασφαλείας".
> 
> "μπορει καποιος να περασει πακετο απο 
> την INPUT και να κανει connection σε port ?"

Ναι έχει.  Αφού εσύ ο ίδιος αφήνεις κάποια INPUT ports ανοιχτά.

Τα προβλήματα που έχει το συγκεκριμένο setup είναι πολύ περισσότερα από
κάτι τόσο απλό όσο το "αφήνει κάποια ports ανοιχτά" όμως.

> το setup βασιζεται στην δυνατοτητα των iptables να κανουν σωστο tcp
> state detection

Το `setup' αυτό είναι αδικιολόγητα πολύπλοκο.  Κάθε αύξηση στην
πολυπλοκότητα ενός πράγματος μπορεί να λειτουργήσει με δύο διαφορετικούς
τρόπους:

    - Μπορεί να κρατήσει τους "κακούς" μακριά, ακριβώς επειδή δεν
      μπορούν να καταλάβουν τι γίνεται.  Τακτική γνωστή και ως 'security
      through obscurity', και πολύ αμφίβολης γενικής αξίας.

    - Μπορεί να μπερδέψει κάποιον που κάνει αλλαγές σε αυτό και να τον
      οδηγήσει σε "λάθος" αλλαγές, οι οποίες -- τελικά -- αντί να
      αυξάνουν την ασφάλεια του συστήματος, την μειώνουν.

Μάντεψε τι συμβαίνει πιο συχνά.

> πχ. με κατασκευη custom πακετου που θα υποδυεται το ανηκων σε ηδη
> established connection ωστε να καταφερει να διαπερασει την INPUT και
> να κανει connection σε καποιο port

<flamebait>
Το 'ανήκον' είναι ουδέτερο και δεν είμαι σίγουρος αν υπάρχει καν ως
ιδιαίτερα δόκιμη λέξη.

Σε ένα άλλο flamewar, θα γράψω για το πόσο άσχημη είναι η επιτηδευμένα
"φτιαχτή" κομψότητα της προσποιητής καθαρευουσιάνικης χροιάς, και στον
προφορικό αλλά και, πολύ περισσότερο, στον γραπτό λόγο.  Ειδικά όταν
καταλήγει σε ατοπήματα όπως το παραπάνω, τα οποία την κάνουν να φαίνεται
τόσο ανούσιο, κενό και άσχημο ξόανο όσο πραγματικά είναι.

Μετάφραση: άσε την αρχαΐζουσα στον τάφο της και γράφε καθαρά, με όσο πιο
μεγαλύτερη ακρίβεια και σαφήνεια μπορείς, κατανοητά Ελληνικά :P
</flamebait>

> ισως (?) λιγο τραβηγμενο αλλα τα iptables 
> εχουν bugs, true ? 

`True', αλλά τι σχέση έχει αυτό;  Και ένα σωρό άλλα πράγματα έχουν
'bugs', αλλά αυτό δε μας εμποδίζει να τα χρησιμοποιούμε μέσα στα όρια
των δυνατοτήτων τους.

> http://lists.hellug.gr/pipermail/linux-greek-users/2006-August/064592.html

ΟΚ, είπα να μη γίνω *ΠΟΛΥ* κακός, αλλά με προκαλείς.

Που είναι τα σχόλια που εξηγούν *ΓΙΑΤΙ* υπάρχει κάθε κανόνας στο
firewall ruleset σου;

Ενα ενδεικτικό ruleset με σχόλια που είναι χρήσιμα και εξηγούν γιατί
υπάρχει κάθε κανόνας εκεί είναι:

    #       $FreeBSD: src/etc/pf.conf,v 1.3 2006/01/27 17:16:20 mlaier Exp $
    #       $OpenBSD: pf.conf,v 1.21 2003/09/02 20:38:44 david Exp $
    #
    # See pf.conf(5) and /usr/share/examples/pf for syntax and examples.
    # Required order: options, normalization, queueing, translation, filtering.
    # Macros and tables may be defined and used anywhere.
    # Note that translation rules are first match while filter rules are last match.
    
    ##############################################################################
    # Misc tables:
    ##############################################################################
    
    # A table of IP addresses which will be allowed to connect to TCP:6000 (the
    # currently active X11 session).  The current list of addresses can be seen
    # or modified with the pfctl(8) utility, i.e:
    #
    #    # pfctl -t xclients -T show
    #    # pfctl -t xclients -T add    10.0.0.1
    #    # pfctl -t xclients -T delete 10.0.0.1
    #
    table <xclients> {}
    
    ##############################################################################
    # Options:
    ##############################################################################
    
    # Blocked ports can generate valid ICMP responses, when hit.
    set      block-policy return
    set      require-order yes
    #set     limit { states 10000, frags 5000 }
    set      skip on lo0
    
    ##############################################################################
    # Normalization:
    ##############################################################################
    
    # Reassemble fragments and resolve or reduce traffic ambiguities.
    scrub    in all
    
    ##############################################################################
    # Packet filtering rules:
    ##############################################################################
    
    # The default firewall policy is to block everything.
    block    in  log all
    block    out log all

    # Allow all ICMP packets through.  They are mostly useful and rate-limited by
    # the FreeBSD kernel anyway.  See the icmp(4) manpage for a description of the
    # net.inet.icmplim* tunables, for more details.
    pass     in  proto icmp all
    pass     out proto icmp all
    
    # Allow all outgoing connections.
    pass     out proto { tcp, udp } all keep state (no-sync)
    
    # Allow some incoming connections.
    pass     in  proto tcp from any         to any port =   22 keep state (no-sync)
    pass     in  proto tcp from any         to any port =   80 keep state (no-sync)
    pass     in  proto tcp from any         to any port =  113 keep state (no-sync)
    pass     in  proto tcp from <xclients>  to any port = 6000 keep state (no-sync)

Το δικό σου firewall ruleset, θα μπορούσε ίσως να είναι πιο χρήσιμο και
πιο κατανοητό σε κάποιον που θα το δει ένα χρόνο μετά, αν ...

1) έσβηνες τα άχρηστα 'DROP' από το τέλος (είναι εντελώς άχρηστα και
   παραπλανητικά, αφού το default policy κάθε chain αρκεί για να κάνεις
   ακριβώς το ίδιο πράγμα με πιο απλό τρόπο).  Αναφέρομαι στις γραμμές:

        iptables -A INPUT -j DROP
        iptables -A OUTPUT -j DROP
        iptables -A FORWARD -j DROP

2) εξηγούσες γιατί ενεργοποιείς κάποιες τιμές στο /proc/sys/net και τι
   σημαίνει η καθεμία από αυτές

3) εξηγούσες γιατί το 127.0.0.1 έχει σημασία να έρχεται μόνο από ή προς
   το lo interface

4) άλλαζες τη σειρά με την οποία κάνεις 'flush' και set το default
   policy στα chains σου (έτσι δεν εξαρτάται η λειτουργία του firewall
   από το τι κάνει το 'flush' με το policy)

5) φιλτράρεις τα πακέτα στο *OUTPUT* chain, με βάση το interface τους
   και το αν έχουν source 127.0.0.1.  Γιατί να μην κάνεις τότε όμως το
   ίδιο με το IP address του PPP interface σου στο `lo' interface, ή στο
   `internal LAN' interface, ή να μην κάνεις το ίδιο με το `internal
   LAN' IP address σου στο `lo' και στο PPP interface.

   Όπως καταλαβαίνεις, αυτή η ιδέα *δεν* είναι τόσο καλή, γιατί
   δημιουργεί την ανάγκη για NxN κανόνες στο `hot path' του firewall
   ruleset σου, όπου `N' ο αριθμός από τα interfaces που έχεις.  Και
   κάθε φορά που προσθέτεις ένα interface ακόμα, θα πρέπει να θυμάσαι να
   προσθέσεις και (2*N + 1) κανόνες ακόμα[1].  Αλλη δουλειά δεν είχαμε,
   να καθόμαστε να μετράμε κανόνες τώρα :P

6) Εχεις ένα σωρό άχρηστους κανόνες στο INPUT chain, για να κάνουν
   explicitly 'DROP' συγκεκριμένες περιπτώσεις.  Αντί να κάθεσαι να
   ασχολείσαι με κάθε μία περίπτωση ξεχωριστά, άσε το default INPUT
   chain policy να τα μαζέψει όλα κάτω από την ίδια, πανέμορφη 'DROP'
   ομπρέλα.

7) Κάνεις log πάρα πολλά πράγματα, αλλά αυτό δεν είναι απαραίτητα κακό
   αν έχεις ένα τρόπο να γίνονται rotate & archive τα τεράστια logs που
   θα βγουν.  Μπορεί να σε καθυστερεί σημαντικά όμως το logging τόσων
   πακέτων στο δίσκο.

8) Επιτρέπεις έτσι απλά και ανενδοίαστα όλα τα incoming connections για
   ports από 1024 και άνω.  ΑΥΤΟ ΔΕΝ ΕΙΝΑΙ ΚΑΛΗ ΙΔΕΑ!  Υπάρχουν περίπου
   64.510 διαφορετικοί λόγοι γιατί αυτό είναι βλακεία, αλλά θα σε αφήσω
   να τους ανακαλύψεις ξεχωριστά τον καθένα, καθώς θα στήνεις νέα
   services στο μηχάνημά σου.

Για να μην τα πολυλογούμε, όλο εκείνο το τερατούργημα πολυπλοκότητας που
προσπάθησες να γράψεις στο email

    http://lists.hellug.gr/pipermail/linux-greek-users/2006-August/064592.html

Μπορεί άνετα να αντικατασταθεί με το παρακάτω:

    iptables -F                             # Flush all chains
    iptables -X                             # Delete user-defined chains
    iptables -Z                             # Zero chain counters
    
    # Set the default chain policy for the INPUT, FORWARD and OUTPUT chains
    iptables -P INPUT DROP
    iptables -P FORWARD DROP
    iptables -P OUTPUT DROP
    
    echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
    echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
    echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
    echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
    
    # Allow everything on `lo', as long as it goes to *and* comes from
    # the 127.0.0.1 IP address.  The default firewall policy will take
    # care of dropping any other case that isn't allowed here.
    iptables -A INPUT  -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
    iptables -A OUTPUT -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
    
    iptables -A OUTPUT -m conntrack --ctstate NEW,ESTABLISHED,RELATED -s $PPP_LOCAL -j ACCEPT

Ποτέ δε μπόρεσα να καταλάβω γιατί ο κόσμος έχει την τάση να γράφει
τεράστια κατεβατά από κανόνες, shell scripts, περίεργους συνδυασμούς από
αλληλοεξαρτήσεις, ολόκληρους Πύργους της Βαβέλ[2], για να πει το πιο απλό
πράγμα στον κόσμο:

    "Το Internet δεν είναι πλέον τόσο φιλικό όσο παλιά.  Έτσι κι εγώ τα
    κάνω DROP όλα κι αφήνω μόνο τα OUTPUT connections, άντε βαριά και
    κανένα INPUT ssh connection."

Όπως θα λεγε κι ο Steve Jobs, αν δεν είχε φτιάξει την Apple:

    ``Think simple!''





--- Σημειώσεις ------------------------------------------------------------

[1] Τα νέα interfaces είναι N+1, οπότε συνολικά θα πρέπει να προσθέσεις
    (N + 1)^2 - N^2 κανόνες = (N^2 + 2*N + 1) - N^2 = 2*N + 1.

[2] Σαν το απαίσιο κατασκεύασμα που υπάρχει, για παράδειγμα, εδώ:
    http://firewall.lutel.pl/download/0.92/firewall




More information about the Linux-greek-users mailing list