Archivo

Archive for the ‘Web Applications’ Category

Phishing 2.0 con Evilginx2 – Parte 1.

noviembre 6, 2019 2 comentarios

Los ataques de phishing tradicionalmente se han basado en una plantilla con una estructura fija, la cual evidentemente puede quedar desactualizada rápidamente si no se mantiene y lo que es peor, es necesario poner una URL “rara” que probablemente nada tiene que ver con el dominio objetivo, la cual con un vistazo más detallado se puede apreciar claramente que no es el dominio del sitio web legitimo. Aún así, los ataques de este tipo siguen siendo predominantes y con unos muy buenos niveles de éxito. Existen un buen número de herramientas que permiten emprender este tipo de ataques con plantillas fijas y del mismo modo le permiten al atacante crear las suyas. No obstante, hoy en día ya encontramos lo que se conoce como el “phishing 2.0” y herramientas como Evilginx2 definen las bases de este tipo de ataques, más sofisticados y efectivos que los ataques de phishing clásicos basados en plantillas.

Evilginx2 es una herramienta que ha sido desarrollada en Go y que cuenta con las siguientes características:

* Se encarga de levantar de forma automática un servidor DNS para resolver las peticiones que se vayan a realizar contra un dominio concreto.

* Realiza un ataque de “Hombre en medio”, en donde no hace falta tener plantillas HTML fijas con la estructura del sitio web objetivo. Evilginx2 se encarga de realizar una petición HTTPS contra el sitio web legitimo y enseñar la estructura que devuelva el sitio web a la víctima.

* Evilginx2 es capaz de hacer un bypass sobre mecanismos de 2FA dado que no realiza ningún tipo de modificación sobre la estructura de la página, simplemente se encarga de actuar como cualquier cliente para el sitio web legitimo permitiendo que sea la víctima la que realiza la interacción con el servicio.

* Solicita y configura automáticamente un certificado SSL valido (Lets Encrypt) para el dominio que se utilizará para el ataque de phishing.

* Es capaz de mantener la condición de MITM entre la víctima y el sitio web legitimo tras la autenticación correcta. Esto permite capturar no solamente cookies de sesión o usuarios y contraseñas en texto plano, también permite obtener información sensible en la medida que el usuario va navegando por el sitio web legitimo pasando primero por el dominio configurado con Evilginx2.

Estás son solamente algunas de las “maravillas” que es capaz de hacer la herramienta. Sin embargo, existen algunas complicaciones que se pueden presentar en la configuración de este tipo de ataques con Eviginx2.

* Es necesario contar con una IP pública para poder resolver las peticiones DNS contra el dominio controlado por Evilginx2. Esto puede ser por medio de un VPS o servidor dedicado en cualquiera de los proveedores disponibles en Internet.

* Es necesario adquirir y configurar correctamente un dominio DNS. Como se verá más adelante, es necesario crear un registro DNS del tipo “A” que apunte a la IP pública donde se encuentra en ejecución Evilginx” y algunos registros “CNAME”.

* Dada la naturaleza de este tipo de ataque, si se realiza una campaña muy extensa o contra un objetivo “delicado”, es posible que el proveedor del VPS reciba quejas y que dependiendo de la gravedad de las actividades, se lleven a cabo acciones legales. En una campaña llevada a cabo por ciberdelincuentes profesionales, lo más probable es sea rápida y precisa, además también es posible que el proveedor del VPS contratado sea anónimo de tal manera que se dejen el menor número de trazas posible.

Requisitos e instalación.

Ahora que el lector entiende de qué va esto y el posible impacto que puede tener, resulta interesante pasar a la práctica viendo cómo instalar y configurar la herramienta para llevar a cabo un ataque de éste tipo.

En primer lugar, lo requisitos son los siguientes para que esto funcione bien.

  • Una dirección IP pública en un VPS o servidor dedicado. Se puede conseguir lo mismo en un entorno domestico creando reglas NAT en router que se encarguen de redireccionar las peticiones hacia el interior de la red local, sin embargo este enfoque es totalmente desaconsejado ya que el router no tendrá una IP fija todo el tiempo y además, es posible que Evilginx2 no funcione correctamente en este caso.
  • Un dominio correctamente configurado.
  • Una instalación limpia de Eviginx2, la cual puede ser partiendo del código fuente o de alguno de los paquetes precompilados que están preparados para ser descargados y ejecutarlos directamente, siendo ésta última opción la más sencilla y cómoda.

Primero lo más sencillo, la instalación. El repositorio oficial se encuentra disponible en GitHub: https://github.com/kgretzky/evilginx2 en dicho repositorio se incluyen las instrucciones básicas para su instalación, algo que no lleva mucho tiempo si se cuenta con todas las dependencias en GO requeridas por el programa. En “releases” se puede apreciar que existen paquetes preparados para utilizar la herramienta directamente.

Al ejecutar la herramienta es importante hacerlo con privilegios de root, utilizando “sudo” por ejemplo, ya que es necesario abrir el puerto 53 para el servidor DNS que levanta la herramienta. Se puede apreciar una tabla de phishlets, algo que se mencionará más adelante.

A continuación es necesario cumplir con los otros dos requisitos obligatorios que se han indicado anteriormente: Una IP pública y un dominio. Sobre el primero de ellos, es importante tener en cuenta que en dicha dirección IP pública se debe ejecutar Evilginx2. Es decir, la imagen anterior que enseña la ejecución de la herramienta corresponde a una instancia de Evilginx2 ejecutándose, en este caso concreto, en un VPS con una IP pública.

Sobre el segundo requisito, es necesario contar con un dominio correctamente configurado. Existen cientos de servicios en Internet que permiten contratar un dominio por muy bajo precio, sin embargo para realizar pruebas se puede utilizar un servicio como freenom.com el cual permite adquirir dominios de forma gratuita por un tiempo fijo.

Configuración del ataque.

A modo de ejemplo, se realizará un ataque de phishing con Evilginx2 utilizando el dominio “es-twitter.ml”. La selección de éste dominio es totalmente arbitraria, el lector puede elegir el que quiera.

En freenom se puede configurar el dominio recién creado fácilmente. En este caso interesa crear registros del “A”, “CNAME” y los correspondientes “NS”. Primero se configurarán los registros “NS” y “A”, posteriormente los registros CNAME tras configurar el dominio en Evilginx2. Como una imagen vale más que mil palabras, la configuración sería como se puede ver a continuación.

Con esto será suficiente para tener el los registros NS correctamente establecidos. Ahora, el registro “A” será como se puede ver a continuación. (Evidentemente, es necesario poner la IP en donde se encuentra Evilginx2 en ejecución).

Con esto el dominio está prácticamente listo. Ahora es necesario habilitar el “phishlet” correspondiente a Twitter para poder continuar con la configuración y posterior preparación del ataque. Un phishlet es similar a las plantillas que se utilizan en las herramientas destinadas a este tipo de ataques, sin embargo, en lugar de contener una estructura HTML fija, contienen “metainformación” sobre cómo conectar con el sitio objetivo, parámetros soportados y páginas de inicio a las que debe de apuntar Evilginx2. Los phishlets son ficheros de texto en formato YAML y la herramienta se encarga de cargarlos desde el directorio <EVILGINX2_ROOT>/phishlets esto significa que es posible crear ficheros en formato YAML para sitios web concretos que no se encuentran entre los que vienen por defecto en la herramienta. Algo que es bastante habitual en una campaña de RedTeam en la que se aplican técnicas de Phishing 2.0.

