28 dic 2016

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

Buenas a todos, en el post de hoy continuaremos con la cadena sobre la construcción de nuestro escáner de dispositivos, añadiendo las funciones oportunas para almacenar la información que obtenemos con nuestro analizador en una base de datos MySQL. Podéis utilizar la tecnología de almacenamiento que consideréis más eficiente para vuestras pruebas de concepto. En nuestro caso, será suficiente con MySQL, el cual en el caso de ser necesario podríamos implementar en modo cluster.

A continuación os compartimos el código del archivo principal del analizador:
import socket
import pygeoip
import MySQLdb
from ports import getcommonports

# Database
DB_HOST = 'localhost'
DB_USER = 'fluscan'
DB_PASS = 'F1u$c4n'
DB_NAME = 'fluscan'

def geo(_file, _ip, _id):
    ''' This function search the geolocation values of an IP address '''
    try:
        geoDb = pygeoip.GeoIP(_file)
        ip_dictionary_values = geoDb.record_by_addr(_ip)
        ip_list_values = ip_dictionary_values.items()
        q = "INSERT INTO t_geo (host, city, region_code, area_code, time_zone, dma_code, metro_code, country_code3, latitude, postal_code, longitude, country_code, country_name, continent) VALUES ('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ON DUPLICATE KEY UPDATE city='%s', region_code='%s', area_code='%s', time_zone='%s', dma_code='%s', metro_code='%s', country_code3='%s', latitude='%s', postal_code='%s', longitude='%s', country_code='%s', country_name='%s', continent='%s'" % (_id, ip_list_values[0][1], ip_list_values[1][1], ip_list_values[2][1], ip_list_values[3][1], ip_list_values[4][1], ip_list_values[5][1], ip_list_values[6][1], ip_list_values[7][1], ip_list_values[8][1], ip_list_values[9][1], ip_list_values[10][1], ip_list_values[11][1], ip_list_values[12][1], ip_list_values[0][1], ip_list_values[1][1], ip_list_values[2][1], ip_list_values[3][1], ip_list_values[4][1], ip_list_values[5][1], ip_list_values[6][1], ip_list_values[7][1], ip_list_values[8][1], ip_list_values[9][1], ip_list_values[10][1], ip_list_values[11][1], ip_list_values[12][1])
        run_query(q)
    except:
        pass

def hosts(_ip):
    ''' This function search the hostnames '''
    _host = None
    try:
        hosts_values = socket.gethostbyaddr(_ip)
        _host = str(hosts_values[0])
        if _host:
            run_query("INSERT INTO t_hosts (ip, host, date) VALUES ('%s', '%s', now()) ON DUPLICATE KEY UPDATE host='%s', date=now()" % (_ip, _host, _host))
            return run_query("SELECT id FROM t_hosts WHERE ip='%s'" % _ip)[0][0]
    except:
        return None

def portscan(_host, _port):
    ''' This function execute a port scan '''
    banner = ''
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(0.5)
        result = sock.connect_ex((_host, _port))
        sock.send('GET HTTP/1.1 \r\n')
        banner = sock.recv(1024)
        sock.close()
    except:
        pass
    return result, banner

def ports(_ip, _id):
    ''' This function search open ports '''
    try:
        common_ports = getcommonports()
        for value in common_ports:
            banner_exists, banner = portscan(_ip, value)
            if not banner_exists:
                run_query("INSERT INTO t_ports (host, port, service, banner, date) VALUES ('%d', '%d', '%s', '%s', now()) ON DUPLICATE KEY UPDATE service='%s', banner='%s', date=now()" % (_id, value, str(common_ports[value]), str(banner), str(common_ports[value]), str(banner)))
    except:
        pass

def ip_order(_ip1, _ip2):
    try:
        _ip1_split = _ip1.split('.')
        _ip2_split = _ip2.split('.')
        for i in range(0, 4):
            if _ip2_split[i] < _ip1_split[i]:
                return _ip1, _ip2
            elif _ip2_split[i] > _ip1_split[i]:
                return _ip2, _ip1
        return _ip2, _ip1
    except:
        return _ip1, _ip2

def ip_add(_ip):
    try:
        _ip_split = _ip.split('.')
        if int(_ip_split[3]) < 255:
            return "%s.%s.%s.%d" % (_ip_split[0], _ip_split[1], _ip_split[2], int(_ip_split[3])+1)
        elif int(_ip_split[2]) < 255:
            return "%s.%s.%d.%d" % (_ip_split[0], _ip_split[1], int(_ip_split[2])+1, 0)
        elif int(_ip_split[1]) < 255:
            return "%s.%d.%d.%d" % (_ip_split[0], int(_ip_split[1])+1, 0, 0)
        elif int(_ip_split[0]) < 255:
            return "%d.%d.%d.%d" % (int(_ip_split[0])+1, 0, 0, 0)
        else:
            return _ip
    except:
        return _ip

def run_query(query=''):
    datos = [DB_HOST, DB_USER, DB_PASS, DB_NAME]
    conn = MySQLdb.connect(*datos)
    cursor = conn.cursor()
    cursor.execute(query)
    if query.upper().startswith('SELECT'):
        data = cursor.fetchall()
    else:
        conn.commit()
        data = None
    cursor.close()
    conn.close()
    return data

def main(_ip1,_ip2):
    ''' Main function, launch the main activities '''
    ''' You can download GeoIP databases from here: https://dev.maxmind.com/geoip/legacy/geolite '''
    _ip3 = _ip1
    while _ip3 <> _ip2:
        _ip3 = ip_add(_ip3)
        print _ip3
        try:
            _id = hosts(_ip3)
            if _id:
                geo('GeoIP/GeoLiteCity.dat', _ip3, _id)
                ports(_ip3, _id)
        except:
            print 'Error on: %s' % _ip3

if __name__ == "__main__":
    print 'FluScan, an IPv4 scanner. Created by http://www.flu-project.com\n'
    ip1 = 'X.X.X.X'
    ip2 = 'Y.Y.Y.Y'
    ip2, ip1 = ip_order(ip1, ip2)
    main(ip1, ip2)
Por otro lado, os compartimos el código SQL para generar la BBDD con las tablas necesarias para el funcionamiento del sistema:
CREATE DATABASE IF NOT EXISTS `fluscan` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `fluscan`;

CREATE TABLE `t_geo` (
  `id` int(11) NOT NULL,
  `host` int(11) DEFAULT NULL,
  `city` text,
  `region_code` text,
  `area_code` text,
  `time_zone` text,
  `dma_code` text,
  `metro_code` text,
  `country_code3` text,
  `latitude` text,
  `postal_code` text,
  `longitude` text,
  `country_code` text,
  `country_name` text,
  `continent` text
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `t_hosts` (
  `id` int(11) NOT NULL,
  `ip` varchar(250) DEFAULT NULL,
  `host` text,
  `date` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `t_ports` (
  `id` int(11) NOT NULL,
  `host` int(11) DEFAULT NULL,
  `port` int(11) DEFAULT NULL,
  `service` text,
  `banner` text,
  `date` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `t_geo`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `host` (`host`);

ALTER TABLE `t_hosts`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `ip` (`ip`);

ALTER TABLE `t_ports`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `host` (`host`,`port`);
Con todo esto tendremos lista la base de nuestro escáner.

Saludos!

No hay comentarios:

Publicar un comentario