Usando NMAP con Python

Nmap es un software destinado al análisis de puertos de uno o varios hosts de una red, gracias a el podemos desde identificar puertos abiertos, servicios que está corriendo una determinada máquina hasta comprobar de forma sencilla información sensible que pueda exponer a través de un servicio y vulnerabilidades que puedan presentar dichos servicios. Ya hablamos en un artículo anterior sobre su uso básico y el motor de scripts que lleva y cómo poder programar un script NSE de forma sencilla.

Existen varias formas de poder usar NMAP con el lenguaje de programación Python, en este artículo abordaremos algunas formas sencillas con las cuales podremos usar con pocas líneas de código esta navaja suiza de redes.

Usando NMAP con os

Para usar nmap con la librería os no necesitamos instalar ninguna dependencia adicional y es la forma más sencilla de lanzar un comando a través de la shell, a continuación dejo un ejemplo:

# -*- coding: utf-8 -*-

import os

NMAP_CMD="nmap -sT 127.0.0.1"
os.system(NMAP_CMD)

Usando NMAP con subproccess

Con subproccess hacemos prácticamente lo mismo que hacíamos con las librerías OS, pero en este caso podemos trabajar con las salidas STDOUT y STDERR de la consola, cosa que nos facilita un poco el posterior tratamiento del resultado

# -*- coding: utf-8 -*-

from subprocess import Popen, PIPE

process = Popen(['nmap', '-F', '127.0.0.1'], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
print(stdout)

Usando las librerías Python de NMAP

Las librerías python-nmap nos agilizan bastante la tarea de escanear con nmap y poder trabajar cómodamente con los resultados que devuelve.

Para instalar esta librerías podemos buscar el paquete python-nmap en nuestros repositorios o bien hacer la instalación mediante pip con el siguiente comando:

pip3 install python-nmap

Ejemplos

Comprobar si tiene un determinado puerto TCP abierto
# -*- coding: utf-8 -*-
import nmap

HOST = '127.0.0.1'

nm = nmap.PortScanner()
nm.scan(HOST, '22')
if nm[HOST].has_tcp(22):
    print("Puerto 22 detectado")
Escanear un rango de puertos TCP
# -*- coding: utf-8 -*-
import nmap

HOST = '127.0.0.1'

nm = nmap.PortScanner()
nm.scan(HOST, '22-443')
print(nm[HOST]['tcp'].keys())
Lanzar script
# -*- coding: utf-8 -*-
import nmap
import pprint

HOST = '127.0.0.1'

pp = pprint.PrettyPrinter(indent=4)
nm = nmap.PortScanner()
result = nm.scan(HOST, '22', arguments='-sC')
pp.pprint(result)

Para escanear con un script personalizado simplemente debemos indicarle en arguments el modificador –script seguido de la ruta de nuestro script personalizado.

Yield

Si necesitamos mostrar los resultados conforme los vayamos obteniendo podemos utilizar su clase PortScannerYield, con el cual podemos ir obteniendo el progreso de nuestro escaneo. Es bastante útil cuando tenemos que escanear un segmento de red y necesitamos hacer operaciones con cada host que vayamos descubriendo.

# -*- coding: utf-8 -*-
import nmap

nm = nmap.PortScannerYield()

for scan_yield in nm.scan('net_ip/24', '22-445'):
    # print(scan_yield[1]['nmap']['scanstats']['uphosts'])
    if scan_yield[1]['nmap']['scanstats']['uphosts'] == "1":
        print("Host ==> " + scan_yield[0])
        print(scan_yield[1]['scan'])
Async
# -*- coding: utf-8 -*-
import nmap

nma = nmap.PortScannerAsync()

def callback_function(host, scan_result):
    print('RESULTADO ==>')
    print(host, scan_result)

nma.scan(hosts='127.0.0.1', arguments='-sC -Pn', callback=callback_function)

while nma.still_scanning():
    print("Esperando a que termine el escaneo ...")
    nma.wait(2)