Bien, ahora que el dominio se encuentra “casi” configurado por completo, es el momento de abrir la terminal con Evilginx2 y realizar algunas configuraciones básicas. En primer lugar, el comando “help” enseñará los comandos disponibles en la herramienta, que como se puede ver, no son muchos.

El primer comando a ejecutar será de configuración global, para establecer el dominio y la IP pública.

Ahora es el momento de habilitar el phishlet correspondiente, que en este caso será el de Twitter.

El primer comando ha permitido habilitar el phishlet “twitter” y ha establecido el hostname que será utilizado para el ataque de phishing. En este caso concreto, la URL “twitter.com.es-twitter.ml” será el señuelo que se le enviará a las víctimas. Algo que resultará totalmente “creíble” al ver que la conexión se establecerá por HTTPS con certificado perfectamente valido y que además, en la URL pone “twitter.com”. Mucha gente seguramente picará. Bien, pero antes de continuar con los detalles del ataque, es necesario terminar la configuración del dominio. Al ejecutar el segundo comando se obtienen los registros CNAME que hay que incluir en la configuración del dominio en freenom. La configuración final del dominio será como se puede apreciar en la siguiente imagen.

Con estos pasos ya se encuentra todo preparado para elaborar el ataque de Phishing con Evilginx2, algo se explicará en detalle en el próximo post.

Si has hecho todo bien hasta aquí, el siguiente paso que corresponde a la ejecución del ataque propiamente dicho será bastante fácil y rápido.

Un saludo y Happy Hack
Adastra.

Herramientas de pentesting interesantes: Shellphish – Parte 3

noviembre 1, 2019 2 comentarios

