Tabla de Contenidos
Utilizando Python para realizar búsquedas en Shodan
Módulo perteneciente al curso Python avanzado para proyectos de seguridad
Para utilizar Shodan desde python de forma programática es necesario tener una cuenta en Shodan, donde encontraremos nuestra Developer Shodan Key, de esta forma, permite que los desarrolladores de Python puedan automatizar las búsquedas en sus servicios a través de su API.
Si nos registramos como desarrolladores obtenemos una SHODAN_ API_KEY que utilizaremos desde nuestros scripts en Python para realizar las mismas búsquedas que se pueden realizar a través de la interfaz web.
Si nos registramos como desarrolladores, además de poder obtener el API_KEY, también tenemos otras ventajas como las de obtener más resultados o usar filtros de búsqueda.
Cabe recalcar que Shodan recoge la información que le devuelve la máquina, y nada le impide a esa máquina falsear esta información. Podría ser que un apache server nos engañe con la versión, etc… Todo esto nos puede hacer caer en falsos positivos y en honeypots, por tanto, hay que ir con cuidado y utilizar la información que nos da Shodan como una primera búsqueda que después tendremos que verificar.
Shodan API REST
Shodan dispone también de un API REST para realizar peticiones a sus servicios: https://developer.shodan.io/api
Podemos utilizar el API utilizando los endpoint que aparecen en la documentación y concatenando como parámetros el API KEY y la consulta a realizar.
Uno de los endpoint permite realizar una consulta de búsqueda en Shodan a través del parámetro query. La cadena proporcionada se utiliza para buscar en la base de datos de Shodan, con la opción de proporcionar filtros dentro de la consulta de búsqueda utilizando un formato de "nombre filtro: valor".
Por ejemplo, si queremos realizar una búsqueda, podemos utilizar el endopoint /shodan/host/search:
https://api.shodan.io/shodan/host/search?key=<YOUR_API_KEY>&query=<query>
Para realizar las peticiones correctamente es necesario indicarle el API_KEY que hemos obtenido cuando nos hemos registrado.
Por ejemplo, con esta petición obtenemos los resultados de búsqueda con la cadena “apache”, que devuelve una respuesta en formato JSON.
https://api.shodan.io/shodan/host/search?key=<API_KEY>&query=apache
En este punto podríamos declararnos una función en python que a partir de una dirección ip obtenga esta información en formato json.
En el siguiente script lo que hacemos es obtener la información de un servidor a partir de su dirección ip.
Recuerda modificar la variable SHODAN_API_KEY y añadir tu propia clave que has obtenido en el proceso de registro.
Puede encontrar el siguiente código en el archivo shodan_obtener_host.py:
import requests SHODAN_API_KEY = "API_KEY" ip = '8.8.8.8' def ShodanInfo(ip): try: result = requests.get('https://api.shodan.io/shodan/host/'+ip+'?key='+SHODAN_API_KEY+'&minify=True').json() except Exception as exception: result = {"error":"Informacion no disponible."} return result print(ShodanInfo(ip))
Una salida del script anterior podría ser la siguiente:
{'region_code': None, 'ip': 134744072, 'postal_code': None, 'country_code': 'US', 'city': None, 'dma_code': None, 'last_update': '2020-06-09T14:42:14.527189', 'latitude': 37.751, 'tags': [], 'area_code': None, 'country_name': 'United States', 'hostnames': ['dns.google'], 'org': 'Google', 'data': [], 'asn': 'AS15169', 'isp': 'Google', 'longitude': -97.822, 'country_code3': None, 'domains': ['dns.google'], 'ip_str': '8.8.8.8', 'os': None, 'ports': [53]}
Acceso a Shodan desde Python
La librería oficial de shodan en lenguaje python está disponible en el repositorio de Github: https://github.com/achillean/shodan-python
La interfaz de línea de comandos (CLI) de shodan está empaquetada con la librería oficial de Python para Shodan, lo que significa que si estás ejecutando la última versión de la librería, deberías tener acceso a la consola.
Para instalar el módulo de Python lo podemos hacer con el comando:
pip install shodan
Con Shodan cli podríamos realizar también nuestras consultas desde línea de comandos instalando el cliente de python:
Para inicializar la herramienta es necesario indicarle el API KEY con el comando:
$ shodan init <API_key>
El comando shodan host permite visualizar información sobre un host, conocer su geolocalización, puertos que están abiertos, y qué organización es propietaria de esa dirección IP.
El comando shodan search permite realizar una búsqueda en Shodan y visualizar los resultados en la terminal de manera amigable.
Por defecto muestra la dirección IP, puerto, nombres del host y otros datos. Se puede utilizar el parámetro --fields“ para imprimir campos de banners en los cuales se está interesado.
$ shodan search --fields ip_str,port,org,hostnames apache tomcat
Shodanploit
Esta herramienta se trata de un script en python que contiene todas las llamadas a la API de shodan desde línea de comandos: https://github.com/ismailtasdelen/shodanploit
Con esta herramienta se puede tener todas las llamadas que hacemos a Shodan desde nuestra terminal, también nos permite hacer búsquedas detalladas sobre lo que queremos buscar.
Lo único que necesitamos hacer es añadir la API key de Shodan al arrancar el script.
Búsquedas de Shodan en python
Shodan tiene servidores que escanean internet, catalogan los resultados de los escaneos y luego permiten que las personas busquen y visualicen esos resultados.
Por ejemplo, cuando un usuario le pide a Shodan que le muestre todos los servidores Microsoft IIS versión 8 que se ejecutan en el puerto 8080 de TCP en China, le mostraría los que el sistema tiene registrado, pero desde el punto de vista de privacidad del usuario ninguno de esos servidores sabe qué usuario es el que buscó esta información.
Con la función search que ofrece la API se pueden realizar búsquedas de la misma forma que se puede hacer con la interfaz web.
Puede encontrar el siguiente código en el archivo busqueda_shodan.py:
import shodan SHODAN_API_KEY = "API_KEY" shodan = shodan.Shodan(SHODAN_API_KEY) try: resultados = shodan.search('apache') print("Numero de resultados:",resultados.items()) except Exception as exception: print(str(exception))
Si ejecutamos el siguiente ejemplo desde la terminal, vemos que si buscamos la cadena apache obtenemos xxx resultados.
También nos podemos crear nuestra propia clase llamada ShodanSearch que tenga como métodos el __init__ para inicializar el objeto de Shodan a partir de la API_ KEY que hemos obtenido cuando nos hemos registrado. Podemos tener también un método buscar que se le pase por parámetro la cadena de búsqueda y llame al método search del api de shodan.
Puede encontrar el siguiente código en el archivo ShodanSearch.py:
class ShodanSearch: """ Clase para buscar en Shodan """ def __init__(self,API_KEY): self.api = shodan.Shodan(API_KEY) def buscar(self,cadena): """ Busca en funcion la cadena pasada por parametro """ try: # Buscamos lo de la cadena pasada como parametro resultado = self.api.search(str(cadena)) return resultado except Exception as exception: print("Ha ocurrido un error: %s" % exception) resultado = [] return resultado
Realizar búsquedas por un host determinado
En este ejemplo vemos que con el método shodan.host() es posible obtener información de una determinada ip como país, ciudad, proveedor de servicios, servidores, versiones.
En la clase que hemos utilizado anteriormente ShodanSearch.py podríamos definir un método que se le pase por parámetro la IP del host y llame al método host() de la API de shodan.
def obtener_info_host(self,IP): """ Obtiene la info que pueda tener shodan sobre una IP """ try: resultados = self.api.host(IP) return resultados except Exception as exception: print("Ha ocurrido un error: %s" % exception) resultados = [] return resultados
La llamada a este método se podría hacer de esta forma:
resultados = shodan.obtener_info_host("8.8.8.8") for key, value in results.items(): print(key, "-->", value)
Ejecución ShodanSearch
Al añadir el método anterior, nuestro script de ShodanSearch.py aceptaría por parámetro una cadena de búsqueda y la dirección IP del host:
Como resultado obtenemos una respuesta en forma de estructura diccionario que podemos recorrer fácilmente con el método items() en formato clave-valor
El código anterior solicita información sobre la resolución DNS 8.8.8.8 de Google y la almacena en la variable info.
El resultado de api.host() devuelve información sobre los servicios que ejecuta así como el proveedor de alojamiento.
Entre las propiedades que devuelve la llamada destacar:
- data: una lista de banners que proporcionan detalles sobre los servicios que tenían un puerto abierto en dicho servidor.
- port: una lista de puertos abiertos para la dirección ip proporcionada.
- tags: Shodan hace validación extra para algunos servicios/dispositivos y tiene etiquetas especiales para facilitar la identificación de ciertos tipos de dispositivos (por ejemplo, la etiqueta- icspara identificar sistemas de control industrial).
Actividad práctica: Completar el código que permite obtener banners e información del servicio de Shodan
Completar el código con las variables y método que permiten completar la funcionalidad con el objetivo de obtener banners e información del servicio de shodan a partir de la información que devuelve el API REST y el método que obtiene información a partir de una determinada dirección IP.
#!/usr/bin/env python import shodan import requests SHODAN_API_KEY= "xxx" api = shodan.xxx(SHODAN_API_KEY) dominio = 'www.python.org' dnsResolve = 'https://api.shodan.io/dns/resolve?hostnames=' + xxx + '&key=' + xxx try: # Primero necesitamos resolver nuestro dominio a una IP resolved = requests.get(xxx) hostIP = xxx.xxx()[xxx] # Entonces necesitamos hacer una busqueda de Shodan en esa IP host = api.xxx(xxx) print("IP: %s" % xxx['ip_str']) print("Organization: %s" % xxx.get('org', 'n/a')) print("Operating System: %s" % xxx.get('os', 'n/a')) # Imprimir todos los banners for item in xxx['data']: print("Port: %s" % xxx['port']) print("Banner: %s" % xxx['data']) except shodan.APIError as exception: print('Error: %s' % exception)
La salida sería similar a la siguiente donde por cada puerto abierto muestra información sobre el servicio:
IP: 151.101.208.223
    Organization: Fastly
    Operating System: None
    Port: 80
    Banner: HTTP/1.1 500 Domain Not Found
    Server: Varnish
    Retry-After: 0
    content-type: text/html
    Cache-Control: private, no-cache
    connection: keep-alive
    X-Served-By: cache-ewr18149-EWR
    Content-Length: 283
    Accept-Ranges: bytes
    Date: Sat, 06 Jun 2020 09:05:06 GMT
    Via: 1.1 varnish
    Connection: keep-alive</p>
    Port: 443
    Banner: HTTP/1.1 500 Domain Not Found
    Connection: keep-alive
    Content-Length: 251
    Server: Varnish
    Retry-After: 0
    content-type: text/html
    Cache-Control: private, no-cache
    X-Served-By: cache-ewr18133-EWR
    Accept-Ranges: bytes
    Date: Wed, 03 Jun 2020 04:23:00 GMT
    Via: 1.1 varnish
Solución
#!/usr/bin/env python import shodan import requests SHODAN_API_KEY= "0LHBvGVGZmepTE4Kg1RKGbNN2o6B3Q48" api = shodan.Shodan(SHODAN_API_KEY) dominio = 'www.python.org' dnsResolve = 'https://api.shodan.io/dns/resolve?hostnames=' + dominio + '&key=' + SHODAN_API_KEY try: # Primero necesitamos resolver nuestro dominio a una IP resolved = requests.get(dnsResolve) hostIP = resolved.json()[dominio] # Entonces necesitamos hacer una busqueda de Shodan en esa IP host = api.host(hostIP) print("IP: %s" % host['ip_str']) print("Organization: %s" % host.get('org', 'n/a')) print("Operating System: %s" % host.get('os', 'n/a')) # Imprimir todos los banners for item in host['data']: print("Port: %s" % item['port']) print("Banner: %s" % item['data']) except shodan.APIError as exception: print('Error: %s' % exception)
Utilizando Shodan para la obtención de información de un servidor FTP
Shodan permite realizar una búsqueda de servidores que tengan un acceso FTP con usuario anónimo y se pueda acceder sin usuario y password.
Si realizamos la búsqueda con la cadena "port: 21 Anonymous user logged in", obtenemos aquellos servidores ftp que son vulnerables por permitir el acceso anónimo.
El siguiente script permite obtener aquellas direcciones ip de servidores que permiten el acceso FTP de forma anónima.
Puede encontrar el siguiente código en el archivo ShodanSearch_FTP_Vulnerable.py
#!/usr/bin/env python import shodan import re sitios =[] shodanKeyString = '<API_KEY>' shodanApi = shodan.Shodan(shodanKeyString) resultados = shodanApi.search("port: 21 Anonymous user logged in") print("numero de hosts: " + str(len( resultados['matches']))) for resultado in resultados['matches']: if resultado['ip_str'] is not None: sitios.append(resultado['ip_str']) for sitio in sitios: print(sitio)
Shodan eye
Esta herramienta recopila toda la información sobre todos los dispositivos que están directamente conectados a Internet con las palabras clave especificadas. Para su instalación y ejecución necesitamos bajarnos el código del siguiente repositorio de github: https://github.com/BullsEye0/shodan-eye
pip3 install shodan git clone https://github.com/BullsEye0/shodan-eye shodaneye cd shodaneye python3 shodan-eye.py





