The BSD mascot drawed by Tatsumi Hosokawa
  Chuck's corner (site title)

Home
  Welcome!
  Who's that Chuck? [FR]

Articles
  Computer forensics [FR]
  Virtual-to-Remote Physical [FR]
  Promethee, educ. intranet [FR]
  Frenzy, live mini CD [FR]
  Open/Closed source sec. [FR]
  Installing FreeBSD 5 [FR]
  Powered by Unknown! [FR]
    FreeBSD / Nmap (1/2) [FR]
    FreeBSD / Nmap (2/2) [FR]
    telnetd [FR]
    ftpd [FR]
    Apache [FR]
    Bind [FR]
    Lukemftpd [FR]
    OpenSSH [FR]
    PHP [FR]
    Qpopper [FR]
    Sendmail [FR]
    Sendmail / Smtpscan [FR]
    Sendmail / Smtpmap [FR]


  Work in progress:
  Fingerprints analyzers [FR]

Software
  Ports [FR]
  HeV project

Links
  BSD sites in french [FR]
  BSD systems list [FR]
  Projects of the month [FR]

Search
  with Google's logo

  on this site:
  
  on BSD contents:
  

Powered by Unknown !

Système FreeBSD contre Nmap (2/2)

Solutions avancées

Nous avons vu dans l'article précédent qu'il était difficile d'empêcher de manière pratique l'identification d'un système par son empreinte réseau.

Il existe cependant une solution à la fois efficace et facile à mettre en œuvre !

Cette solution consiste à retourner contre les applications de type nmap ce qui leur permet de fonctionner, en filtrant les requêtes spécifiques qu'elles emploient à l'aide d'un pare-feu.

Les tests suivants ont été réalisés entre deux machines FreeBSD 4.7-RELEASE, la machine cible étant équipée du pare-feu IPFW :

# cd /sys/i386/conf
# cp GENERIC GENERICFW
# echo "options IPFIREWALL" >> GENERICFW
# echo "options IPFIREWALL_DEFAULT_TO_ACCEPT" >> GENERICFW
# config GENERICFW
# cd ../../compile/GENERICFW
# make depend
# make
# cp kernel /
# reboot

L'empreinte réseau d'une telle machine est (pour le moment) identique à celle d'une machine sans pare-feu :

attaquant# nmap -sS -PT -PI -O -vv -T 3 defenseur \
| egrep "^TSeq|^T[1-7]|^PU"
TSeq(Class=TR%IPID=I%TS=100HZ)
T1(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=N)
T3(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T4(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(Resp=Y%DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=0%ULEN=134%DAT=E)

Pour comprendre la signification de cette empreinte, je vous invite à vous reporter à l'excellent article de l'institut SANS sur le principe des empreintes réseau.

A ce stade des opérations, il suffit de savoir que cette empreinte est constituée du résultat de 9 tests (TSeq, T1 à T7 et PU) dont nous allons maintenant attaquer les spécificités, d'abord pas à pas, puis globalement.

Les deux premiers tests sont des tests de connexion initiale sur un port TCP ouvert. Pour les contrer, nous allons procéder aux manœuvres suivantes (sachant que les seuls ports TCP ouverts sont les ports 22 (ssh), 25 (smtp) et 587 (submission)) :

defenseur# ipfw add 100 deny tcp from any to me 22,25,587 \
tcpflags \!fin,syn,\!rst,\!psh,\!ack,\!urg \
tcpoptions mss,window,\!sack,ts,\!cc
attaquant# nmap -sS -PT -PI -O -vv -T 3 defenseur \
| egrep "^TSeq|^T[1-7]|^PU"
T1(Resp=N)
T2(Resp=N)
T3(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T4(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(Resp=Y%DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=0%ULEN=134%DAT=E)

Le test T1 passe d'une réponse assez caractéristique à pas de réponse ("Resp=N"). Le résultat du test TSeq, quant à lui, disparait totalement et Nmap affiche des messages tels que :

Insufficient responses for TCP sequencing (0), OS detection may be less accurate

Il faut cependant noter que la règle de pare-feu proposée induit certains effets de bord puisqu'elle accroche 0,1 à 0,3% de paquets potentiellement licites, ce qui n'est pas négligeable...

Le test suivant (T2) étant déjà sans réponse, on ne fait rien de particulier.

Le test T3 (celui que bloquait l'option TCP_DROP_SYNFIN du noyau) est un test sur un port TCP ouvert avec une combinaison de drapeaux vraiment atypique :

defenseur# ipfw del 100
defenseur# ipfw add 100 deny tcp from any to me 22,25,587 \
tcpflags fin,syn,\!rst,psh,\!ack,urg \
tcpoptions mss,window,\!sack,ts,\!cc
attaquant# nmap -sS -PT -PI -O -vv -T 3 defenseur \
| egrep "^TSeq|^T[1-7]|^PU"
TSeq(Class=TR%IPID=I%TS=100HZ)
T1(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=N)
T3(Resp=N)
T4(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(Resp=Y%DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=0%ULEN=134%DAT=E)

Le test T4 est un test d'acceptation de connexion sur un port TCP ouvert :

defenseur# ipfw del 100
defenseur# ipfw add 100 deny tcp from any to me 22,25,587 \
tcpflags \!fin,\!syn,\!rst,\!psh,ack,\!urg \
tcpoptions mss,window,\!sack,ts,\!cc
attaquant# nmap -sS -PT -PI -O -vv -T 3 defenseur \
| egrep "^TSeq|^T[1-7]|^PU"
TSeq(Class=TR%IPID=I%TS=100HZ)
T1(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=N)
T3(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T4(Resp=N)
T5(Resp=Y%DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=0%ULEN=134%DAT=E)

Les tests T5 à T7 sont des tests sur un port TCP fermé, qu'un pare-feu est justement habituellement là pour filtrer (c'est également ce que fait la fonctionnalité de "blackhole" sur les ports TCP décrite dans l'article précédent) :

defenseur# ipfw del 100
defenseur# ipfw add 100 deny tcp from any to me 0-21
defenseur# ipfw add 101 deny tcp from any to me 23,24
defenseur# ipfw add 102 deny tcp from any to me 26-586
defenseur# ipfw add 103 deny tcp from any to me 588-1023
defenseur# ipfw add 104 deny tcp from any to me 1024-65535 setup
attaquant# nmap -sS -PT -PI -O -vv -T 3 defenseur \
| egrep "^TSeq|^T[1-7]|^PU"
TSeq(Class=TR%IPID=I%TS=100HZ)
T1(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=N)
T3(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T4(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(Resp=N)
T6(Resp=N)
T7(Resp=N)
PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=0%ULEN=134%DAT=E)

A noter : les règles de pare-feu données ici ne sont là que pour illustrer cet article (pour un système utilisé comme station de travail, il ne faudrait pas nécessairement procéder ainsi...).

Le test PU est un test sur un port UDP fermé (ici également, voir la fonctionnalité de "blackhole" sur les ports UDP) :

defenseur# ipfw del 100 101 102 103 104
defenseur# ipfw add 100 deny udp from any to me
attaquant# nmap -sS -PT -PI -O -vv -T 3 defenseur \
| egrep "^TSeq|^T[1-7]|^PU"
TSeq(Class=TR%IPID=I%TS=100HZ)
T1(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=N)
T3(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T4(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(Resp=Y%DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(Resp=N)

Encore une fois, la règle utilisée ici est un peu excessive. On aurait pu, par exemple, se contenter d'un ipfw add 100 deny udp from any to me 1 puisque Nmap suppose (incorrectement) que le port 1 n'est pas protégé par un pare-feu :

For OSScan assuming that port 22 is open and port 1 is closed and neither are firewalled

La solution intégrée

En définitive, on remarque que pratiquement tous les tests de Nmap ont recours à une combinaison d'options très particulière, qu'on ne rencontre que très peu dans la nature. Il est donc possible de condenser toutes les opérations précédentes en seulement deux règles :

defenseur# ipfw del 100
defenseur# ipfw add 100 deny tcp from any to me \
tcpoptions mss,window,\!sack,ts,\!cc
defenseur# ipfw add 200 deny udp from any to me 1
attaquant# nmap -sS -PT -PI -O --osscan_guess -vv -T 3 defenseur
Starting nmap V. 3.10ALPHA3 ( www.insecure.org/nmap/ )
Host defenseur appears to be up ... good.
Initiating SYN Stealth Scan against defenseur
Adding open port 22/tcp
Adding open port 587/tcp
Adding open port 25/tcp
The SYN Stealth Scan took 9 seconds to scan 1604 ports.
For OSScan assuming that port 22 is open and port 1 is closed and neither are firewalled
Insufficient responses for TCP sequencing (0), OS detection may be less accurate
For OSScan assuming that port 22 is open and port 1 is closed and neither are firewalled
Insufficient responses for TCP sequencing (0), OS detection may be less accurate
For OSScan assuming that port 22 is open and port 1 is closed and neither are firewalled
Insufficient responses for TCP sequencing (0), OS detection may be less accurate
Interesting ports on defenseur:
(The 1601 ports scanned but not shown below are in state: closed)
Port       State       Service
22/tcp     open        ssh                     
25/tcp     open        smtp                    
587/tcp    open        submission              
Too many fingerprints match this host for me to give an accurate OS guess
TCP/IP fingerprint:
SInfo(V=3.10ALPHA3%P=i386-unknown-freebsd4.7%D=11/13%Time=3DD2BFCF%O=22%C=1)
T1(Resp=N)
T2(Resp=N)
T3(Resp=N)
T4(Resp=N)
T5(Resp=N)
T6(Resp=N)
T7(Resp=N)
PU(Resp=N)

Nmap run completed -- 1 IP address (1 host up) scanned in 34.862 seconds

Voilà ! Il y a encore d'autres façons de traiter ce problème (notamment avec des programmes altérant le fonctionnement de la pile IP), mais je trouve que ce genre de solution a le mérite de la simplicité (suivant le bon vieux "principe du bisou"1).

Quelques notes complémentaires

Il existe une option du noyau, RANDOM_IP_ID, qui ne permet d'altérer que le test TSeq (ce qui la met au même niveau d'efficacité relative que TCP_DROP_SYNFIN, c'est-à-dire qu'elle empêche l'identification du système par Nmap sans l'option scan_guess), mais reste malgré tout intéressante en complément de l'approche par pare-feu :

# more /sys/i386/conf/LINT
# RANDOM_IP_ID causes the ID field in IP packets to be randomized 
# instead of incremented by 1 with each packet generated. This 
# option closes a minor information leak which allows remote 
# observers to determine the rate of packet generation on the 
# machine by watching the counter. 

Sur un noyau l'intégrant, elle donne ceci :

# nmap -sS -PT -PI -O -vv -T 3 defenseur
Starting nmap V. 3.10ALPHA3 ( www.insecure.org/nmap/ )
[...]
TSeq(Class=TR%IPID=RD%TS=100HZ)
T1(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=N)
T3(Resp=Y%DF=Y%W=E000%ACK=S++%Flags=AS%Ops=MNWNNT)
T4(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(Resp=Y%DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=0%ULEN=134%DAT=E)


Uptime 0.004 days (since Tue Nov 12 00:33:10 2002)
TCP Sequence Prediction: Class=truly random
                         Difficulty=9999999 (Good luck!)
TCP ISN Seq. Numbers: 87880010 9AC064AC E3C94638 8914CB4B
IPID Sequence Generation: Randomized

Nmap run completed -- 1 IP address (1 host up) scanned in 30.641 seconds


  1. En V.O. KISS pour "Keep It Simple, Stupid!" :-)

[ French flag Version française | Legal information [FR] | About us [FR] | Manifesto [FR] | Privacy & usage charter [FR] | Contact us | Comments on this page ]
[ FreeBSD ring | Sites list | Go to: previous 5 - previous one - random pick - next one - next 5 ]