Simple UDP "port unreachable" port scanner
Di seguito un semplice codice di esempio
riguardante l'implementazione di un basilare UDP scanner.
La tecnica di scanning impiegata è la stessa che adotta nmap
per mezzo dell'opzione -sU (esempio: nmap -sU -p 53 127.0.0.1) e
sfrutta l'eventuale pacchetto ICMP di tipo
port
unreachable (type 3) che può tornare
indietro nel caso in cui la porta UDP scansionata risulti essere
irraggiungibile.
UDP, infatti, non ha alcun meccanismo per informare il client che
la porta presso cui intende instaurare la connessione è irraggiungibile,
viene cosi incaricato ICMP di farlo al posto suo.
Nel semplice codice sotto riportato non si è fatto altro
che:
- Inizializzare un socket e mandare un comune
pacchetto UDP all'host remoto sulla porta interessata.
- Inizializzare un secondo socket di tipo RAW
pronto a ricevere eventuali pacchetti ICMP di ritorno.
- Nel caso in cui tale socket riceva un pacchetto
ICMP type 3 dall'host remoto a cui
si è precedentemente mandato il pacchetto UDP si assume
che la porta scansionata sia chiusa.
- Nel caso in cui tale socket non riceva nessun
pacchetto ICMP type 3 dall'host remoto nell'arco di 2 secondi
si assume che la porta risulti essere aperta.
Come metodo non risulta essere molto affidabile
in quanto una banale regola sul firewall dell'host remoto potrebbe
evitare che in seguito a una richiesta del tipo sopra menzionato
non venga mandato alcun pacchetto ICMP di tipo 3 e che il risultato
dello scanning possa di conseguenza risultare sfalsato generando
un falso
positivo.
Il caso più classico di falso positivo si può verificare
nel caso in cui la macchina remota che si intende scansionare sia
down e non mandando indietro alcun pacchetto (ovviamente) venga
considerata raggiungibile e con porta UDP in stato listening.
A tal proposito prima di cominciare lo scanning il programma pinga
preventivamente la macchina remota e in caso di mancata risposta
avvisa che vi è una alta probabilità di intercorrere
in falsi positivi. Le porte in stato "open" rilevate durante lo
scanning molto probabilmente si riferiranno a una macchina che non
è neanche operativa, o che ha installato un firewall
che droppa preventivamente i pacchetti ICMP di tipo ECHO in entrata
e proibisce il ritorno di pacchetti ICMP di tipo PORT_UNREACHABLE
in uscita in seguito alla ricezione di un pacchetto UDP su una porta
chiusa.
| |
#!/usr/bin/python
# simple UDP scanner by billiejoex
# http://billiejoex.altervista.org
import select
import socket
import sys
import os
import impacket
import getopt
import popen2
from impacket
import ImpactDecoder
def verify():
p_num
= socket.getprotobyname('icmp')
s
= socket.socket(socket.AF_INET,
socket.SOCK_RAW,
p_num)
s.setsockopt(socket.IPPROTO_IP,
socket.IP_HDRINCL,
1)
decoder
= ImpactDecoder.EthDecoder()
if
s in
select.select([s],
[], [],2)[0]:
pkt
= s.recvfrom(4096)[0]
ip
= ImpactDecoder.IPDecoder().decode(pkt)
#layer ip pointer
icmp
= ip.child()
#layer icmp pointer
ipsrc
= ip.get_ip_src()
ipdst
= ip.get_ip_dst()
type
=
icmp.get_icmp_type()
code
=
icmp.get_icmp_code()
if
(type
== 3)
and (code
== 3)
and (ipsrc
== host):
return
False
return
True
def helper():
print
"""\
Simple UDP scanner
Syntax:
%s [-p int,int] [-r int-int]
remote_host
Options:
-p port(s)
-r range
port
Examples:
python %s -p 137,139 10.0.0.1
python %s -p 53 -r 137-139
10.0.0.1
""" %(sys.argv[0],sys.argv[0],sys.argv[0])
def parser():
global
args,
ports
ports
= []
try:
opts,
args =
getopt.getopt(sys.argv[1:],
"h, p:p, r:r")
except:
helper();
os._exit(0)
x
= 2
for
o,
a in
opts:
if
o ==
"-p":
x
+= 1
f
= a.split(',')
for
i in
f:
ports.append(int(i))
if
o ==
'-r':
x
+= 2
f
= a.split('-')
for
i in
range(int(f[0]),
int(f[1])):
ports.append(int(i))
if
opts ==
[]: helper();
os._exit(0)
parser()
host =
args[0]
exec_cmd =
popen2.popen4('ping
-c 2 '+host)
#try to ping host
output =
exec_cmd[0].read()
if 'bytes
from' in
output:
print "
Host %s seems to be up" %host
else:
print "
Host %s seems to be down.\n Starting false positive UDP
scan" %host
u =
socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
ports.sort()
for i
in ports:
addr
= (host,i)
u.sendto('',addr)
if
verify():
print "
open: %-25s" %i
else:
print "
closed: %-25s" %i
|
- root@server:/home/user#
python udp.py -r 136-142 12.255.10.2
Host 12.255.10.2 seems to be up.
closed 136
open 137 netbios-ns
open 138 netbios-dgm
closed 139 netbios-ssn
closed 140
closed 141
closed 142
Finished.
|
|