Sin lugar a dudas, los ataques de phishing hoy en día sustituyen una de las amenazas más frecuentes cuando se habla de seguridad perimetral y es que el factor humano es siempre, el más problemático y difícil de gestionar en todos los aspectos de una organización. No es de extrañar que en algunas pruebas de seguridad enfocadas al RedTeam se incluyan este tipo de técnicas con el objetivo de medir la seguridad del perímetro desde adentro. Quiénes han picado en un ataque de phishing y han pinchado en el enlace, quiénes no han sabido detectar que ese correo electrónico contiene un enlace a un sitio malicioso. Son cuestiones que se afrontan con la formación a los empleados y a la que difícilmente las soluciones de seguridad perimetral pueden hacer frente de forma eficaz. En este sentido existen múltiples herramientas y frameworks enfocados a la ejecución de campañas de phishing, cuyo objetivo es precisamente probar la seguridad del perímetro de una organización ante este tipos de ataques aunque como es evidente, también son herramientas que dadas sus funcionalidades y lo bien hechas que están se utilizan directamente por parte de ciberdelincuentes. En este post hablaré de una de estas herramientas llamada “shellphish”, que sin ser la más interesante o potente sí que hace bien su trabajo y para lo que fue desarrollada por lo tanto merece una mención. En próximos posts hablaré de herramientas mucho más completas y con un enfoque más moderno como es el caso de “evilginx” o “gophish”.
NOTA: Si te interesa aprender más en profundidad sobre técnicas de ingeniería social, es posible que te resulten útiles los recursos del “Social Engineering Framework” (https://www.social-engineer.org/framework/general-discussion/) y el uso de otras herramientas como SET de las que ya he dedicado una serie completa hace algunos años, empezando aquí.

Introducción y uso de Shellphish

Se trata de una herramienta que provee un conjunto de plantillas para los sitios más populares en Internet, entre los que se encuentran Facebook, Twitter, Netflix, Instagram, entre otros. No obstante, dada su flexibilidad es posible crear plantillas personalizadas para sitios web que no se encuentran incluidos en la herramienta, de tal manera que es posible llevar a cabo campañas de phishing contra un objetivo concreto. El uso de la herramienta es realmente simple, basta con seleccionar una plantilla, establecer el tipo de servidor para que sea accesible desde Internet (puede ser serveo.net o Ngrok) y posteriormente, esperar a que el usuario “pinche” en el enlace que se enviaría por email (o cualquier otro medio).

Para instalar la herramienta, basta con clonar el repositorio oficial y ejecutar el script “shellphish”

>git clone https://github.com/thelinuxchoice/shellphish.git

>cd shellphish && chmod 755 shellphish.sh

>./shellphish.sh

Una de las dependencias obligatorias de la herramienta es una versión reciente de PHP, dado que se encuentra desarrollado en dicho lenguaje. Cuando se ejecuta el script de shellphish se abre un asistente muy básico en donde se puede apreciar un listado de las plantillas soportadas por la herramienta y el permite al usuario seleccionar una de ellas.

Se puede seleccionar cualquiera de los servicios disponibles, pero hay que tener en cuenta que las plantillas son fijas, es decir, que si existe algún cambio en cualquiera de los sitios web legítimos, dicho cambio tendrá que ser aplicado también en la plantilla para que sea más creíble. El funcionamiento interno de la herramienta también resulta sencillo. En el directorio <SHELLPHISH_ROOT>/sites se encuentran todas las plantillas de cada uno de los sitios que se listan en el menú principal. En cada uno de los directorios correspondientes a dichos servicios, aparecen como mínimo los siguientes ficheros:
index.php: Se encarga de ejecutar un “include” del fichero “ip.php” y posteriormente realiza una redirección incluyendo la cabecera “Location” en la respuesta con el valor “login.html”.

login.html: Como es natural, incluye la estructura HTML del sitio web legitimo, sin embargo dicha página web está configurada de tal manera que las acciones sobre ella (por ejemplo, pinchar sobre el botón de login) son procesadas por el script “login.php”.

ip.php: Se trata de un script que se encarga de recopilar la información del cliente que accede al sitio web falso. Incluye información básica como la IP del navegador de la víctima, país, ciudad, ISP, etc.

login.php: Es un script que simplemente se encarga de almacenar y enseñar por pantalla la información de login del usuario.

Todas las plantillas en shellphish tienen lo mismo, por lo tanto es fácil extender esto a otras plantillas personalizadas, es decir, a otros sitios web que no se encuentren en la lista de plantillas por defecto en la herramienta.

Después de seleccionar la plantilla a utilizar, la herramienta pedirá al atacante que seleccione el tipo de servidor web para la plantilla seleccionada en el paso previo. En este caso cualquiera de las dos opciones es valida ya que ambas funcionan bastante bien (Serveo.net o Ngrok). Posiblemente resulte conveniente utilizar Serveo.net dado que las conexiones pasan por medio de un túnel SSH.

Una vez que el servidor web se encuentre levantado y la víctima haya entrado en el sitio web falso, se ejecuta el fichero “ip.php” que se encuentra disponible en la plantilla seleccionada y que tal como se ha explicado anteriormente, se encarga de recolectar información básica sobre el navegador del usuario.

A continuación, la víctima podrá ver la misma estructura del sitio web, así que salvo que se fije en la URL no hay nada que en apariencia resulte sospechoso. Si el usuario trata de iniciar sesión en el supuesto servicio, se ejecutará el script “login.php” que se encargará de procesar lo que el usuario ha escrito en las cajas de texto (típicamente, usuario y contraseña).

Se puede ver que además, se encarga de guardar estos detalles en un fichero de texto que posteriormente se puede consultar fácilmente. Todas las plantillas en Shellphish tienen el mismo comportamiento.

Con shellphish también es posible crear plantillas personalizadas y para ello la herramienta cuenta con un asistente que paso a paso, establece un sitio web genérico en el que se pide usuario y contraseña. No obstante es bastante básico lo que genera la herramienta (por no llamarlo cutre) por lo tanto para un ataque de phishing real será mucho más conveniente crear la plantilla manualmente, que como se ha explicado antes no tiene ninguna dificultad, basta simplemente con crear un directorio en <SHELLPHISH_ROOT>/sites con el nombre del sitio web e incluir los ficheros mencionados unos párrafos más arriba.

Para activar el asistente en shellphish se debe seleccionar la opción “Custom” y tal como se puede ver en la siguiente imagen, es necesario comenzar a rellenar ciertos campos.

Ahora, cuando una potencial víctima entra en “https://torrens.serveo.net” podrá ver lo siguiente. Algo que a mi gusto resulta bastante deficiente desde el punto de vista estético, por este motivo es posible que el mejor enfoque sea crear la plantilla manualmente.

Se trata de una herramienta para realizar ataques de phishing basados en servicios existentes, sin embargo dada su simplicidad también es posible crear plantillas personalizadas partiendo de la clonación de un sitio web legitimo. Sin ser una herramienta con muchas características o funcionalidades, cumple bastante bien con el objetivo para el que fue creada.

Un Saludo y Happy Hack!
Adastra.

Herramientas de pentesting interesantes: Jok3r – Parte 2

septiembre 20, 2019 1 comentario

En el post anterior se ha comenzado a hablar de Jok3r y sus funcionalidades básicas, una herramienta que es interesante desde el punto de vista de un pentester dado que integra muchas de las herramientas de uso común en auditorías de red y web. En dicho post solamente se han mencionado los comandos básicos, el manejo de bases de datos locales y cómo instalar la herramienta utilizando la imagen oficial de Docker. Ahora, resulta conveniente ver cómo utilizar lo visto anteriormente para realizar verificaciones de seguridad sobre un entorno concreto.
El comando utilizado para realizar las verificaciones de seguridad incluidas en Jok3r es “attack” el cual recibe múltiples opciones que sirven para configurar los detalles del objetivo, añadir los resultados a una base de datos local concreta o incluso para realizar ataques a múltiples objetivos que se encuentran almacenados en alguna “mission” de Jok3r. En la configuración del ataque es posible utilizar un perfil existente en Jok3r, que tal como se ha visto en el post anterior a este, se pueden consultar con el comando “info” de la siguiente forma:

python3 jok3r.py info –attack-profiles

Opciones en el comando “attack”

A continuación se verá una lista de las opciones disponibles para el comando “attack”, las cuales hay que conocer para poder lanzar las pruebas correctamente.

Opción Descripción
-t / –target Permite especificar el objetivo del ataque. Puede ser una IP:Puerto, un nombre de dominio o una URL.
-s / –service Permite especificar un servicio concreto a auditar.
–add2db Permite añadir o actualizar los resultados obtenidos por el comando en la “mission” (base de datos local) especificada. Si no se utiliza esta opción, los resultados son añadidos/actualizados directamente en la mission “default”.
-m / –mission Permite leer una mission local y lanzar los checks de seguridad contra todos los objetivos registrados en dicha mission.
-f / –filter Filtro sobre los objetivos a los que se deben ejecutar las pruebas de seguridad. Normalmente viene acompañada de la opción “-m”. Los filtros disponibles son ip, host, port, service, url, osfamily y banner. Además, cada filtro debe venir separado por “;” y la sintaxis es “filtro=valor”. Por ejemplo:
“ip=10.1.1.0/24,10.0.0.4;port=80,8000-8100;service=http”. También es posible repetir esta opción varias veces en el mismo comando.
–new-only Realiza las pruebas de seguridad únicamente sobre los servicios que no han sido probados previamente.
–nmap-banner-grab Habilita o deshabilita un escaneo con Nmap del tipo “service detection”. Valores validos “on” y “off”
–reverse-dns Habilita o deshabilita las peticiones DNS reversas contra el objetivo. Valores validos “on” y “off”
–profile Permite ejecutar un perfil de ataque concreto.
–cat-only Permite ejecutar las pruebas de seguridad sobre las categorías especificadas únicamente. Cada categoría se indica separada por coma.
–cat-exclude Permite ejecutar las pruebas de seguridad sobre todas las categorías excepto sobre las especificadas en esta opción. Cada categoría se indica separada por coma.
–checks Permite ejecutar los checks especificados en esta opción. Cada check se indica separado por coma.
–fast Modo rápido. Desactiva la interacción con el usuario y todas las verificaciones se ejecutan en modo desatendido.
–recheck Si un check se ha ejecutado previamente, se vuelve a lanzar. Esto es útil especialmente cuando se utiliza una mission sobre la que se ha trabajado previamente e interesa que se vuelvan a realizar todas las comprobaciones.
-d Habilita el modo “debug”.
–userlist En el caso de encontrar un formulario o mecanismo de autenticación, la herramienta ejecuta un atacante por diccionario con listas que vienen incluidas en la herramienta. Con esta opción se utiliza una lista de usuarios indicada por el usuario
–passlist Con esta opción se utiliza una lista de contraseñas indicada por el usuario
–cred En el caso de que se cuente con las credenciales de un servicio concreto, en lugar de permitir que la herramienta ejecute un ataque de fuerza bruta se pueden indicar dichas credenciales en esta opción de la siguiente forma: –cred <service> <user> <pass>
–user Permite especificar un usuario concreto con el que se deberán realizar los ataques de fuerza bruta en el caso de encontrar un formulario o mecanismo de autenticación.
–option Permite especificar una opción personalizada, por ejemplo una cabecera HTTP concreta para realizar las peticiones contra un sitio web.

Conociendo las opciones, ya se puede utilizar el comando “attack” sin limitaciones. Evidentemente la forma más simple de hacerlo es contra un objetivo concreto y lanzando todas las comprobaciones. Por ejemplo:

python3 jok3r attack -t http://192.168.1.50/twiki/

La herramienta intenta obtener información sobre el servidor web utilizando “Wappalyzer” y también ejecuta un escaneo del tipo “service detection” para identificar el banner del servicio con Nmap. Al no indicar la opción “–add2db” todos los resultados serán guardados en la mission “default”.

Después de recopilar toda la información, la herramienta solicita confirmación para iniciar el ataque. Las comprobaciones pueden tardar un buen rato y en segundo plano, la herramienta se encargará de almacenar los resultados en la mission correspondiente. No obstante, dado que no se ha indicado la opción “–fast”, la herramienta pedirá confirmación antes de lanzar cualquier prueba, lo cual puede ser bastante tedioso tal como se enseña en la siguiente imagen.

El siguiente comando se encargará de lanzar todas las comprobaciones, en modo “fast” y añadiendo los resultados a la mission “adastra”.

python3 jok3r.py attack –fast -t http://192.168.1.50/twiki/

En la medida en la que se van ejecutando las pruebas, se puede apreciar la ejecución de herramientas comunes como “dirsearch”, “wig”, “nikto”, “h2t”, módulos de metasploit y scripts para la detección de vulnerabilidades en CMS, servidores de aplicación y frameworks concretos, aunque evidentemente muchas de estás comprobaciones estarán fuera de contexto dependiendo del objetivo a analizar.

Se pueden combinar todas las opciones indicadas en la tabla anterior, permitiendo ejecutar la herramienta de un modo más concreto contra el objetivo a analizar, por ejemplo.

 

#python3 jok3r.py attack -t 192.168.1.50:21 -s ftp –cat-only recon –add2db ftpmission
#python3 jok3r.py attack -m adastra -f “port=21;service=ftp” –fast #python3 #python3 jok3r.py attack -m adastra -f “port=2222;service=ssh;ip=192.168.1.1” -f “ip=192.168.1.50;service=ftp” –fast –recheck

Finalmente, cuando finalizan las comprobaciones de seguridad realizadas por la herramienta, todos los resultados se quedan almacenados en la base de datos local y a continuación se puede generar un reporte con la opción “report” del comando “db” tal como se enseña en la siguiente imagen.

Una vez se abre el reporte, se muestra cada una de las herramientas y pruebas realizadas para los hosts que se encuentran almacenados en la “mission” seleccionada. Se trata de un informe en formato HTML que está muy bien estructurado y que da una visión general de las vulnerabilidades descubiertas y la ejecución de las herramientas incluidas en el toolbox.

Bien, esto es todo sobre Jok3r, en el próximo post de esta serie hablaré sobre otra herramienta para pentesting que seguramente te resultará también muy interesante.

Un saludo y Happy Hack
Adastra.

Seguridad en ElasticSearch: modo cluster – Parte IV

septiembre 16, 2019 1 comentario

En el post anterior ya se ha hablado sobre algunas características avanzadas para la búsqueda de contenidos en ES, ahora es el momento de hablar sobre la configuración necesaria en ES para que funcione en modo cluster. En primer lugar hay que mencionar que cuando se inicia una instancia de ES, lo primero que hace es intentar unirse a un cluster si se han indicado los detalles en dicho cluster en la configuración, en el caso de que no sea así, se entiende que el nodo funcionará en modo “standalone” y en tal caso, creará un cluster en donde es la propia instancia la que funciona como “master”.

Configuración modo “cluster” con múltiples nodos.

La configuración en modo cluster de ES con múltiples nodos es considerada como una configuración para un entorno de producción. Esto significa que en primer lugar, la instancia de ES ya no se ejecutará únicamente en la interfaz de loopback como se ha visto hasta ahora, sino que evidentemente, debe estar disponible y alcanzable por otros nodos/instancias que harán parte del cluster. La configuración de todas las instancias de ES giran en torno al fichero “elasticsearch.yml” para cuestiones concretas de la instancia y otros ficheros como el “jvm.option” y “log4j2.properties”  para asignar valores de configuración a la VM de Java, evidentemente se trata de una labor de vital importancia para el tuning de una máquina virtual y el correcto funcionamiento de la instancia, pero se sale un poco del scope de estos post. Todos estos ficheros, así como el keystore y certificado de la instancia se encuentran en el directorio “config”.

ES normalmente requiere muy poca configuración y prácticamente todos los cambios se pueden realizar en caliente gracias a la API disponible en el motor, excepto la configuración en modo cluster, de hecho, si se ha iniciado una instancia con sus valores por defecto se creará un directorio llamado “data” el cual contiene toda la información de los nodos vinculados al cluster. Si se inicia una instancia de ES con la configuración por defecto y luego, se plantea integrar dicha instancia en un cluster existente, es importante tener en cuenta que no solamente será necesario editar el fichero de configuración como se explicará a continuación, sino que además se debe eliminar el directorio “data” para que la instancia comprenda que ahora no es el “master” de un cluster local, sino que se unirá a un cluster existe. Esto último es importante, ya que en el caso de no hacerlo se producirán errores en el arranque aunque la configuración sea correcta.

Ahora bien, los valores de configuración mínimos que se deben indicar en el fichero de “elasticsearch.yml” son los siguientes:

cluster.name: Nombre que tiene el cluster al que la instancia se unirá.
node.name: Nombre del nodo.
cluster.initial_master_nodes: Se trata de las direcciones IP o nombres de dominio de uno o varios nodos “master” del cluster objetivo.
transport.host: Interfaz de red o dirección IP utilizada internamente por los nodos del cluster para la comunicación. Por ejemplo, esta dirección junto con el puerto indicado en “transport.tcp.port” son utilizados por otros nodos en el cluster para las replicas de shards.
transport.tcp.port: Puerto que se abrirá en la interfaz indicada en “transport.host”.
http.host: Interfaz de red sobre la que se servirá la API rest de la instancia (por defecto es localhost).
http.port: Puerto vinculado a la interfaz indicada con la propiedad “http.host” (por defecto es 9200).
network.host: Interfaz de red a la que se vinculará el servicio de conexión de la instancia. Es decir, la interfaz de red sobre la que otros nodos del cluster se conectarán con la instancia local.
node.master: Valor booleano que indica si la instancia es master o no del cluster.

Esto es lo mínimo que debe de existir en un fichero de configuración de ES para que funcione en modo cluster con otros nodos, sin embargo hay muchas más opciones de configuración que se pueden consultar en la documentación oficial. https://www.elastic.co/guide/en/elasticsearch/reference/current/important-settings.html

Una configuración valida podría ser la siguiente:

Nodo master:

cluster.name: cluster-adastra
node.name: adastra-1
transport.host: 0.0.0.0
http.host: 0.0.0.0
network.host: 0.0.0.0
transport.tcp.port: 9300
node.master: true

Nodo slave1:

cluster.name: cluster-adastra
node.name: slave1-node
discovery.seed_hosts: [“192.168.1.144”] #Dirección IP del master.
cluster.initial_master_nodes: [“adastra-1”]
transport.host: 0.0.0.0
http.host: 0.0.0.0
network.host: 0.0.0.0
transport.tcp.port: 9300
node.master: false

Nodo slave2:

cluster.name: cluster-adastra
node.name: slave2-node
discovery.seed_hosts: [“192.168.1.144”] #Dirección IP del master.
cluster.initial_master_nodes: [“adastra-1”]
transport.host: 0.0.0.0
http.host: 0.0.0.0
network.host: 0.0.0.0
transport.tcp.port: 9300
node.master: false

Esto se puede ejecutar desde un mismo ordenador con 3 instancias independientes de ES, con máquinas virtuales, contenedores de Docker o máquinas físicas. No obstante aquí no termina la configuración, cuando se utiliza la propiedad “network.host” con un valor distinto de la interfaz de loopback provoca que ES ejecute una serie de comprobaciones sobre el sistema llamadas “bootstrap checks” las cuales se encargan de verificar que el sistema cumple con las especificaciones mínimas para que el nodo funcione correctamente en un entorno productivo y de esta manera reducir los problemas que puedan tener los usuarios al interactuar con nodos configurados “de aquella manera”. La configuración del sistema que se debe de aplicar para cumplir con los requisitos se explica en la documentación oficial: https://www.elastic.co/guide/en/elasticsearch/reference/current/system-config.html

En este apartado la documentación está bien detallada y explica qué se debe hacer a nivel de sistema para que el nodo arranque correctamente y se una a un cluster existente o funcione como master.

Como se puede apreciar en la imagen anterior, cuando existe cualquier tipo de problema en la instancia relacionada con los “bootstrap checks” la instancia simplemente no arranca. Sin embargo es algo fácil de resolver si se siguen las indicaciones que arroja la instancia de ES.

En esta última imagen se puede ver cómo debe de ser una configuración “buena” para el nodo que actuará como master, como se puede ver se han pasado todas las comprobaciones iniciales y posteriormente, se ha elegido al nodo “adastra-1” como master ya que es la forma en la que se ha indicado en la configuración gracias a la propiedad “node.master: true”.

De momento, con lo que se ha visto en éste post en las partes 1 , 2 y 3 es suficiente para comenzar a abordar cuestiones relacionadas con el pestesting y securización sobre instancias de ES.

Un saludo y Happy Hack.
Adastra.

Seguridad en ElasticSearch: búsquedas avanzadas y operaciones sobre índices – Parte III

septiembre 9, 2019 1 comentario

En el post anterior se ha hablado sobre como crear y gestionar índices así como la forma de realizar búsquedas con el endpoint “_search”, lo cual es el punto de entrada para comprender el funcionamiento de ES. Probablemente las características más complejas de este producto están precisamente relacionadas con las búsquedas, ya que como se verá en este post, existen varias maneras de aplicar filtros sobre índices y documentos.

En primer lugar, el endpoint “_search” no solamente admite peticiones GET, también es posible ejecutar una petición POST y en el cuerpo de la petición enviar filtros un poco más específicos que los que se podrían incluir en una petición GET. Por ejemplo:

POST /indice/tipo/_search
{ “query”: { “match”: { “title”: {
“query”: “palabra1 palabra2”,
“operator”: “and”}
}
}

“size”: 2,
“from”: 0,
“_source”: [ “campo1”, “campo2”, “campo3” ],
“highlight”: { “fields” : { “title” : {} } }
}

Se trata de una búsqueda más compleja, en la que se incluye el campo “query” que a su vez admite una estructura muy concreta para realizar la búsqueda. Con “match” se especifican los filtros, que en este caso aplican únicamente al campo “title”, es decir, que todos los documentos que tengan dicho campo serán objeto de búsqueda. Luego, se repite nuevamente el campo “query” pero en esta ocasión será útil para indicar un texto libre. Es posible utilizar operadores como “or” y “and”, de tal manera que dicha operación lógica se aplicará sobre las palabras especificadas en el campo “query”. En el ejemplo anterior, al aplicar el operador “and”, significa que la búsqueda devolverá solamente aquellos documentos que tenga en el campo “title” las palabras “palabra1” y “palabra2”. Luego, se puede apreciar en el cuerpo de la petición otros campos adicionales, tales como “size” y “from”, los cuales permiten devolver resultados en bloques, algo ideal para implementar búsquedas paginadas. Finalmente, los campos “_source” y “highlight” sirven para indicar aquellos campos del documento que devolverá la búsqueda, en este caso “campo1”, “campo2” y “campo3”. Si el documento tiene más campos estos no son incluidos en los resultado de la búsqueda.

El resultado de una búsqueda como la anterior es una estructura en formato JSON que contiene algunos campos interesantes, como por ejemplo “_source” y “score”. En el caso del primero, se trata de la estructura JSON con los resultados de la búsqueda, es decir, todos los documentos que han coincidido con los filtros especificados y el segundo, es el factor de coincidencia y es aquí en donde ES se complica un poco más, ya que ES internamente realiza una serie de calculos para asignar a cada resultado de las búsquedas un valor de coincidencia, esto es un indicativo que permite ubicar cada documento en un orden concreto en el listado de resultados. Pensad por ejemplo en Google, los enlaces a páginas externas que arroja cada búsqueda enseñan en las primeras posiciones aquellos que tienen mejor page rank, aquellos que pueden ser más interesantes para el usuario. ES hace lo mismo partiendo de los filtros que se incluyen en las búsquedas. Por ejemplo, en el caso anterior, cuantas más veces aparezca en un documento las palabras “palabra1” y “palabra2”, el documento tendrá mejor score y por lo tanto aparecerá en mejores posiciones dentro del resultado de la búsqueda. En la documentación oficial de ES podéis ver algunos ejemplos de búsquedas de este tipo para que quede un poco más claro, aunque desafortunadamente en mi opinión, la documentación oficial de ES es una de las más escuetas, poco claras y con más errores que me he encontrado hasta ahora en un producto de software, desafortunadamente es lo que hay y muchas veces toca pegarse con el producto para aprender realmente cómo funciona y ver las cosas que han cambiado, que ya no funcionan o que funcionan de forma diferente entre diferentes versiones. Los siguientes enlaces pueden ser útiles:

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html

Por otro lado, algunos de los campos que se han incluido en el cuerpo de la petición (los más simples) también se pueden incluir como parámetros en la URL del endpoint “_search”, por ejemplo:

GET /_search?size=5
Enseña los 5 primeros resultados de la búsqueda.

GET /_search?size=5&from=5
Enseña los resultados del 5 al 10.

GET /_search?size=5&from=10
Enseña los resultados del 5 al 15.

como se ha explicado anteriormente, ES se encarga ordenar los resultados de las consultas antes devolverlos basándose en el campo “_score”, por lo tanto es común y recomendable utilizar los mecanismos de paginación para evitar problemas de rendimiento en las consultas.

Operaciones sobre índices y documentos.

Es importante conocer la forma en la que ElasticSearch interpreta los documentos almacenados en un índice concreto, ya que es posible que algunos de los campos no contengan la estructura esperada, tal como se ha visto en el post anterior a este, es posible crear documentos que no siguen ninguna estructura referente a los campos. Para ver el “mapeo” que tienen los documentos (parecido a la definición de una tabla en una base de datos relacional) es necesario utilizar el endpoint “_mapping” disponible en el índice.

GET /index/_mapping

A la hora de crear un índice es posible incluir el campo “mappings” y especificar cómo será la estructura de los campos que podrán ser heredados por los documentos creados en el índice, por ejemplo:

PUT my_index

{ “mappings”: { “properties”: {
“campo”: { “type”: “keyword”}
}}}

Es recomendable echarle un vistazo a lo que se explica en la documentación oficial sobre los mapeos en índices: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html

Los índices pueden estar abiertos o cerrados, lo que significa que es posible trabajar  con ellos para operaciones de lectura/escritura o no. No es posible indexar documentos o realizar búsquedas sobre índices cerrados. Cuando un índice está cerrado, ES no mantiene las estructuras de datos internas para la búsqueda, es decir, los documentos no se indexan y por lo tanto, el consumo de memoria es menor. No obstante, dependiendo del tamaño de los documentos de dicho índice, un índice cerrado puede suponer un consumo considerable de disco duro ya que como resulta evidente, la información de dichos documentos se debe guardar de forma persistentemente en disco en el caso de que el índice se abra nuevamente. Abrir o cerrar un índice es muy sencillo tal como se muestra a continuación. (obviamente, “my_index” corresponde al nombre del índice).

* Abrir un índice: POST /my_index/_open
* Cerrar un índice: POST /my_index/_close

Alias sobre índices.

Una forma rápida y sencilla de obtener todos los índices disponibles en ES es por medio del endpoint “_aliases” el cual devuelve un listado de todos los alias disponibles para cada uno de los índices. Con este endpoint también es posible crear o eliminar alias (etiquetas) sobre los índices creados.

POST /_aliases {
“actions” : [ { “add” : { “index” : “test1”, “alias” : “alias1” } },
{ “remove” : { “index” : “test1”, “alias” : “alias2” } } ] }

En el caso anterior, las acciones utilizadas son “add” y “remove”. Se ha creado un alias el nombre “alias1” sobre el indice “test1” y además, se ha eliminado el alias “alias2” sobre el índice “test1”. Un índice puede tener múltiples “alias” sin que esto afecte a los documentos o estructura del índice.
Probablemente una de las características más potentes de los alias es que permiten crear vistas sobre los índices partiendo de los filtros, por ejemplo:

POST /_aliases {
“actions” : [ {“add” : {“index” : “test1”, “alias” : “alias2”,
“filter” : { “term” : { “campo” : “valor” } } } } ] }

Como se puede apreciar, se ha creado un alias con nombre “alias2” sobre el índice “test1”. Cuando se intente consultar dicho alias, ES aplicará el filtro indicado en el campo “filter” y devolverá los documentos que coincidan con la búsqueda. Esto en el mundo de las bases de datos relacionales es similar a las vistas, lo cual simplifica mucho las consultas que se pueden realizar contra un índice concreto. Para consultar el alias, se accede directamente al endpoint “_search”, por ejemplo:

GET /alias1/_search
GET /alias2/_search

Al realizar una petición como la anterior ES se encargará de buscar dicho alias, ver el índice al que apunta y si hay algún filtro, aplicarlo.

Los alias también se pueden utilizar como vistas de escritura, es decir, una forma de simplificar la creación de documentos con el atributo “is_write_index”.

POST /_aliases
{ “actions” : [
{ “add” : {“index” : “test”, “alias” : “alias1”, “is_write_index” : true } }
]}

Como se puede apreciar, para crear un alias en modo escritura, basta simplemente con incluir el campo “is_write_index” con el valor “true” a la hora de crearlo. Para utilizar el índice en modo de escritura se podrá realizar una petición POST o PUT de la siguiente forma.

PUT /alias1/_doc/1
{
“campo”: “valor”
}

En donde “_doc” es un endpoint que le permite a ES saber que se intenta acceder a la estructura de documentos que se encuentran almacenados en el índice al que apunta el alias “alias1”, luego en el cuerpo de la petición viene el JSON con el documento propiamente dicho.

Consultas interesantes en ES

Antes de finalizar este post, es conveniente conocer algunos de los endpoints disponibles en el producto para realizar consultas directas sobre el estado del nodo o cluster. Para ello existen varios endpoints interesantes que son muy sencillos y aportan información valiosa. Por ejemplo:

GET /_cat/master?v
GET /_cat/nodes?v
GET /_cat/indices?v
GET /_cat/plugins?v
GET /_cat/shards?v
GET /_cat/health?v
GET /_cat/master?help
GET /_nodes/node1,node2
GET /_nodes/process
GET /_nodes/_all/process
GET /_nodes/node1,node2/jvm,process
GET /_nodes/plugins
GET /_nodes/stats/indices
GET /_nodes/stats/os,process
GET /_nodes/192.168.1.101/stats/process
GET /_nodes/usage
GET /_nodes/nodeId1,nodeId2/usage
GET /_nodes/hot_threads

Son peticiones fáciles de entender y que permiten extraer información relevante sobre una instancia de ES en ejecución, de hecho, complementos como “cerebro”, “elasticsearch-HQ” o el propio Kibana hacen uso de estos endpoints de forma directa para enseñar la información en un formato amigable para el usuario.

En el próximo artículo de la serie se hablará sobre configuración de una instancia de ES y algunas consideraciones de seguridad que se entenderán mucho mejor después de haber leído la parte 1 y la parte 2 de la serie.

Un saludo y Happy Hack.
Adastra.

Herramientas de pentesting interesantes: Jok3r – Parte 1

septiembre 4, 2019 Deja un comentario

Desde hace bastante tiempo he querido escribir ésta serie de artículos pero por cuestiones de tiempo no había podido. Últimamente han ido apareciendo bastantes herramientas enfocadas al pentesting/hacking para diferentes contextos, algunas de ellas realmente interesantes y que merece la pena mencionar en este blog. Es importante automatizar todo el trabajo posible para soportar el procedimiento de descubrimiento, detección y posterior explotación de vulnerabilidades, incluyendo otras actividades que en ocasiones se deben realizar directa o indirectamente como ataques de Phishing, aplicación de técnicas OSINT, traceo y seguimiento de usuarios, análisis de tráfico, desarrollo de software, etc. No obstante, como siempre he dicho, ninguna herramienta o conjunto de ellas puede sustituir el trabajo y la metodología que aplica un pentester/hacker a la hora de lanzar un plan de ataque contra un objetivo, aunque las herramientas permiten recopilar información y en algunos casos, directamente explotar vulnerabilidades, lo más común es encontrarnos entornos en donde hay unas medidas de seguridad que ya tienen en cuenta las cosas más obvias, como actualizaciones y medidas de seguridad entre otras cosas. Dicho esto, no hay que olvidar nunca que como en prácticamente cualquier trabajo relacionado con tecnología, es necesario ser muy metódico, ordenado y limpio a la hora de realizar pruebas de penetración y esto es algo que no lo aprendes lanzando todo lo que viene en Kali Linux, lo aprendes con la experiencia y conociendo exactamente qué hacen por debajo las herramientas que utilizas en tu día a día para que no te conviertas en un “Nessus con patas” que solo lanza scripts y si no reportan nada es que todo está bien. Dicho esto, comenzaré a explicar algunas herramientas libres que me ido encontrando y que de alguna manera me han venido bien para trabajos que he realizado para algunos de mis clientes.

Jok3r: https://github.com/koutto/jok3r

Se trata de una herramienta particularmente interesante ya que no “reinventa la rueda” sino que en lugar de eso, reutiliza y combina un buen conjunto de herramientas de pentesting comunes para extraer la mayor cantidad de información de manera conjunta, sin tener que estar ejecutando cada una de forma independiente. Cuando se instala Jok3r el proceso puede tardar unos minutos ya que intenta instalar todas las dependencias y librerías necesarias por los proyectos que intenta combinar. También es posible instalar Jok3r desde su imagen oficial de Docker, una forma cómoda y rápida de tener la herramienta preparada para su uso.

Tal como se indica en el “README” del proyecto, cuenta con algunas características que la convierten en una herramienta muy interesante:

* Integración con más de 50 herramientas de pentesting comunes.

* Configuración sencilla, es posible eliminar o añadir herramientas con un simple fichero de configuración.

* Soporte a múltiples servicios de red basados en TCP y UDP, tales como HTTP, SSH, FTP, DNS, VNC, PostgreSQL, MySQL, etc.

* Se encarga de verificar el objetivo y seleccionar de forma automática las herramientas que puedan arrojar mejores resultados de acuerdo al contexto. Por ejemplo, en el caso de una aplicación web habilitará las herramientas relacionadas con pentesting en entornos web.

* Es capaz de detectar versiones y banners de productos específicos, para posteriormente compararlos con bases de datos CVE online, concretamente tirando de CVE Details y Vulners.

* Es capaz de realizar la explotación automática de algunas vulnerabilidades.

* Es capaz de realizar comprobaciones en CMS para detectar complementos o vulnerabilidades conocidas en Joomla, Drupal, WordPress, entre otros.

* Todos los resultados encontrados por la herramienta se van almacenando localmente en una base de datos y cuenta con algunas funcionalidades de reporting y gestión de resultados de forma independiente para cada auditoría realizada.

Bien, una vez visto el potencial de la herramienta lo siguiente es instalarla y usarla. Tal como se indica en las instrucciones de instalación del proyecto, la forma recomendada de hacerlo es utilizando la imagen Docker oficial, de esta forma no será necesario instalar dependencias directamente en el sistema host (son unas cuantas). No obstante, también se puede instalar directamente desde código fuente fácilmente, ya que cuenta con un script de instalación llamado “install_all.sh” que se encarga de dejarlo todo preparado para que sea posible utilizar la herramienta sin mayores dificultades. Basta simplemente con descargar la imagen y crear un nuevo contenedor, de la siguiente manera:

#sudo docker pull koutto/jok3r

#sudo docker run -i -t --name jok3r-container -w /home/adastra/jok3r -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --shm-size 2g --net=host koutto/jok3r

Las opciones “-w”, “-e”, “-v” y “–shm-size” son utilizadas para evitar problemas de memoria en el contenedor, así como para utilizar herramientas con una GUI como por ejemplo un navegador web. Con “–net” en Docker se especifica el modo de red, en este caso es compartido con el fin de que tanto anfitrión como contenedor se puedan ver y sea posible crear conexiones reversas.

Luego, para poder detener y volver a levantar el contenedor, se puede utilizar el comando “sudo docker start -i jok3r-container”

Una vez levantado el contenedor, es necesario dirigirse a la ruta “~/jok3r” que es donde se encuentra el script “jok3r.py”. Para ver las herramientas que se encuentran instaladas se debe ejecutar el comando:

#python3 jok3r.py toolbox --show-all

En el caso de la imagen Docker, se podrá ver que están todas las herramientas instaladas, luego para la gestión de las mismas, se pueden ejecutar los siguientes comandos:

Instalar todas las herramientas disponibles (algo que ya viene en la imagen de Docker).
#python3 jok3r.py toolbox --install-all --fast

Actualizar todas las herramientas sin realizar preguntas, todo sí y adelante. 
#python3 jok3r.py toolbox --update-all --fast
Desinstalar todas las herramientas.
#python3 jok3r.py toolbox --uninstall-all --fast
Desinstalar una herramienta concreta.
#python3 jok3r.py toolbox --uninstall-tool nombre_herramienta
Desinstalar un servicio concreto y las herramientas asociadas.
#python3 jok3r.py toolbox --uninstall nombre_servicio

Además del comando “toolbox” existen otros que permiten realizar verificaciones, ataques y ver el estado de la base de datos local.

Comando de información para los perfiles, servicios y productos.

El comando “info” permite ver qué perfiles se encuentran habilitados en la herramienta, las pruebas de seguridad que se aplican sobre cada protocolo soportado e información de los productos de software que se encuentran registrados en la herramienta. Tal como se ha visto antes con el comando “toolbox” hay una serie de opciones que permiten interactuar con éste comando.

Como se puede apreciar, el comando “info” soporta algunas opciones simples que permiten ver qué cosas puede hacer jok3r contra un objetivo determinado y otros detalles informativos que pueden ser útiles. Se puede ejecutar la herramienta de la siguiente manera.

#python3 jok3r.py info –services

Enseña una tabla con los servicios, puertos por defecto de cada servicio, herramientas asociadas y número de checks que realizará Jok3r sobre dicho servicio.

#python3 jok3r.py info --checks <servicio>

Enseña una tabla con el nombre de cada una de las comprobaciones disponibles para el servicio indicado, así como la categoría del chequeo y la herramienta empleada para ejecutarlo.

#python3 jok3r.py info –products

Enseña una lista de servicios disponibles y los diferentes tipos de productos que implementa dicho servicio, por ejemplo, para un servidor web, el producto puede ser Apache, Nginx, IIS, etc.

#python3 jok3r.py info –attack-profiles

Enseña una tabla con los perfiles de ataque disponibles, los cuales simplemente se encargan de agrupar varios checks y herramientas en un contexto concreto, por ejemplo para realizar comprobaciones sobre un CMS.

Base de datos local en Jok3r.

Antes de realizar cualquier tipo de auditoría de seguridad, en Jok3r se almacena todo en diferentes espacios de trabajo, de tal manera que cada auditoría y sus resultados correspondientes, se encuentran almacenados de forma persistente en contextos separados, esto es similar a lo que hay en Metasploit Framework cuando se utiliza el comando “workspace” desde msfconsole. El comando “db” es el encargado de definir misiones, las cuales son simplemente el contexto de una auditoría y partiendo de dichas misiones ejecutar pruebas de seguridad contra los objetivos indicados, los resultados quedarán almacenados en dicha misión.

Para crear una misión basta con ejecutar el comando “mission” tal como se aprecia en la imagen anterior.

Tal como se puede apreciar, el comando “mission” sirve para gestionar las misiones en Jok3r y además, al crear una nueva misión automáticamente cambia el contexto y ubica al usuario en la misión que se acaba de crear. Para moverse entre las diferentes misiones previamente creadas, se ejecuta el comando “mission <nombre>” y la herramienta se encargará de cambiar el contexto y apuntar a la misión indicada.

De momento esto es suficiente para ver las funcionalidades básicas de la herramienta, en el siguiente post se profundizará en su uso a la hora de ejecutar pruebas para auditorías de seguridad.

Un saludo y Happy Hack

Adastra.

Seguridad en ElasticSearch: Indices y búsquedas – Parte II

agosto 25, 2019 3 comentarios

En la primera parte de esta serie se han explicado las características funcionales incluidas en ES y los diferentes mecanismos de instalación. Ahora es el momento de comprender cómo funciona ES a la hora de crear índices, tipos y documentos, así como los endpoints disponibles en la API Rest para realizar búsquedas. La API Rest de ES es extensa y compleja, por lo tanto en estos posts solo se intentará cubrir las cuestiones relacionadas con la forma de realizar búsquedas, configuración de nodos/clusters, así como algunos complementos y medidas que pueden ayudar a mejorar la seguridad de una instancia de ES.

En primer lugar, hay que tener en cuenta que ES es bastante parecido a otros gestores de bases de datos no relacionales como MongoDB, especialmente en el sentido de que no hay una estructura fija. Esto significa que a diferencia de una base de datos relacional con tablas, las cuales están compuestas por un conjunto de columnas con restricciones en tipos de datos, relaciones con otras tablas (claves foráneas), longitudes, campos obligatorios, etc. En ES este tipo de estructuras y jerarquías a la hora de almacenar información son un poco diferentes. Para que esta idea quede clara, se expone el siguiente ejemplo:
En una base de datos relacional, se podría crear una tabla de usuarios, la cual estará compuesta por campos tales como: “nombre”, ”edad”, “genero”, “rol” y “fechaNacimiento”. A la hora de realizar una inserción de un registro en dicha tabla, se debe incluir como mínimo, un valor para todos aquellos campos que sean obligatorios y no se podría crear un registro que tenga un campo que no se encuentre definido en la tabla, es decir, no se podría crear un registro que incluya un campo llamado “direccionUsuario” dado que este campo no está en la definición de la tabla. Esto, en el mundo de ES no es así, ya que cada registro que es conocido como un document almacenado en un index y type concretos, no necesariamente tiene una estructura de campos fija, de hecho, se trata simplemente de estructuras JSON que pueden tener “cualquier cosa”, incluso elementos con múltiples valores como arrays, comportamiento que podría servir para crear relaciones de composición entre diferentes bloques de información, tal como se pretende hacer con las claves foráneas en una base de datos relacional. Los documentos en ES, desde el punto de vista técnico pueden estar compuestos por estructuras de datos no homogéneas, aunque evidentemente a la hora de diseñar un sistema es altamente recomendable definir una estructura base que será utilizada para la creación de registros en un nodo o cluster de ES. Dicho esto, es el momento de ver cómo crear índices, tipos y documentos.

¿Cómo crear registros en una instancia o cluster de ES?

Como se ha explicado en el post anterior a éste, para interactuar con una instancia o cluster de ES es necesario utilizar la API Rest que se encuentra disponible en cualquier nodo en ejecución. Se puede utilizar cualquier cliente HTTP para realizar peticiones contra dicha API Rest, desde CURL, wget, Postman hasta un objeto HttpConnection en Java o la librería “requests” de Python. El cliente empleado no es tan importante como conocer los endpoints disponibles y cómo se deben invocar de forma correcta. Probablemente la creación de índices es la labor más importante en ES y también, de las más sencillas tal como se puede apreciar en la siguiente imagen:

Utilizando Postman se ha creado un índice llamado “articulos”, con un tipo llamado “noticia” y un documento con identificador “2019001”. Si se quisiera comparar esta estructura con algo más familiar, como una base de datos relacional, “articulos” sería un esquema en la base de datos, “noticia” una tabla y “2019001” la clave primaria del registro insertado y luego, la estructura JSON que viaja en el cuerpo de la petición contiene los valores del registro propiamente dicho, cada uno en el campo que le corresponde. Sencillo, no?

Bien, esto es la operación de inserción pero también se puede gestionar el índice, tipos y documentos con operaciones CRUD (Create, Read, Update, Delete) tal como se puede apreciar a continuación.

Operación de lectura: Petición HTTP GET: http://ES_IP:ES_PORT/index/type/id

Operación de actualización: Petición HTTP POST: http://ES_IP:ES_PORT/index/type/id

Operación de borrado: Petición HTTP DELETE: http://ES_IP:ES_PORT/index/type/id

Gestionar índices en ES no es una labor compleja pero si vital para el correcto funcionamiento del sistema, ya que evidentemente es “el core” de la información y sobre los cuales trabajan otros endpoints de la API Rest disponibles en ES. Ahora que se ha visto cómo crear, obtener, actualizar y eliminar índices en ES, es el momento de hablar de búsquedas sobre estás estructuras de datos.

¿Cómo realizar búsquedas en ES?

Nuevamente es necesario utilizar la API Rest para realizar búsquedas contra ES. Dado que ES al igual que Lucene, se han creado precisamente para realizar búsquedas rápidas y potentes, no es de extrañar que ésta sea también una de sus características más complejas y difíciles de controlar. En este post solamente se explicará el proceso de búsquedas simples con el endpoint “_search”. En el próximo se hablará sobre la ejecución de búsquedas más complejas con múltiples filtros, paginación, acceso a mapeos, etc.

En primer lugar, el endpoint “_search” se pude utilizar directamente contra todos los índices disponibles en ES o contra uno concreto, nuevamente se puede utilizar Postman o cualquier cliente HTTP para realizar peticiones como las siguientes:

http://ES_HOST:ES_PORT/_search

Búsqueda sobre todos los índices disponibles en ES.

http://ES_HOST:ES_PORT/articulos/_search

Búsqueda sobre todos los documentos disponibles en el índice “articulos”.

http://ES_HOST:ES_PORT/articulos,negocios/_search

Búsqueda sobre todos los documentos disponibles en los índices “articulos” y “negocios”.

http://ES_HOST:ES_PORT/a*,n*/_search

Búsqueda sobre todos los documentos disponibles en los índices que empiezan por “a” y “n”.

http://ES_HOST:ES_PORT/articulos/noticia/_search

Búsqueda sobre todos los documentos disponibles en el índice “articulo” y tipo “noticia”.

http://ES_HOST:ES_PORT/_all/noticia,test/_search

Búsqueda sobre todos los documentos disponibles en todos los índices que tengan los tipos “noticia” y “test”.

http://ES_HOST:ES_PORT/articulos/noticia/_search?q=constitución

Búsqueda sobre todos los documentos disponibles en el índice “articulo” y tipo “noticia” aquellos cuyos en los que al menos un campo tenga la palabra “constitución”, o que se asemeje (esto se verá en el siguiente post).

Se trata de algunas de las peticiones más simples que se pueden ejecutar con ES y el endpoint “_search”, teniendo en cuenta que ahora mismo solamente se aplican filtros sobre índices y tipos, aún no se ha visto cómo filtrar por campos o paginar y además, las búsquedas anteriores se pueden hacer simplemente utilizando método HTTP GET. Como se verá en el siguiente post, esto se puede complicar bastante más dada la flexibilidad del motor de búsqueda y su potencia a la hora realizar consultas rápidas sobre volúmenes grandes de información.

Un saludo y Happy Hack.

Adastra.

A %d blogueros les gusta esto: