14 dic 2016

Construyendo nuestro propio escáner de dispositivos conectados a Internet. Parte 3

Buenas a todos, en el post de hoy continuaremos con la cadena sobre la construcción de nuestro escáner de dispositivos online, añadiendo dos funcionalidades. La primera de ellas será un analizador de puertos abiertos, que partirá de un listado con los puertos más habituales que se encuentran abiertos en los distintos activos expuestos a Internet. Y por otro lado, otra con la que comprobaremos el hostname asociado.

¡Vamos allá! Vamos a crear un nuevo archivo al que llamaremos ports.py, y que alojaremos en la carpeta raíz del proyecto. En este archivo copiaremos el siguiente código, que contendrá el listado de puertos que utilizaremos para cada escaneo:

COMMON_PORTS = {
    1: 'tcpmux',
    5: 'rje',
    7: 'echo',
    9: 'discard',
    11: 'systat',
    13: 'daytime',
    17: 'qotd',
    18: 'msp',
    19: 'chargen',
    20: 'ftp-data',
    21: 'ftp',
    22: 'ssh',
    23: 'telnet',
    25: 'smtp',
    37: 'time',
    39: 'rlp',
    42: 'nameserver',
    43: 'nicname',
    49: 'tacacs',
    50: 're-mail-ck',
    53: 'domain',
    63: 'whois++',
    67: 'bootps',
    68: 'bootpc',
    69: 'tftp',
    70: 'gopher',
    71: 'netrjs-1',
    72: 'netrjs-2',
    73: 'netrjs-3',
    79: 'finger',
    80: 'http',
    88: 'kerberos',
    95: 'supdup',
    101: 'hostname',
    105: 'csnet-ns',
    106: 'poppassd',
    107: 'rtelnet',
    109: 'pop2',
    110: 'pop3',
    111: 'sunrpc',
    113: 'auth',
    115: 'sftp',
    117: 'uucp-path',
    119: 'nntp',
    123: 'ntp',
    137: 'netbios-ns',
    138: 'netbios-dgm',
    139: 'netbios-ssn',
    143: 'imap',
    161: 'snmp',
    162: 'snmptrap',
    163: 'cmip-man',
    164: 'cmip-agent',
    174: 'mailq',
    177: 'xdmcp',
    178: 'nextstep',
    179: 'bgp',
    191: 'prospero',
    194: 'irc',
    199: 'smux',
    201: 'at-rtmp',
    202: 'at-nbp',
    204: 'at-echo',
    206: 'at-zis',
    209: 'qmtp',
    210: 'z39.50',
    213: 'ipx',
    220: 'imap3',
    245: 'link',
    347: 'fatserv',
    363: 'rsvp_tunnel',
    369: 'rpc2portmap',
    370: 'codaauth2',
    372: 'ulistproc',
    389: 'ldap',
    427: 'svrloc',
    434: 'mobileip-agent',
    435: 'mobilip-mn',
    443: 'https',
    444: 'snpp',
    445: 'microsoft-ds',
    464: 'kpasswd',
    468: 'puertos',
    487: 'saft',
    488: 'gss-http',
    496: 'pim-rp-disc',
    500: 'isakmp',
    515: 'printer spooler',
    519: 'utime unixtime',
    521: 'ripng',
    525: 'timed timeserver',
    532: 'netnews',
    535: 'iiop',
    538: 'gdomap',
    546: 'dhcpv6-client',
    547: 'dhcpv6-server',
    548: 'afpovertcp',
    554: 'puertos',
    556: 'remotefs',
    563: 'nntps',
    565: 'whoami',
    587: 'submission',
    610: 'npmp-local',
    611: 'npmp-gui',
    612: 'hmmp-ind',
    631: 'ipp',
    636: 'ldaps',
    674: 'acap',
    694: 'ha-cluster',
    749: 'kerberos-adm',
    750: 'kerberos-iv',
    751: 'kerberos_master',
    752: 'passwd_server',
    754: 'krb5_prop',
    760: 'krbupdate',
    765: 'webster',
    767: 'phonebook',
    808: 'omirr',
    873: 'rsync',
    953: 'rndc',
    992: 'telnets',
    993: 'imaps',
    994: 'ircs',
    995: 'pop3s',
    1080: 'socks',
    1109: 'kpop',
    1236: 'bvcontrol',
    1300: 'h323hostcallsc',
    1433: 'ms-sql-s',
    1434: 'ms-sql-m',
    1494: 'ica',
    1512: 'wins',
    1524: 'ingreslock',
    1525: 'prospero-np',
    1645: 'datametrics',
    1646: 'sa-msg-port',
    1649: 'kermit',
    1701: 'l2tp',
    1718: 'h323gatedisc',
    1719: 'h323gatestat',
    1720: 'h323hostcall',
    1758: 'tftp-mcast',
    1789: 'hello',
    1812: 'radius',
    1813: 'radius-acct',
    1911: 'mtp',
    1985: 'hsrp',
    1986: 'licensedaemon',
    1997: 'gdp-port',
    2049: 'nfs',
    2053: 'knetd',
    2102: 'zephyr-srv',
    2103: 'zephyr-clt',
    2104: 'zephyr-hm',
    2105: 'eklogin',
    2150: 'ninstall',
    2401: 'cvspserver',
    2600: 'hpstgmgr [zebrasrv]',
    2601: 'discp-client [zebra]',
    2602: 'discp-server [ripd]',
    2603: 'servicemeter [ripngd]',
    2604: 'nsc-ccs [ospfd]',
    2605: 'nsc-posa',
    2606: 'netmon [ospf6d]',
    2809: 'corbaloc',
    2988: 'afbackup',
    3130: 'icpv2',
    3306: 'mysql',
    3346: 'trnsprntproxy',
    3455: 'prsvp',
    4011: 'pxe',
    4321: 'rwhois',
    4444: 'krb524',
    5002: 'rfe',
    5232: 'sgi-dgl',
    5308: 'cfengine',
    5354: 'noclog',
    5355: 'hostmon',
    5432: 'postgres',
    5999: 'cvsup',
    6667: 'ircd',
    7000: 'afs3-fileserver',
    7001: 'afs3-callback',
    7002: 'afs3-prserver',
    7003: 'afs3-vlserver',
    7004: 'afs3-kaserver',
    7005: 'afs3-volser',
    7006: 'afs3-errors',
    7007: 'afs3-bos',
    7008: 'afs3-update',
    7009: 'afs3-rmtsys',
    8008: 'http-alt',
    8080: 'webcache',
    8081: 'tproxy',
    9359: 'mandelspawn mandelbrot',
    9876: 'sd',
    10080: 'amanda',
    10081: 'kamanda',
    11371: 'pgpkeyserver',
    11720: 'h323callsigalt',
    13720: 'bprd',
    13721: 'bpdbm',
    13722: 'bpjava-msvc',
    13724: 'vnetd',
    13782: 'bpcd',
    13783: 'vopied',
    20011: 'isdnlog',
    20012: 'vboxd',
    22273: 'wnn6 wnn4',
    24554: 'binkp',
    26000: 'quake',
    26208: 'wnn6-ds',
    27374: 'asp',
    33434: 'traceroute',
    60177: 'tfido',
    60179: 'fido'
}

def getcommonports():
    return COMMON_PORTS

Nuestro nuevo esquema de archivos quedará tal que así:


Por otro lado, vamos a ampliar el código del programa FluScan.py, modificándolo por el siguiente:

import pygeoip
import socket
from ports import getcommonports

def geo(_file, _ip):
    ''' This function search the geolocation values of an IP address '''
    geoDb = pygeoip.GeoIP(_file)
    ip_dictionary_values = geoDb.record_by_addr(_ip)
    ip_list_values = ip_dictionary_values.items()
    print "*******************"
    print "*** Geolocation ***"
    print "*******************"
    for value in ip_list_values:
        print str(value[0]) + ": " + str(value[1])

def hosts(_ip):
    ''' This function search the hostnames '''
    print "\n*******************"
    print "***    Hosts    ***"
    print "*******************"
    try:
        hosts_values = socket.gethostbyaddr(_ip)
        print str(hosts_values[0])
    except:
        print 'No hosts associate'

def portscan(_host, _port):
    ''' This function execute a port scan '''
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(0.01)
        result = sock.connect_ex((_host, _port))
        sock.close()
    except:
        pass
    return result

def ports(_ip):
    ''' This function search open ports '''
    common_ports = getcommonports()
    print "\n*******************"
    print "***    Ports    ***"
    print "*******************"
    for value in common_ports:
        if not portscan(_ip, value):
            print str(value) + ': ' + str(common_ports[value])

def main(_ip):
    ''' Main function, launch the main activities '''
    ''' You can download GeoIP databases from here: https://dev.maxmind.com/geoip/legacy/geolite '''

    # Extract geolocation values
    geo('GeoIP/GeoLiteCity.dat', _ip)
    hosts(_ip)
    ports(_ip)

if __name__ == "__main__":
    print 'FluScan, an IPv4 scanner. Created by http://www.flu-project.com\n'
    main('X.X.X.X') #Sustituir por la IP de ejemplo a escanear

La ejecución de nuestro programa daría un resultado como el siguiente (como en mi caso se trata de un servidor de prueba, he sanitizado la salida por pantalla):

FluScan, an IPv4 scanner. Created by http://www.flu-project.com

*******************
*** Geolocation ***
*******************
city: XXXXXXXXX
region_code: XX
area_code: XXX
time_zone: XXXXXXX/XXXXXXXXX
dma_code: XXX
metro_code: XXXXXXXXX, XX
country_code3: XXX
latitude: XX.XXXXXXXXXX
postal_code: XXXXX
longitude: -XX.XXXXXXXX
country_code: XX
country_name: Spain
continent: XX

*******************
***    Hosts    ***
*******************
XXXXX-XXX-XX-X.XXXXXXXXXXX.es

*******************
***    Ports    ***
*******************
80: http

Eso es todo por hoy :), en el próximo post de la cadena continuaremos evolucionando nuestro escáner.

Saludos!

1 comentario: