Archivo

Posts Tagged ‘rest services nessus’

La API Rest de Nessus en su versión 6

julio 9, 2015 Deja un comentario

Hace algunos meses que ha salido la versión 6 de Nessus, el popular escaner de vulnerabilidades diseñado y desarrollado por “Tenable network security” y la verdad es que llevaba tiempo sin trabajar con él, pero la semana pasada me escribió alguien comentando que la librería que desarrollé hace algunos meses (pynessus-rest) para interactuar programáticamente desde cualquier script en Python con Nessus, no le funcionaba correctamente. Pues bien, me puse a ver las trazas que me había enviado y me resultaron de lo más curiosas, ya que ni siquiera había conseguido obtener un token de autorización utilizando su cuenta de usuario. Pensé que a lo mejor se debía a un fallo en su instalación de Nessus o algo similar, así que me descargo e instalo la última versión de Nessus, escribo un script simple en el que solamente me autentico y creo una política y a continuación, cierro sesión para destruir el token creado anteriormente. 5 líneas de código, ni más ni menos. Pues bien, también me falla. Comienzo a revisar qué puede estar pasando y me llevo una “agradable” sorpresa al ver que la API Rest de Nessus 6.0 no es compatible hacia atrás con las demás versiones de Nessus.
Pues muy bien, es estupendo hacer cosas sobre un producto que no solamente no sigue sus propios estándares, sino que además no documenta adecuadamente los cambios que hace tras cada versión. La guía oficial a la fecha de redactar este artículo sigue siendo la correspondiente a la API Rest 5.0 (http://static.tenable.com/documentation/nessus_5.0_XMLRPC_protocol_guide.pdf) y por mucho que he buscado, no he encontrado esa misma guía para la nueva especificación, solamente comentarios en el foro de “Tenable” en el que mucha gente hace básicamente las mismas preguntas, ya que no hay una guía en la que se indique exactamente todos los detalles de los servicios REST de Nessus 6, tales como métodos HTTP soportados, parámetros, cabeceras, path de los servicios, descripción funcional detallada, etc. Lo más parecido a una documentación actualizada se encuentra en la propia interfaz de Nessus en la siguiente ruta: https://<NESSUS_SERVER>:8834/nessus6-api.html#/
Allí se explican todos los servicios que se encuentran actualmente disponibles en la versión 6 y como se puede ver, el path de los servicios en la versión 5.0 ha cambiado drásticamente en la versión 6.0. Así que si tenias algún script para automatizar alguna tarea utilizando la API Rest de Nessus en su versión 5.0, ya te puedes olvidar de que funcione en las nuevas versiones de Nessus. Ahora bien, es perfectamente comprensible que cada nueva versión de un programa incluya mejoras y nuevas características, cosas que hacen que el programa en cuestión evolucione y sea cada vez mejor, pero lo que siempre hay que tener en cuenta es que los usuarios esperan que las cosas que funcionaban en una versión, sigan funcionando correctamente en la siguiente (salvo error u omisión). Lo que se espera es que las interfaces o mecanismos de acceso sigan siendo los mismos, con el objetivo de que una posible migración sea lo más transparente posible. En el caso de la API Rest de Nessus, ninguno de los endpoints que estaban disponibles en la versión 5 de la API se encuentra disponibles en la versión 6, lo que obliga a todos los usuarios que actualicen Nessus a volver a implementar completamente todas rutinas automatizadas que tiren de la API.

Aunque con los nuevos cambios implementados en la versión actual de Nessus, la librería “pynessus-rest” queda deprecada, aun es posible seguir utilizando Python para realizar conexiones contra una instalación de Nessus y obtener información a partir de la API Rest de Nessus 6.
Para hacerlo, se puede utilizar cualquier librería para realizar peticiones HTTP, algo que abunda en Python. Por comodidad y simplicidad se puede utilizar “requests”.

nessus1Autenticación contra Nessus usando requests

Como se puede apreciar, es muy fácil conseguir un token de autenticación valido para interactuar con otros servicios de la API mucho más interesantes y en este caso concreto, lo único que ha cambiado entre la versión 6 y la versión 5 de la API es el endpoint, que ahora es “/session”. Si los cambios de todos los servicios fueran así de simples, no habría mayor problema, pero debido al rediseño que ha tenido el propio core Nessus en la versión actual, muchos de los servicios más utilizados como aquellos que permiten crear/editar políticas, gestionar escaneos y reportes, también han cambiado en la forma y estructura en la que devuelven información, con lo cual, una rutina de parseo del JSON de respuesta que antes funcionaba perfectamente en la versión 5 no va a funcionar para la versión 6. Es un limitante que impide la migración de scripts que esperan un formato y una estructura muy especifica para parsear la información que viene incluida en los JSON de respuestas. No obstante, en el caso de crear scripts desde cero, partiendo de la versión actual y con las reglas definidas en los servicios, realizar peticiones y procesar respuestas no es demasiado complicado y como siempre, se debe partir de un token valido para invocar a servicios que requieren autenticación para ser invocados, algo que ya se ha visto en la imagen anterior. El siguiente script enseña cómo utilizar las principales funciones en “pynessus-rest” adaptándolas un poco a los nuevos servicios disponibles en la versión 6.

import requests
import json 

class NessusClient():
    def __init__(self, nessusServer, nessusPort,
			validateCert=False,initialSeqNumber=1):
        self.nessusServer = nessusServer
        self.nessusPort = nessusPort
self.url='https://'+str(nessusServer)+':'+str(nessusPort)
        self.token = None
        self.headers = {}
        self.bodyRequest = {}
        self.seqNumber = initialSeqNumber
        self.validateCert = validateCert
    def constructParamsAndHeaders(self,
			headers={}, params={}, jsonFormat=True):
        if jsonFormat:
            self.body = {'seq' : self.seqNumber,
			'json' : '1'}
        else:
            self.body = {'seq' : self.seqNumber,
			'json' : '0'}
        if self.token is not None:
            #No authentication needed.
            self.headers={'Host': str(self.nessusServer)+':'+str(self.nessusPort),			'Content-type':'application/x-www-form-urlencoded',
	'X-Cookie':'token='+self.token,'seq':self.seqNumber}
        else:
            self.headers={'Host':str(self.nessusServer)+':'+str(self.nessusPort),
'Content-type':'application/x-www-form-urlencoded'}
        self.body.update(params)
        self.headers.update(headers)
        print self.headers 

    def requestNessus(self, url, method="POST"):
        '''
        Perform a request to Nessus server using the data and headers received by parameter.
        This function automatically increments the sequence identifier for Nessus requests.
        '''
        if method == "GET":
            response = requests.get(url,
			data=self.body, headers=self.headers, verify=self.validateCert)
        else:
            response = requests.post(url,
			data=self.body, headers=self.headers, verify=self.validateCert)
        self.seqNumber += 1
        try:
            return json.loads(response.content)
        except ValueError:
            return response.content 

    def call(self, service, params={},
			jsonFormat=True, method="GET"): self.constructParamsAndHeaders(params=params,
			jsonFormat=jsonFormat)
        content =self.requestNessus(self.url+service, method=method)
        return content
    def login(self, nessusUser, nessusPassword,
			jsonFormat=True):
        '''
        Login with the Nessus server using the user and password specified.
        '''
	self.constructParamsAndHeaders(params= 'username':nessusUser, 'password':nessusPassword})
        content = self.requestNessus(self.url+"/session", method="POST")
        if content.has_key("token"):
            self.token = content['token']
        return content 

client = NessusClient('127.0.0.1','8834')
client.login('adastra','password')
print str(client.call('/policies'))+"\n"
print str(client.call('/scans',
			params={'folder_id':1, 'last_modification_date':1}))+"\n"

El servicio “/scans” es un claro ejemplo de los cambios se han implementado en Nessus en esta última versión, ya que ahora este tipo de elementos se almacenan en contenedores internos de llamados “folders”. Para poder consultar un listado de escaneos es obligatorio especificar el identificador del folder, tal como se ha visto en el script anterior.

nessus2Peticiones y respuestas tras invocar a los servicios “/scans” y “/policies”

La imagen corresponde a lo que pinta por pantalla el script anterior, de tal forma que se pueden ver las cabeceras de las peticiones así como también el cuerpo de las mismas. Las respuestas emitidas por Nessus vienen en formato JSON y contienen información sobre las políticas y escaneos que se han creado.

Si quieres conocer más sobre los servicios que se encuentran disponibles en la nueva versión Nessus, te recomiendo que te fijes en la documentación que viene incluida en https://<NESSUS_SERVER>:8834/nessus6-api.html#/ tendrás que levantar una instancia de Nessus y ver los servicios disponibles junto con sus métodos. Si bien la documentación no está mal, hay ciertos detalles importantes que no se detallan pero si que los encuentras en el foro de Nessus, así que también es un buen recurso para visitar con frecuencia.
La persona que me reporto el posible “fallo” en pynessus-rest también me pregunto que si pensaba actualizar la librería para hacerla compatible con los nuevos esquemas definidos en la versión actual. Francamente no tiene sentido dedicar tiempo y esfuerzos en hacer algo que muy probablemente se va a quedar obsoleto en pocos meses debido a que Tenable no consigue definir unas pautas mínimas de compatibilidad entre las distintas versiones de su software. Dicho esto, si utilizas Nessus 5, pynessus-rest te va a funcionar perfectamente a la hora de automatizar tareas, pero para la versión 6 tendrás que programar un poco más y crear tus propias de rutinas de parseo (y esperar a que no se rompa nada cuando salga una nueva versión de Nessus en unos pocos meses).

Un saludo y Happy Hack!
Adastra.

Servicios REST en Nessus y pynessus-rest

octubre 14, 2014 1 comentario

Nessus es un escáner de vulnerabilidades que ha ganado su prestigio gracias a sus capacidades a la hora de detectar y reportar fallos de todo tipo. Es una herramienta que se encuentra a la altura de otras herramientas tan potentes y utilizadas como OpenVAS, NeXpose o Metasploit Framework. Nessus permite crear y lanzar diferentes tipos de escaneos contra múltiples objetivos, crear políticas ajustadas a diferentes tipos de auditorías que pueden ser lanzadas por el pentester y generar reportes muy completos sobre las vulnerabilidades encontradas. Su uso es muy intuitivo y aunque muchos pentesters suelen utilizarlo “in-situ” por medio de la consola administrativa de Nessus, también es posible utilizarlo de forma programática por medio de la API Rest disponible para ello. No son muchos los pentesters que suelen utilizar esta potente característica de Nessus, ya que normalmente estos servicios serán consumidos por herramientas de auditoría desarrolladas por terceros que quieran aprovechar los beneficios de Nessus o automatizar sus rutinas, como es el caso del plugin de “nessus” incluido en Tortazo.
Hace varios meses, tenia la necesidad de utilizar Nessus desde mis scripts escritos en Python, pero desafortunadamente no encontré ninguna librería que utilizará la especificación de servicios REST incluida a partir de la versión 5 de Nessus, solamente encontraba librerías que utilizaban la especificación antigua, la cual se basaba en XML-RPC. Una de las primeras que me encontré fue pynessus (http://code.google.com/p/pynessus/) la cual no solamente no utiliza la última especificación, sino que además no se encuentra soportada por nadie y tiene varias funciones con errores de compilación. Cualquier desarrollador la descartaría a la primera. Otras más como nessusxmlrpc (http://code.google.com/p/nessusxmlrpc/) o python-nessus (https://github.com/greencm/python-nessus) son más de lo mismo.
Cansado de perder tiempo buscando y encontrando solamente escombros de código, decidí crear una librería en Python para consumir los servicios REST de Nessus desde cualquier herramienta escrita en Python y es así como he terminado escribiendo pynessus-rest (https://github.com/Adastra-thw/pynessus-rest).
Se trata de una librería muy simple que consume todos los servicios REST definidos en la especificación de Nessus(http://static.tenable.com/documentation/nessus_5.0_XMLRPC_protocol_guide.pdf) y permite convertir los formatos de las respuestas (típicamente JSON) en una estructura de objetos en Python para su posterior uso.
Para instalar pynessus-rest, basta con ejecutar el script “setup.py” con el argumento “install”.

	python setup.py install

Después de instalar la librería, es posible utilizarla desde cualquier script en Python simplemente importando las clases y/o funciones necesarias. En este caso, la clase más importante para interactuar con una instancia de Nessus es la clase “NessusClient”, la cual cuenta con varios métodos para gestionar usuarios, políticas, reportes, escaneos planificados, etc.

Autenticación con el servidor de Nessus.

Lo primero es autenticarse para poder interactuar con los demás servicios y para ello, se debe invocar al servicio REST “login” el cual recibe como argumentos, el nombre de usuario y contraseña. Si el proceso de autenticación es correcto, el servicio devolverá un token identificativo del usuario, el cual debe ser utilizado por el cliente para futuras invocaciones a otros servicios que requieran permisos de acceso. La clase “NessusClient” tiene la función “login”, la cual se encarga de todos estos detalles a la hora de interactuar con el servicio REST “login” de Nessus e internamente, guarda el token devuelto por el servicio en el caso de una autenticación exitosa. Esto quiere decir, que la propia instancia de “NessusClient” guarda el token de autenticación internamente para que cualquier otra petición posterior lo pueda usar. El desarrollador se despreocupa de tener que guardar él mismo dicho token entre diferentes peticiones a otros servicios REST.
Para crear una instancia de la clase “NessusClient” se deben enviar al constructor el host y el puerto donde se encuentra en ejecución el servidor de Nessus y la función “login” recibe como argumentos las credenciales de acceso para iniciar sesión y obtener un token valido.

	from pynessus.rest.client.NessusClient import NessusClient
	client = NessusClient('127.0.0.1','8834')
	client.login('adastra','adastra')

En el caso de que el proceso de login se ejecute correctamente con las credenciales ingresadas por el usuario, es posible utilizar todos los servicios expuestos en Nessus por medio de la instancia de “NessusClient” creada anteriormente.

 

Gestión de Políticas

Para iniciar un escaneo utilizando Nessus, es obligatorio crear una política que será aplicada a dicho escaneo. Las políticas definen los objetivos e indican el tipo de auditoría que se debe aplicar e internamente, define los plugins que se lanzarán contra los objetivos definidos. Hay una serie de plantillas de políticas que vienen pre-configuradas en Nessus, el usuario normalmente debe seleccionar una de dichas plantillas y rellenar los campos necesarios para configurar la política. Con Pynessus-rest, es posible utilizar todos los servicios REST definidos en la especificación de Nessus para la creación y gestión de políticas. El uso de algunas de dichas funciones se incluye a continuación:

	client.policyPreferencesList()
	client.policyList()
	client.policyCopy(1)
	client.policyDelete(1)
	client.policyFilePolicyImport("policy.nessus")

 

Gestión de Escaneos

Los escaneos son la principal característica funcional de Nessus, sin los cuales evidentemente la herramienta carecería de sentido. Los escaneos creados en Nessus pueden ser planificados y además pueden pausarse, reanudarse o detenerse manualmente. Estas características también se pueden controlar programáticamente desde pynessus-rest utilizando los servicios REST de Nessus disponibles para ello.

	client.scanNew("192.168.1.33",'1','EscaneoConPolitica1')
	client.scanStop('ec665c9e-ce24-336b-acb4-e2b199fac1800854abce5c111a8d')
	client.scanTemplateNew('1','127.0.0.1', 'Plantilla')
	client.scanTemplateLaunch('NewTemplate')

 

Gestión de Reportes

Todos los escaneos lanzados desde Nessus van generando reportes de forma periódica, dependiendo del progreso del escaneo, dichos reportes pueden ser más o menos completos.

	client.reportList()
	client.reportHosts("2e8ed9f5-79b5-4f60-d223-bc08e9688c79a606b97c670a7deb")
	client.reportTags("2e8ed9f5-79b5-4f60-d223-bc08e9688c79a606b97c670a7deb", '127.0.0.1', jsonFormat=True)

 

Convertir respuestas JSON a objetos en Python.

Todas las respuestas devueltas por los servicios REST de Nessus pueden estar en formato XML o JSON, siendo el formato JSON el valor por defecto y de uso más común cuando hablamos de servicios REST. Dado que las estructuras de datos que devuelven algunos servicios REST de Nessus son bastante complejas, la clase “NessusConverter” se encarga de convertir dichas respuestas en objetos Python que puedan ser manejados mucho más fácilmente por el desarrollador.

 nessusConverter = NessusConverter(self.nessusClient.usersList())
 nessusConverter.userToStructure()
 for nessusUser in nessusConverter.nessusStructure.nessusUsers:
     print nessusUser.name,nessusUser.admin,nessusUser.idx,nessusUser.lastLogin

 
 nessusConverter = NessusConverter(self.nessusClient.pluginsList())
 nessusConverter.pluginsListToStructure()
 for nessusPlugin in nessusConverter.nessusStructure.pluginsList:
     print nessusPlugin.familyMembers, nessusPlugin.familyName

 nessusConverter = NessusConverter(self.nessusClient.pluginsMd5())
 nessusConverter.md5StructureToStructure()
 for md5 in nessusConverter.nessusStructure.md5Structure:
     print  md5.fileName, md5.md5

En esta entrada solamente he incluido una breve descripción de la librería con algunas de sus funcionalidades, un uso mucho más exhaustivo lo podrás encontrar en el módulo “nessus” de Tortazo, el cual explota completamente todas las funciones disponibles en pynessus-rest y los servicios REST definidos en la última versión de Nessus. Además te invito a que pruebes esta librería con cualquier instancia de Nessus a la que tengas acceso.

Saludos y Happy Hack!

A %d blogueros les gusta esto: