Archivo de la categoría: Networking

Docker 101 #1: Introducción a docker y los contenedores

docker-image

Hola lectores, en los últimos 6 meses he tenido la oportunidad de estar desarrollando mi carrera en una de las empresas de tecnología más grandes que hay en México, he estado trabajando muy de cerca en temas de Cloud computing, virtualizacion, bare metal e IaaS en general.

Es por eso que he decidido que es una buena idea crear una serie de tutoriales sobre docker, herramienta que considero esencial para los desarrolladores hoy en día, sobre todo si te atrae el mundo del cloud computing :). Si no tienes conocimientos previos de docker no te preocupes, planeo escribir tutoriales desde cero y voy a ir explicando cosas un poco más complejas conforme vayamos avanzando.

Un poco de teoria

Cuando hablamos de docker hablamos de contenedores. Pero ¿Que es un contenedor?, seguramente podrás encontrar una definición más formal de lo que es, pero imagínate que un contenedor es una caja que contiene tu solución de software, y no solo eso, también contiene las dependencias necesarias para ejecutar tu aplicación, las dependencias pueden ser librerías, configuraciones especiales e incluso otras aplicación o servicios que necesites (como un servidor web, nginx, apache, tomcat, etc.), todas las dependencias y aplicaciones dentro de una imagen están organizadas mediante un concepto de layers (capas), de esa manera cuando modificas un contenedor (una imagen) solo actualizas un layer en específico.

La gran ventaja de los contenedores es que, a diferencia de las máquinas virtuales estos no tienen asignadas cuotas específicas de recursos del sistema host (memoria, cpu, storage, etc), cuentan con un sistema de archivos virtual que permite que los contenedores se ejecuten de forma independiente y separada de los procesos del sistema, de esta manera la memoria de un proceso del contenedor no interfiere con un proceso de la maquina donde es ejecutado.

Un contenedor solo incluye consigo la aplicación y sus dependencias lo que hace que las imágenes de docker sean bastante livianas.

Otro de los grandes beneficios que nos aportan los contenedores es la potabilidad, me refiero a que si tienes una aplicación y la quieres migrar a otro sistema (por ejemplo de desarrollo a producción) puedes creas una imagen de docker que incluya tu solución y ejecutarla en cualquier otro sistema teniendo la certeza de que va a “correr” pues la imagen contiene todas las dependencias necesarias. Existen técnicas para “comunicar” nuestra maquina host con los contenedores como el mapeo de puertos y directorios, eso lo veremos en los siguientes tutoriales.

Conceptos básicos

  • Docker: Tecnología de software para creación y administración de contenedores.
  • Docker image: Un sistema de archivos virtual que puede contener aplicaciones y dependencias.
  • Docker container: Una imagen de docker que está siendo ejecutada, una instancia de una imagen.
  • Dockerhub: Un repositorio que contiene muchísimas imágenes de docker listas para ser descargadas.
  • DockerFile: Un script que indica una serie de pasos para construir una imagen de docker.

Bien suficiente teoría, si quieres saber más a fondo sobre docker pueden visitar el sitio web o ir a la documentación oficial

Instalar docker

Lo primero que debemos hacer es instalar docker, dependiendo de tu sistema operativo es el instalador que utilizaras, descarga docker de la página oficial, si estas en Windows descarga el ejecutable y sigue el wizard (siguiente, siguiente, siguiente), en Mac OSX puedes descargar una imagen dmg y hacer lo mismo, en mi caso lo que tengo a la mano es un sistema Linux, Ubuntu para ser específico y para proceder con la instalacion lo hago de la siguiente forma:

$ sudo apt-get install docker.io

Sea cual sea tu sistema operativo, una vez hayas instalado docker para verificar que la herramienta está bien instalada abre una consola y escribe el comando docker

$ docker

docker1

Si el resultado es un output similar al de la imagen significa que instalaste docker correctamente, si por el contrario recibes algún mensaje que dice que el comando docker no existe esto se puede deber a varias razones pero principalmente si estas en Windows verifica que la ruta al binario de docker se encuentre definida en tus variables de entorno.

Docker contiene muchisimos comandos pero los más importantes, o al menos los que utilizaras más son:

  • $ docker run
  • $ docker images
  • $ docker build
  • $ docker pull
  • $ docker ps
  • $ docker start
  • $ docker stop
  • $ docker commit
  • $ docker attach

Conforme vayamos avanzando en los tutoriales iré explicando que hace cada uno de ellos

Nuestro primer contenedor

Estamos listos para crear nuestro primer contenedor, abrimos una consola y escribimos el siguiente comando:

$ sudo docker run hello-world

El comando anterior le dice a docker que ejecute una nueva instancia (un contenedor) de la imagen hello-world, primero busca en el repositorio local y si no la encuentra va al dockerhub y procede a con la descarga.

docker2

¿Observas la parte que dice Pull complete?:

Unable to find image 'hello-world:latest' locally
latest: Pulling from hello-world

264eca88cf85: Pull complete 
f0cb9bdcaa69: Pull complete 
Digest: sha256:548e9719abe62684ac7f01eea38cb5b0cf467cfe67c58b83fe87ba96674a4cdd
Status: Downloaded newer image for hello-world:latest

Ahi es donde docker está mostrando el progreso de la descarga y los layers de la image, el resultado final de ejecutar este contenedor es el mensaje que dice: Hello from Docker!

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

Si ejecutamos el comando docker images, obtendremos una lista de las imágenes que tenemos disponibles localmente, y claro ahí tenemos nuestra imagen hello-world

$ docker images

docker3

Ahora veremos uno de los conceptos importantes de docker, el sistema de archivos virtual, vamos a descargar y ejecutar una imagen docker de ubuntu con el comando:

$ sudo docker run ubuntu

docker4

Corroboramos que tenemos una nueva imagen almacenada localmente:

[email protected]:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              426844ebf7f7        2 weeks ago         127.1 MB
hello-world         latest              f0cb9bdcaa69        3 months ago        1.848 kB

Ya tenemos una imagen docker de ubuntu, ¿Pero cómo accedemos a ella? ¿Cómo la utilizamos?, podemos utilizar el siguiente comando para acceder al contenedor en tiempo de ejecución utilizando una shell interactiva:

$ sudo docker run -t -i ubuntu /bin/bash

Cuando el contenedor este corriendo podrás navegar su sistema de archivos como lo harías normalmente en Linux, incluso si estas corriendo docker desde una maquina con Windows podrás ver que el sistema de archivos es de Linux, aquí es donde puedes empezar a considerar la opción de dejar atrás Cygwin y comenzar a utilizar un contenedor de ubuntu con todas las herramientas que necesites.

docker5

Para salir del contenedor utiliza el comando exit, como si terminaras una sesión remota de ssh.

Un punto importante a recalcar es que los contenedores no son persistentes, si creas un archivo dentro del contenedor la siguiente vez que lo ejecutes no existirá, posteriormente veremos cómo podemos solucionar eso. Por el momento quiero que entiendas los conceptos básicos de los contenedores en docker, como descargar imágenes y lanzarlas, los comandos básicos, etc.

Al inicio mencionaba el dockerhub, el repositorio público de donde puedes descargar miles de imágenes de docker, te invito a explorarlo e instalar las que más te gusten:

docker6

Servidor web nginx utilizando docker

Para terminar el tutorial mostrare rápidamente como podemos ejecutar un servidor web utilizando docker, como mencionaba, el dockerhub tiene miles de imágenes públicas y muchas comunidades de software libre están creando versiones “contenerizadas” de sus soluciones, en este caso el servidor web nginx, lo primero que debemos hacer es descargar la imagen de nginx para docker

$ sudo docker pull nginx

docker7

Ejecutamos docker images para verificar que se descargó correctamente:

[email protected]:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              426844ebf7f7        2 weeks ago         127.1 MB
nginx               latest              4c0e7e3661d2        2 weeks ago         181.4 MB
hello-world         latest              f0cb9bdcaa69        3 months ago        1.848 kB

Ahora para lanzar el contenedor utilizaremos el comando:

$ sudo docker run --name nginx-server1 -p 80:80 nginx

docker8

  • El comando docker run especifica que queremos correr un contenedor
  • El parametro –name nos permite definir un nombre único y amigable para esa instancia
  • El parametro -p nos permite mapear puertos entre el sistema operativo y los servicios que corren dentro del contenedor
  • Al final especificamos el nombre de la imagen de la cual queremos crear el contenedor, nginx en este caso

docker9

Incluso podemos abrir una segunda terminal y ejecutar el siguiente comando para lanzar un segundo servidor web contenerizado pero en un puerto diferente:

$ sudo docker run --name nginx-server2 -p 8080:80 nginx

docker10

Al lanzar cada una de las imágenes de nginx habrás notado que la consola se queda “ocupada” corriendo el contenedor, en el siguiente tutorial mostrare como evitar eso, finalmente para detener la ejecución del contenedor presiona ctrl+c

Si ejecutas el comando docker ps -a podras ver todas los contenedores que hemos creado hasta el momento, la mayoria no estara en ejecucion y puede ser eliminado utilizando docker rm [CONTAINER ID]

docker11

Si haz entendido bien los conceptos básicos ya te imaginaras el potencial de docker y hacia donde iré en los siguientes tutoriales :).

Saludos y happy hacking.

Solución al reto Capture The Flag de #CPMX6

dc-flag

Otro año, otro campus party al que asisto. En esta ocasión me di tiempo de asistir a varias conferencias y workshops que se impartieron durante el evento (y no solo pasármela en la zona gamer :p), además, al igual que en el evento pasado también estuve participando en el reto de seguridad que fue organizado por el Instituto Tecnológico Superior de Atlixco.

El wargame estuvo muy divertido (horas y horas de diversión) y me ayudo a conocer a mas colegas de la seguridad informática durante el evento, bueno sin mas preámbulo comienzo a explicar en que consistía cada uno de los retos y como fue que llegue a la solución.

Reto #1

Comenzando con lo básico, en el reto uno nos daban la IP donde había alojada una pagina web, la pagina tenia varias pestañas y la URL de cada una de las secciones tenia una estructura como la siguiente:

http://52.11.240.182/index.php?file=contacto.html

Jugando un poco con el parámetro file vemos que el sitio tiene una vulnerabilidad de Local File Inclusión. Utilizando la herramienta que desarrollo mi amigo @lightOS para explotar este tipo de vulnerabilidad https://github.com/lightos/Panoptic es posible automatizar el proceso y obtener archivos importantes del servidor, por ejemplo:

http://52.11.240.182/index.php?file=../../../../../../../../../../etc/apache2/envvars
http://52.11.240.182/index.php?file=../../../../../../../../../../etc/logrotate.d/apache2

ctf_cpmx_1

Sin embargo, el reto es mas sencillo que eso, en el archivo robots.txt (corrimos un dirbuster al sitio web) vimos que hay un archivo llamado dir.txt, revisando su contenido nos encontramos:

$ ls -l
html/
secreto.txt

secreto.txt, un archivo interesante, entonces aprovechamos el Local File Inclusion que teníamos y cargamos este archivo.

http://52.11.240.182/index.php?file=../secreto.txt

ctf_cpmx_2

67d71184adf4b700d5cadce0c9bfdcc7e91d01cb <- esta es la bandera del reto 🙂

Reto #2

El segundo reto nos daba como pista “DNS record types” junto con un dominio gcs-ibero.com, si es la primera vez que escuchan de record types en el siguiente enlace podrán encontrar mas información https://en.wikipedia.org/wiki/List_of_DNS_record_types

Entendiendo un poco mas sobre el tema comenzamos a hacer lookup a los distintos records hasta que llegamos al record TXT http://mxtoolbox.com/TXTLookup.aspx y encontramos la solución.

ctf_cpmx_3

4db055f7386c6bb8a14b5883417a4b61 <- es la bandera de este reto

Reto #3

El reto numero 3 es bastante interesante, al inicio nos dan una captura de paquetes, un archivo .pcapng que procedemos a visualizar con wireshark (si no han escuchado de el o no saben utilizarlo ahora es el momento https://www.wireshark.org/)

ctf_cpmx_4

Como podemos observar hay partes de la lectura que están cifradas (ahí se ve una negociación TLS), por suerte entre los archivos que nos daban también venia una llave privada (llave.pem) que nos servirá para descifrar esas partes. En Wireshark nos vamos al menú Edit > Preferences y en la siguiente ventana del lado derecho seleccionamos Protocol > SSL

ctf_cpmx_5

Damos clic en RSA keys list y agregamos una nueva llave, nos pedirá algunos datos como dirección IP, puerto, protocolo y la llave privada (llave.pem), haciendo un análisis de lo que teníamos anteriormente:

En la captura tenemos dos direcciones IP:

  • 192.168.15.7 (dirección local)
  • 52.27.174.204 (dirección remota a la que nos estamos comunicando)

De igual forma, viendo la captura, sabemos que la comunicación con la maquina remota fue atreves de ftp utilizando el puerto 21 (por default) por lo tanto escribimos esos datos y adjuntamos la llave privada como se muestra en la siguiente imagen.

ctf_cpmx_6

ctf_cpmx_7

Damos ok a las ventanas y Wireshark nos debería de mostrar el trafico descifrado. Para analizar mas rápido vamos a pasar la captura a un archivo de texto, File > Print. Seleccionamos Plaint Text y Output to file.

ctf_cpmx_8

Abrimos el archivo generado con nuestro editor de texto favorito y empezamos a buscar por cadenas interesantes como password, pass, secret, etc

ctf_cpmx_9

La bandera de este reto es: ZXASDF727fa2raSFP!FRA-,aSF

Reto #4

El reto cuatro era facil y consistía en un reto criptográfico, al principio nos daban una cadena de texto que parecía no tener sentido y en mi experiencia la mayoría de los retos de este tipo son cifrados caesar. Con la ayuda de google buscamos un sitio para resolver este tipo de cifrados de sustitución por desplazamiento http://www.xarg.org/tools/caesar-cipher/

Introducimos el texto cifrado y obtenemos la respuesta 🙂

ctf_cpmx_10

Mas sabe el diablo por viejo que por diablo <- esta es la bandera del reto

Reto #5

Tip: la bandera es el md5 del contenido del archivo zip.

El reto nos da un archivo comprimido en formato zip, que tiene la particularidad que al descomprimirlo nos genera otro archivo zip, y después otro y otro mas, parecería nunca acabar, lo primero que hice fue abrir el archivo con un editor hexadecimal solo para corroborar lo que ya sabíamos.

ctf_cpmx_11

Del lado derecho podemos ver los nombres de los archivos que se van generado: 617.zip, 293.zip, 558.zip, 689.zip, etc. (son bastantes) así que lo mas fácil es realizar un script para descomprimir todo lo que haya que descomprimir recursivamente xd, yo utilice un comando en bash.

$ while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]; do find -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;; done

ctf_cpmx_11
Al final del ultimo Zip nos encontramos con un archivo de texto llamado flag.txt, calculamos su hash md5 y obtenemos la bandera 🙂

$ md5sum flag.txt
da44354d0de702b12934235a51094813 flag.txt

da44354d0de702b12934235a51094813 <- es la bandera del reto (el hash)

Reto #6

El reto 6 nos dio bastante dolor de cabeza a los participantes, a pesar de que su solución era bastante sencilla, en el reto nos daban una dirección IP y se nos pedía utilizar nmap https://nmap.org/ (para escaneo de puertos y servicios) y Hydra para realizar ataques de fuerza bruta, hubo bastante confusión puesto que a aparentemente el servidor solo tenia corriendo un servicio de ssh y fue lo que intente atacar.

El servidor ssh no soportaba autenticación mediante usuario y contraseña por lo que termine creando script en bash, python, etc y probando diferentes tipos de exploits sin éxito :(. Me di cuenta que el primer escaneo que realice no fue un barrido completo de puertos, así que volví a escanear nuevamente esta vez asegurándome de revisar todos los puertos.

$ nmap –sV –p- --version-all --max-retries 1–d IP
...
...
333/tcp open ftp vsftpd 2.0.8 or later
...
...
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
# Nmap done at Fri Jul 24 18:08:31 2015 -- 1 IP address (1 host up) scanned in 6.26 seconds

Y ahora si encontramos que en el puerto 333 había un servidor de ftp corriendo.
Empezamos a analizar el servicio, tratamos de conectarnos y vemos como responde.

Intentando conectarse con el usuario admin

$ ftp admin @ 52.26.250.230 333
Connected to 52.26.250.230.
220 Welcome to FTP service.
331 Please specify the password.
Password: 
530 Login incorrect.
ftp: Login failed
ftp> exit
221 Goodbye.

Intentando conectarse con el usuario root

$ ftp root @ 52.26.250.230 333
Connected to 52.26.250.230.
220 Welcome to FTP service.
530 Permission denied.
ftp: Login failed
ftp> exit
221 Goodbye.

El usuario admin parece ser valido (vean como las respuestas son diferentes), pero no tenemos la contraseña, utilizaremos hydra y un buen diccionario, al final y después de un par de horas obtuvimos la contraseña 🙂

$ hydra -t 1 -l admin -P default_pass_for_services_unhash.txt -vV -s 333 52.26.250.230 ftp

ctf_cpmx_12

La bandera de esto reto era x.x: 12345678 (máximum trolling)

Reto #7

Otro reto bastante sencillo, aquí nos dan una foto y se nos pide encontrar la marca del dispositivo con el que fue tomado la fotografía.

Utilizamos cualquier extractor de metadatos online http://regex.info/exif.cgi y obtenemos que la foto fue tomada con una dispositivo Huawei

ctf_cpmx_13

La bandera del reto es: Huawei

Reto #8

En el reto 8 nos dan un archivo .iv que podemos crackear utilizando aircrack-ng, para quien no sepa aircrack es un software incluido en la distribución de seguridad Kali que sirve para crackear redes inalámbricas http://www.aircrack-ng.org/

En nuestro kali utilizamos aircrack-ng para procesar el archivo .iv del reto:

$ aircrack-ng captura.iv

ctf_cpmx_14

Y obtenemos la contraseña de la red inalámbrica que también es la solución al reto
12345 <- es la bandera de este reto

Reto #9

El ultimo reto del capture the flag consistía en explotar una vulnerabilidad de inyección SQL y obtener la contraseña en texto plano del administrador del sitio. El reto, al inicio nos presenta un sitio web con un catalogo de películas, podemos consultar las películas de un director en especifico con una URL similar a la siguiente:

http://54.68.213.190/busqueda.php?idDirector=1

Esta claro que si queremos inyectar comandos SQL tendremos que empezar por el parámetro idDirector y para hacerlo de una forma mas rápida y automática utilizaremos la herramienta sqlmap http://sqlmap.org/ que viene instalada en nuestro Kali.

$ sqlmap --url=http://54.68.213.190/busqueda.php?idDirector=1 --level=1 --risk=3 --all

ctf_cpmx_15

La herramienta nos hace un dump de la tabla de usuarios y vemos que los passwords son almacenados no en texto plano sino cifrados (probablemente en md5), también observamos que la tabla contiene un campo de salt y un valor que muy seguramente fue utilizado para calcular el hash de la contraseña.

Pues manos a la obra (o mas bien dicho, al teclado), el reto nos pide encontrar la contraseña del usuario maria (que es el administrador del sitio), podemos hacer rápidamente un script para intentar crackear el hash.

<?php 
$salt = "WDUOPALD6N";
$hash = "fa38084963f74741ea1184963fa2cd91";

$handle = fopen("pass2.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
    	
    	$line = str_replace("\n", "", $line);

		if(md5($salt.$line) == $hash || md5($line.$salt) == $hash)
		{
			echo $line . " OK! \n";
			exit(); 
		} else {
			echo $line . ":" . md5($salt.$line) . " Nop\n";
		}   
    }

    fclose($handle);
} else {
    echo "file error \n";
} 

?>

Lo que hace nuestro script es, con la ayuda de un diccionario de 2 millones de contraseñas populares, intentar encontrar cual es el texto plano concatenado al valor salt del hash que obtenemos, para cada contraseña de nuestro diccionario calculamos

  • salt + contraseña = hash
  • Contraseña + salt = hash

Y revisamos si tenemos alguna coincidencia.

ctf_cpmx_16

Afortunadamente la contraseña en texto plano se encontraba en nuestro diccionario y la pudimos encontrar 🙂

La bandera del reto final era: passw0rd1 (era la contraseña numero 795975 en nuestro diccionario)

ctf_cpmx_17

Nos vemos el siguiente año.
Happy hacking 🙂

50% de descuento para Campus Party 2014!

cover2

Uno de los eventos más importantes de Tecnología y ambiente tecnológico del mundo se celebrará en nuestro país en Zapopan, hablamos de CPMX5 y hoy te mostraremos la oportunidad de como obtener tus entradas con el 50 de descuento.

  • Deben registrarse como campusero en www.campus-party.com.mx.
  • Si ya tienes usuario solo debes hacer login.
  • Una vez hecho login en el panel de usuario deben seleccionar la opción «Comprar entrada». (http://www.campus-party.com.mx/webapp/fichaUsuario/pago)
  • Elegir la opción «Comprar con descuento».
  • En el proceso deben usar el siguiente código de descuento: CD501ihw35hi (copia y pega).
  • Una vez elegido el tipo de entrada se procede al pago de la cantidad vía PayPal.

¡Y listo! solo faltaría esperar a que llegue el día de comienzo de #CPMX5 para disfrutar de una semana de contenidos para los fans de la tecnología y lo que esto implica.

Código de 50% de descuento para #cpartymx4!

Hola amigos en esta ocasión les traigo un código de 50% de descuento para todos los usuarios de las comunidades afiliadas a Campus Party! El código es:

cpmx4comunidadesmayo

¿Como activo el código?

Accede a tu cuenta de campusparty, si aun no estas registrado corre y registrate

Captura de pantalla 2013-05-09 a la(s) 13.08.36

Una vez dentro de tu cuenta, accede a comprar tu entrada

Captura de pantalla 2013-05-09 a la(s) 13.13.51

Te aparecerá un botón con la leyenda “Comprar con descuento” haz clic en el

Captura de pantalla 2013-05-09 a la(s) 13.16.06

Por ultimo introduce el código de 50% de descuento para asistir a campusparty México

cpmx4comunidadesmayo

Captura de pantalla 2013-05-09 a la(s) 13.18.15

De manera paralela, Campus Party ha habilitado un micrositio para regalar pases gratis en en la siguiente dirección

salu2

Lista de ganadores de entradas para Campus Party 2013

Muchas gracias a todos los que participaron el sorteo de 3 entradas gratis para asistir a Campus Party México 2013, las personas listadas a continuación ganaron una entrada con puesto en sala para el evento :), muchas felicidades.

  • Braicot Espinoza
  • Rocio Barragan
  • Jose Vazquez Quezada

Si no resultaste ganador no te desanimes, todavía puedes conseguir tu entrada con un 20% de descuento :)!

¿Como? Muy fácil, tan solo pídela utilizando nuestra sección de contacto y con mucho gusto te enviare un código promocional para que puedas adquirir tu entrada!.

Ya falta poco, nos vemos en Campus Party México 2013

salu2