Durante el pasado Black Friday el portal de consulta de cualquier dispositivo conectado a Internet Shodan puso de oferta el upgrade de las cuentas free por 49 5 €, oferta que aproveché para actualizar mi cuenta actual.
Con esta cuenta se obtienen una serie de beneficios a la hora de realizar consultas, evitando algunas limitaciones que tiene la versión gratuita. Estas ventajas, a su vez, se limitan a unos umbrales anuales, a diferencia de las cuentas de pago mensual cuyos contadores se reinician todos los meses.
Con esta actualización podemos probar ciertas funcionalidades, tanto en la web como desde cualquiera de sus APIs. Desde la web oficial podemos acceder a la información de las APIs (pincha aquí). Me he centrado en la API de Python, publicado en el enlace https://shodan.readthedocs.io/en/latest/, y estos son los comandos que me resultaron de más interés.
Tabla de contenidos
Instalación
Para instalar la librería de Shodan usamos el comando pip.
# pip search shodan shodan (1.10.4) - Python library and command-line utility for Shodan (https://developer.shodan.io) INSTALLED: 1.10.4 (latest) RoboShodan (1.2) - Robot Framework Library for Shodan
En mi caso ya lo tenía instalado, de lo contrario ejecutaríamos el siguiente comando.
pip install shodan
Conectar con la cuenta
Para conectar con la cuenta debemos de consultar la API_KEY publicada en la sección MyAccount de Shodan.
Ahora importamos la librería y cargamos la aplicación con la API_KEY.
import shodan SHODAN_API_KEY = "XXX" api = shodan.Shodan(SHODAN_API_KEY)
Información de la cuenta
Una vez conectado con la cuenta podemos conocer su información actual con el métido info().
api.info()
Resultado.
{u'https': False, u'plan': u'dev', u'query_credits': 100, u'scan_credits': 98, u'telnet': False, u'unlocked': True, u'unlocked_left': 100}
Búsqueda básica
Para realizar una búsqueda debemos de usar el método search e iterar con todos los resultados usando un bucle for. Por ejemplo, vamos a realizar una búsqueda por el servidor web Apache.
try: results = api.search('apache') print("Resultados encontrados: {}' . format(results['total'])) for result in results['matches']: print('IP: {}' . format(result['ip_str'])) print(result['data']) print('') except shodan.APIError, e: print('Error: {}' . format(e))
Resultado.
Resultados encontrados: 25504866 IP: 213.226.249.184 HTTP/1.1 302 Moved Temporarily Date: Fri, 30 Nov 2018 11:36:15 GMT Server: Apache Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0 Location: http://213.226.249.184:5000/ Content-Length: 0 Content-Type: text/plain IP: 1.51.246.132 HTTP/1.1 200 OK Date: Fri, 30 Nov 2018 11:27:18 GMT Server: Apache X-Frame-Options: SAMEORIGIN Last-Modified: Thu, 19 Jul 2018 08:41:31 GMT ETag: "2a0-5715625581d4b" Accept-Ranges: bytes Content-Length: 672 Content-Type: text/html ...
Búsqueda de host
Para buscar información de un host concreto usamos el método host y la función get.
results = api.host('8.8.8.8') # Mostramos la informacion. print(""" IP: {} Oganization: {} Operative Sistem: {} """ . format(results['ip_str'], results.get('org', 'n/a'), results.get('os', 'n/a')))
Resultado.
IP: 8.8.8.8 Organization: Google Operative Sistem: None
Mostrar Banners
Usando el comando anterior podemos obtener los Banners mostrados por los servicios cuando se realiza una conexión, y registrados en Shodan.
for item in results['data']: print(""" Port: {} Banner: {} """.format(item['port'], item['data']))
Resultado.
Port: 53 Banner: Recursion: enabled
Como el resultado anterior es muy simple, a continuación se muestra el resultado tras consultar otra IP diferente.
Port: 443 Banner: HTTP/1.1 200 OK Date: Wed, 28 Nov 2018 07:09:50 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Keep-Alive: timeout=10 Vary: Accept-Encoding X-Powered-By: PHP/5.6.38-0+deb8u1 Server: RainLoop Strict-Transport-Security: max-age=15768000 Port: 993 Banner: * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready. * CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN A001 OK Pre-login capabilities listed, post-login capabilities have more. * ID ("name" "Dovecot") A002 OK ID completed. A003 BAD Error in IMAP command received by server. * BYE Logging out A004 OK Logout completed.
Script búsqueda básica
El siguiente script, que llamaremos busquedaBasica.py, permite realizar una búsqueda básica con el método search y mostrar las IPs registradas con el patrón indicado. Se debe de indicar algún parámetro tras ejecutar el script.
#!/usr/bin/env python # # Buscador para imprimir una lista de IPs resultantes de una consulta. import shodan, sys API_KEY = "XXX" # Validacion de entrada if len(sys.argv) == 1: print 'Uso: %s <search query>' % sys.argv[0] sys.exit(1) try: # Setup de API api = shodan.Shodan(API_KEY) # Perform the search query = ' '.join(sys.argv[1:]) result = api.search(query) # Loop through the matches and print aeach IP for service in result['matches']: print service['ip_str'] except Exception as e: print 'Error: %s' % e sys.exit(1)
Resultados.
# ./basicSearch.py Uso: ./basicSearch.py <search query> # ./basicSearch.py postfix 110.164.188.212 107.170.209.96 194.49.99.178 107.6.142.228 91.134.112.234 ....
Búsqueda con FACETS
Los FACETS son propiedades de los resultados, como pueden ser organización, dominio, puerto, …, muy útiles para organizar los resultados de una búsqueda. Nos permite, entre otras cosas, conocer qué versiones son las más populares, o qué países son los que más resultados muestran en función de lo especificado en la búsqueda.
Para ello usamos el método count() para buscar en Shoddan sin devolver cualquier resultado. Preguntamos por información concreta, acotando la búsqueda, y por consiguiente el resultado. Por defecto se muestra el top 5 del resultado de cada facet, a no ser que indiquemos lo contrario como vamos a poder ver en el siguiente ejemplo (facet country).
En el siguiente script, que llamaremos query-search.py indicamos el patrón por el que queremos buscar.
#!/usr/bin/env python # # Busqueda en Shodan e impresion del resultado de la query. import shodan, sys # Configuracion API_KEY = "XXX" # Lista de propiedades que queremos mostrar. # Por defecto se muestran los primeros 5 resultados. FACETS = [ 'org', 'domain', 'port', 'asn', # Solo queremos mostrar el top 3 de paises. # Por defecto se muestran 5!!! # Si queremos mostrar mas de 5 indicamos ('country', 1000) para mostrar 1000, por ejemplo. ('country', 3), ] FACET_TITLES = { 'org': 'Top 5 Organizaciones', 'domain': 'Top 5 Dominios', 'port': 'Top 5 Puertos', 'asn': 'Top 5 Sistemas Autonomos', 'country': 'Top 3 Paises', } # Validacion de entrada. if len(sys.argv) == 1: print 'Usage: %s <search query>' % sys.argv[0] sys.exit(1) try: # Setup API api = shodan.Shodan(API_KEY) # Generamos la variable de la query con los argumentos. query = ' '.join(sys.argv[1:]) # Usamos el metoddo count() porque no devuelve resultados y no requiere un plan de pago. # Y es mas rapido que ejecutar un search(). result = api.count(query, facets=FACETS) print 'Shodan Summary Information' print 'Query: %s' % query print 'Total Results: %s\n' % result['total'] # Imprimer la informacion de los facets. for facet in result['facets']: print FACET_TITLES[facet] for term in result['facets'][facet]: print '%s: %s' % (term['value'], term['count']) # Imprimerr una linea en blanco entre el resumen y la info. print '' except Exception, e: print 'Error: %s' % e sys.exit(1)
Resultado.
./query-summary.py apache Shodan Summary Information Query: apache Total Results: 34612043 Top 5 Organizations Amazon.com: 808061 Ecommerce Corporation: 788704 Verio Web Hosting: 760112 Unified Layer: 627827 GoDaddy.com, LLC: 567004 Top 5 Domains secureserver.net: 562047 unifiedlayer.com: 494399 t-ipconnect.de: 385792 netart.pl: 194817 wanadoo.fr: 151925 Top 5 Ports 80: 24118703 443: 8330932 8080: 1479050 81: 359025 8443: 231441 Top 5 Autonomous Systems as32392: 580002 as2914: 465786 as26496: 414998 as48030: 332000 as8560: 255774 Top 3 Countries US: 13227366 DE: 2900530 JP: 2014506
Listado de métodos
En el siguiente enlace se pueden consultar todos los métodos publicados para la API. Dependiendo de la licencia adquirida algunos métodos no podrán ser utilizados.
https://shodan.readthedocs.io/en/latest/api.html
Fuentes
Shodan oficial pincha aquí.
Shodan API reference pincha aquí.
Shodan Python GitHub pincha aquí.
Shodan Python doc pincha aquí.
Gracias por compartir.