systemadmin.es > Redes > Crear un script NSE que realize conexiones TCP

Crear un script NSE que realize conexiones TCP

nmap es una herramienta muy completa que permite además de escanear puertos, descubrir los hosts de una red, detectar el sistema operativo, permite extender su funcionalidad mediante scripts. Vamos a ver como crear un script de ejemplo para nmap.

Un ejemplo de script NSE para nmap es el siguiente:

description = "Detect unpatched Apache servers against CVE-2011-3192"

author = "Jordi Prats Catala <jprats@systemadmin.es>"

license = "BSD"

categories = {"default","safe"}

require "comm"
require "shortport"

portrule = shortport.http

action = function(host, port)
        local hostname, uri = stdnse.get_script_args('hostname', 'uri')

        local hostheader = ""

        if hostname then
                hostheader = "Host: "..hostname.."\r\n"
        end

        if not uri then
                uri = "/"
        end

        local status, result  = comm.exchange(host, port,
                "GET "..uri.." HTTP/1.1\r\n"..hostheader.."Range:bytes=0-0,1-1,2-2,3-3,4-4,5-5,6-6,7-7,8-8,9-9,10-10\r\nAccept-Encoding: gzip\r\nUser-Agent: nmap-range-header\r\nConnection: close\r\n\r\n", {proto=port.protocol, timeout=5000})
        if (result:find "206 Partial") then
                return stdnse.format_output(true, "CVE-2011-3192 - vulnerable")
        else
                if(result:find "HTTP/1.1 200 OK") then
                        return stdnse.format_output(true, "CVE-2011-3192 - not vulnerable")
                else
                        return stdnse.format_output(true, "BAD URI: Can't test CVE-2011-3192")
                end
        end
end

Este permite la detección de host vulnerables a CVE-2011-3192:

  • En el caso que no sea vulnerable:
    # nmap --script rangeheader.nse 1.1.1.1 --script-args hostname=systemadmin.es,uri=/ -p80
    
    Starting Nmap 5.51 ( http://nmap.org ) at 2011-09-18 21:56 CEST
    Nmap scan report for 1.1.1.1 (1.1.1.1)
    Host is up (0.033s latency).
    PORT   STATE SERVICE
    80/tcp open  http
    | rangeheader:
    |_  CVE-2011-3192 - not vulnerable
    
    Nmap done: 1 IP address (1 host up) scanned in 0.56 seconds
    
  • En el caso que sea vulnerable:
    # nmap --script rangeheader.nse 1.2.3.4 --script-args hostname=systemadmin.es,uri=/ -p80
    
    Starting Nmap 5.51 ( http://nmap.org ) at 2011-09-18 21:57 CEST
    Nmap scan report for 1.2.3.4 (1.2.3.4)
    Host is up (0.034s latency).
    rDNS record for 194.116.240.89: tierra.trackgi.com
    PORT   STATE SERVICE
    80/tcp open  http
    | rangeheader:
    |_  CVE-2011-3192 - vulnerable
    
    Nmap done: 1 IP address (1 host up) scanned in 0.32 seconds
    
  • En el caso que no se pueda determinar, también nos lo indicará, por ejemplo si el recurso no existe:
    # nmap --script rangeheader.nse 1.2.3.4 --script-args hostname=systemadmin.es,uri=/dsads -p80
    
    Starting Nmap 5.51 ( http://nmap.org ) at 2011-09-18 21:57 CEST
    Nmap scan report for 1.2.3.4 (1.2.3.4)
    Host is up (0.033s latency).
    rDNS record for 194.116.240.89: tierra.trackgi.com
    PORT   STATE SERVICE
    80/tcp open  http
    | rangeheader:
    |_  BAD URI: Can't test CVE-2011-3192
    
    Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds
    

En las primeras lineas del plugin definimos algunos metadatos: Descripción, autor, licencia del script y categorias según corresponda. A continuación mediante require se indican las librerias de NSE que necesitaremos.

En este caso se usa comm para la comunicación por red y shortport para indicar cuando debemos ejecutar dicho script.

Esto lo hacemos mediante portrule, que podríamos indicar un determinado puerto TCP:

shortport.portnumber({80}, {"tcp"})

O bien, como en este caso cualquier puerto que sea HTTP:

portrule = shortport.http

Para definir la acción crearemos una función con las acciones a ejecutar que acabamos con end:

action = function(host, port)
(...)
end

Para la obtención de argumentos para el script debemos usar la función stdnse.get_script_args:

local hostname, uri = stdnse.get_script_args('hostname', 'uri')

En este caso mediante la función comm.exchange intercambiamos datos. En Lua una función puede devolver más de un valor, en este caso nos indica el estado (si se ha establecido la conexión o no) y los datos que ha contestado el servidor.

El trato de la cadena devuelta la podemos hacer, por ejemplo, mediante find:

variable:find "texto-a-buscar"

Finalmente para mostrar algún mensaje podemos usar la función format_output o print_verbose/print_debug de la librería stdnse:

stdnse.format_output(true, "BAD URI: Can't test CVE-2011-3192")

A partir de este ejemplo básico podemos ampliar el script con las muchas librerías y funciones.

Como nota personal, no soy muy amigo de lenguajes del estilo de Pascal o Python, sino mas bien de los similares a C, como lo sería perl, pero poder añadir funcionalidades a una herramienta tan completa como es nmap vale la pena tener que escribir el odioso if then end

3 comments to “Crear un script NSE que realize conexiones TCP”

  1. Interesante post. Pero un apunte, en Python la estructura condicional únicamente viene indicada por el if y la indentación. Ni el then y el end existen

  2. Es muy interesante muchas gracias … lo voy a intentar usar para abrir conexiones contra puertos de tomcat y comprobar si estan en funcionamiento o no cada pocos segundos….. alguna sugerencia de como podriamos hacer esto?

  3. ¿Para esto no sería mejor usar Nagios?

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>