En análisis forense es una pieza muy importante en el mundo de la ciberseguridad y, aunque ser perito informático es complejo, no deja de ser un desafío profesional muy interesante.
Tanto en las charlas que he realizado en todos estos años, como en entrevistas y contenido que publico en Internet, siempre destaco la importancia de la formación en el desarrollo profesional de cualquier persona, pero, no cualquier tipo de formación, debe ser de calidad y contar con rigor técnico.
¿Cómo sabes cuándo una formación merece la pena?
Cuando la persona que te va a enseñar domina perfectamente su campo porque trabaja en él. En otras palabras: Si el formador no puede demostrar que ha trabajado y tiene experiencia práctica en lo que enseña, desconfía.
Incluso, aunque diga que tiene experiencia de 2 o 3 años y tenga certificaciones como la OSCP, CEH, CISSP, OSWE, EJTP, RDDSR, YTGR, HHYT, ATPC y sea muy conocido, desconfía igualmente, porque no tiene experiencia suficiente y aún tendrá lagunas de conocimientos muy profundas.
Lorenzo Martínez será tu formador y me consta, porque ya he realizado cursos con él, que es un profesional que no solo domina perfectamente este campo, porque se dedica a ello, sino que, además, lo explica todo de una forma muy clara.
Y no solo lo digo yo, es la opinión de cientos de personas a las que Lorenzo ha formado desde hace varios años.
Así que, mi recomendación es que te apuntes a los cursos que empiezan en el mes de abril. Es una formación muy especializada que no encontrarás en otras academias, por lo que es de alto valor profesional.
Si quieres saber más, tienes toda la información sobre lo que aprenderás y las fechas concretas en este enlace
En la primera parte de esta serie has visto cómo configurar un sistema Windows Server 2022, o al menos, una configuración mínima para tener un dominio de Active Directory. En esta segunda parte, verás como vincular una estación de trabajo con Windows 11 al dominio creado anteriormente, además de ver cómo ejecutar el proyecto BadBlood para tener un dominio «mal configurado» con cientos de objetos, de tal manera que tendrás un entorno parecido a lo que hay en cualquier empresa de tamaño medio, al menos en lo que respecta al número de objetos gestionados por el directorio activo.
Configuración inicial y vinculación del sistema al Dominio.
En primer lugar, se debe tener instalado un sistema Windows 11, el cual puedes descargar desde aquí:
Se puede utilizar VirtualBox o VMWare para la creación de una máquina virtual con dicho sistema, en el primer caso es recomendable instalar el «VirtualBox Guest Additions» y en el segundo, VMWare tools.
Dicho esto, se describen los pasos que se deben realizar en la estación de trabajo con Windows 11 para que se pueda unir al dominio.
Asignar un nombre a la estación de trabajo recién instalada. Para ello, puedes ir a: Windows -> en el campo de búsqueda escribir «PC Name» y luego, seleccionar la opción «Renombrar ordenador». Tal como aparece en el vídeo de YouTube, se ha asignado el nombre «THW-WORKSTATION»
En la barra inferior, pinchar en conexiones de red -> Red & Internet -> Configuración de red avanzada -> pinchar en «Ethernet» -> Ver propiedades adicionales -> Asignación de servidor DNS -> Introducir la IP del DC.
Unirse al dominio: Escribir en la barra de búsqueda -> «Dominio» -> Seleccionar «Obtener acceso a trabajo o escuela»
Pinchar en «Connect» o «Conectarse». A continuación, seleccionar la opción «Unir este dispositivo a un dominio local de Active Directory«.
En el campo donde se debe introducir el dominio, escribir «thehackerway.local» o el nombre de dominio indicado cuando se ha configurado el controlador de dominio. Dado que ya se ha configurado el servidor DNS en la estación de trabajo en el paso anterior, debería resolver dicho nombre de dominio sin problema. Pinchar en «Siguente».
Ahora, el sistema solicita un usuario y contraseña para acceder al Active Directory. Debe ser un usuario de dominio, por lo tanto se recomienda crear primero un usuario en controlador de dominio.
Finalmente, el sistema pedirá vincular una cuenta de usuario de dominio con esta máquina y si dicho usuario de dominio será un administrador de la estación de trabajo, a lo que se puede responder que sí. Llegados a este punto, es conveniente seleccionar la opción «reiniciar ahora».
Para comprobar que la estación de trabajo se encuentra vinculada al dominio, basta con dirigirse al controlador de dominio en: Administrador de Servidor -> Herramientas -> Usuarios y Equipos de Active Directory y el nodo de «Computers» que cuelga del dominio principal, se podrá ver la estación de trabajo con el nombre asignado debidamente registrada.
Ejecución de BadBlood.
Se trata de un script en PowerShell que se encarga de crear objetos en un AD de forma aleatoria, muchos de ellos con características inseguras con el objetivo de ejecutar diferentes tipos de ataques. Está diseñado para crear usuarios, estaciones de trabajo, ACLs, grupos, OUs, entre otras cosas.
Cada vez que se ejecuta es capaz de producir objetos y configuraciones distintas, genera objetos de forma aleatoria. Hay que tener en cuenta que una vez se ejecuta la herramienta, no hay forma de revertir estos cambios, a menos que se cree otro script en powershell para limpar todo lo que ha hecho BadBlood y lo que había antes de ejecutar la herramienta también. Por lo tanto es aconsejable generar un snapshot o instantánea del servidor antes de ejecutar este script y para tener la capacidad de revertir los cambios que genera BadBlood.
Son necesarios permisos de administrador para poder ejecutarlo y el procedimiento para
ejecutar BadBlood se describe a continuación.
Es necesario subir o descargar el script de PowerShell al controlador de dominio. Dicho programa se encuentra en el repositorio Github del proyecto
Se debe abrir una terminal de PowerShell con permisos de Administrador y ejecutar el siguiente comando:Set-ExecutionPolicy unrestrictedA continuación, ubicarse en la ruta donde se encuentra el script y ejecutar «.\Invoke-BadBlood.ps1». Esto abrirá una nueva terminal y generará una serie de mensajes que advierten del uso de este programa en un entorno productivo (algo que bajo ningún concepto se debe hacer).
Finalmente escribir en la terminal «badblood» cuando se solicite y esperar a que finalice el proceso. Puede tardar varios minutos.
Con estos sencillos pasos, puedes empezar a probar herramientas de pentesting para entornos de Active Directory y comprobar su funcionamiento, ya tendrás un entorno debidamente configurado (o mejor dicho, mal configurado) para hacer tus pruebas.
En esta última entrega veremos cómo crear una bind shell con Python. En realidad es algo que no tiene mucha complejidad ya que se aplican los mismos principios y librerías que se han visto en las dos partes anteriores, solamente que en este caso el sentido de la conexión cambia y es ahora el la víctima quien levanta el servidor y espera una conexión entrante por parte del atacante.
Para crear una bind shell, será necesario utilizar el módulo «socket» y sobre una instancia de la clase «Socket», invocar a los métodos «bind», «listen» y «accept» en este orden.
Lo que se aprecia en la imagen anterior sería perfectamente válido para levantar un servidor TCP plano y aceptar una conexión, aunque evidentemente aún falta implementar más instrucciones.
El siguiente paso consistiría en gestionar la conexión, concretamente los flujos de entrada, salida y error. Dado que lo que se pretende es «recibir bytes» por parte del socket cliente y a continuación, pasar esas cadenas al sistema operativo para que las ejecute en forma de comandos, el flujo de entrada es precisamente lo que interesa gestionar en primer lugar.
En este caso se utiliza la función «select» que representa un envoltorio de la system call «select» en sistemas Unix y se utiliza el file descriptor del socket cliente para recibir los datos que envía el atacante desde su máquina. Finalmente, tal como se ha visto en los dos artículos anteriores, se utiliza la clase Popen con el objetivo de crear un proceso y ejecutar el comando que se está enviando en el socket. En este caso, el programa es capaz de aceptar múltiples clientes y por lo tanto, las referencias de cada uno de ellos se van almacenando en una lista en la que se van añadiendo o eliminando las conexiones entrantes.
En la consola superior se observa la ejecución del script que permite establecer la bindshell y en la consola inferior, desde la máquina del atacante se establece la conexión que permite la ejecución de instrucciones.
Ahora bien, en este caso nuevamente el tráfico no se encuentra cifrado, por lo tanto sería posible capturar dichos paquetes en la red y ver su contenido. La solución a este problema podría ser utilizar Paramiko tal como se ha mencionado en el post anterior a este para establecer conexiones cifradas con SSH, algo que puedes hacer cambiando un poco las instrucciones de los scripts que se han enseñado en la parte dos de esta serie.
Al hablar de DevSecOps (o SecDevOps) inevitablemente se deben mencionar herramientas que ayuden a mejorar los procesos de seguridad en cada una de las etapas del SDLC. En este sentido, ya se han publicado un par de posts sobre algunas herramientas interesantes, tales como SonarQube, Insider o Security Code Scan las cuales están pensadas para el análisis estático de aplicaciones, sin embargo una vez superada las etapas de codificación y pruebas, la seguridad en las etapas de entrega y despliegue también es de vital importancia. En estos puntos ya no se analiza el código fuente estático, ahora se comprueba la integridad y seguridad del paquete que se pretende desplegar. Dependiendo de la aplicación, dicho paquete puede ser una imagen Docker, un fichero WAR para aplicaciones basadas en Java o simplemente un fichero ZIP. En cualquier caso, dicho «artifact» tiene todo lo necesario para que la aplicación funcione en un servidor y en este punto, es fundamental analizar las librerías y dependencias de dicho componente para detectar vulnerabilidades antes de que se produzca el despliegue. No solamente interesa analizar los módulos y librerías desarrollados por terceros, también es importante analizar los ficheros IaC (Infraestructure as Code) como por ejemplo XML, YML, Dockerfile, Jenkinsfile, Kubernetes entre muchos otros. En ocasiones, este análisis está fuera del alcance de algunas herramientas SAST o no es lo suficientemente completo. En este caso es necesario utilizar otras herramientas que se puedan incorporar fácilmente en los pipelines de CI y que sean lo suficiente potentes como para dar una buena cobertura a los componentes disponibles. Para esto tenemos a Trivy
¿Qué es Trivy?
Se trata de otra estupenda herramienta de AquaSecurity y que se define como un escaner de vulnerabilidades y malas configuraciones en imágenes de contenedores, ficheros de configuración y repositorios Git. Es una herramienta desarrollada en GO, la cual se puede compilar directamente en un sistema basado en Unix o descargar el binario que se encuentra disponible en la sección de «releases» del repositorio oficial.
No requiere ningún tipo de instalación y solamente hace falta descargar el binario y ejecutarlo con los parámetros que admite.
Para escanear una imagen, basta con el ejecutar el comando con la opción «image». Si es la primera vez que se ejecuta o si lleva tiempo sin actualizarse, procede a descargar la base de datos de vulnerabilidades con la que realiza las comprobaciones.
La herramienta es capaz de detectar las librerías vulnerables y enseñar el CVE, la severidad, la versión utilizada que presenta la vulnerabilidad y si la hay, la versión que corrige el defecto.
Otros parámetros interesantes consisten precisamente en analizar proyectos que se encuentran en un directorio concreto.
Al ser una aplicación que se ejecuta desde línea de comandos, puede ser fácil de integrar en un pipeline de Jenkins o cualquier otra herramienta similar a la hora de llevar a cabo procesos de integración continua. La información que aporta es vital para poder detectar problemas en los componentes de la aplicación antes de ser desplegada en el servidor. Sin duda, una herramienta útil que hay que tener en cuenta.
Continuando con lo que se ha explicado en el primer post de Buenas prácticas en Docker – Parte 1 de 2 se listarán ahora algunas buenas prácticas adicionales que representan los conocimientos mínimos que se deben de tener para utilizar esta tecnología de forma efectiva.
Evitar la ejecución de contenedores con root.
La mejor forma de evitar ataques de elevación de privilegios desde el interior de un contenedor es configurar las aplicaciones que se ejecuten en él con privilegios de usuarios regulares (sin privilegios administrativos de ningún tipo). El cliente de docker cuenta con la opción “-u” o “–user”para especificar un nombre de usuario o ID, esto es importante tenerlo en cuenta ya que por defecto todos los contenedores se ejecutan con privilegios de root y aunque el contenedor está debidamente aislado, un atacante tendrá pleno control sobre dicho contenedor en el caso de que consiga comprometerlo.
Utilizar la instrucción USER en los ficheros DockerFile.
En el diseño de imágenes la instrucción USERen el fichero DockerFile permite especificar un usuario distinto a “root” en un momento concreto de la ejecución. De ésta forma, es posible ejecutar instrucciones como “root” en el DockerFile cuando sea necesario y posteriormente cambiar de usuario a uno sin privilegios con dicha instrucción. Por ejemplo:
En el caso anterior, es necesario contar con privilegios de root para instalar paquetes y otras cuestiones de configuración, pero una vez dicha operación termina, se cambia el contexto de usuario para ejecutar los contenedores que se creen partiendo de la imagen anterior con un usuario concreto (definido por su identificador).
Especificar únicamente las capabilities necesarias y evitar la flag “privileged”.
Por defecto, todos los contenedores en Docker son “no privilegiados”. Esto quiere decir que por ejemplo, dentro de un contenedor no es posible ejecutar otro servicio Dockerd o manipular características importantes del sistema host. Sin embargo, un contenedor privilegiado, es aquel que tiene acceso a todos los dispositivos y puede manipular características importantes del sistema anfitrión como la configuración de SELinux o AppArmor, lo que le permitirá al contenedor tener prácticamente el mismo nivel de acceso sobre el sistema host.
Para crear un contenedor privilegiado se utiliza la flag “–privileged” y por defecto permite el acceso a todos los dispositivos del host anfitrión. Para limitar dicho nivel de acceso se puede combinar con la flag “–device”
docker run –privileged –device=/dev/snd:/dev/snd docker run –device=/dev/sda:/dev/xvdc –rm -it ubuntu fdisk /dev/xvdc docker run –device=/dev/sda:/dev/xvdc:r –rm -it ubuntu fdisk /dev/xvdc docker run –device=/dev/sda:/dev/xvdc:w –rm -it ubuntu fdisk /dev/xvdc
Además de la opción “–privileged”, en Docker también existe la posibilidad de controlar las “capabilities” de Linux por medio de las opciones “–cap-add” y “–cap-drop”, lo cual permite tener un control muy fino sobre lo que se puede y no se puede hacer dentro del contenedor. La mejor política de seguridad consiste precisamente en eliminar todas las capabilities y añadir solamente aquellas que sean necesarias:
docker run –cap-drop=ALL –cap-add=NET_ADMIN –cap-add=CAP_NET_BIND_SERVICE
Limitar el acceso a recursos desde el contenedor (memoria y CPUs).
Por defecto, no hay restricciones de forma implícita en los recursos que puede consumir un contenedor y aunque gracias a cgroups es posible evitar condiciones de denegación de servicio, es altamente recomendable utilizar las opciones disponibles en Docker para poner limites de forma explicita a los contenedores creados. Las principales opciones se listan a continuación:
Gestión de la memoria.
-m or –memory=
Memoria máxima que el contenedor podrá usar. El valor mínimo para esta opción es 4m (4 megabytes).
–memory-swap*
La cantidad de memoria que el contenedor puede “swapear” al disco.
–memory-reservation
Permite especificar un límite blando (soft limit) más pequeño que el valor indicado con la opción «-m». Este límite se activa cuando Docker detecta contención o poca memoria en el sistema host.
–kernel-memory
Indica la cantidad máxima de memoria del kernel que podrá usar el contenedor. El valor minimo permitido es de 4M.
Gestión de la CPU.
–cpus=<value>
Especifica la cantidad de recursos disponibles en la CPU puede usar el contenedor. Por ejemplo, si el host tiene 2 CPUs y se establece la opción con –cpus=»1.5″, el contenedor tendrá garantizado el uso de al menos uno y medio de CPUs.
–cpuset-cpus
Especifica los cores concretos que el contenedor puede usar. Cada CPU está numerada desde 0. Es posible indicar que el contenedor puede usar los cores de 0 a 4 con el valor “0-3” o que el contenedor puede usar los cores 2 y 4 especificando los valores “1,3”.
En este post has podido ver algunas de las buenas prácticas a la hora de crear y gestionar contenedores en Docker, sin embargo pueden haber muchas más. Puedes dejar un comentario en este post con las que sueles utilizar para que todos aprendamos un poco más.
Desde hace algunos años, Docker se ha convertido en una tecnología de uso habitual para cualquier profesional IT. Programadores, administradores de sistemas y profesionales de la seguridad suelen utilizarlo con frecuencia. Sus beneficios son innegables y ha ayudado a definir las bases de que hoy en día conocemos como la «arquitectura basada en microservicios«. Si bien se «parece» a las tan extendidas y conocidas máquinas virtuales, existen diferencias notables, especialmente relacionadas con el rendimiento y el uso que se le suele dar a un contenedor. De hecho, la siguiente imagen ilustra bastante bien las diferencias entre una máquina virtual clásica y un contenedor en Docker.
Las máquinas virtuales dependen de un Hypervisor y sobre éste, se van montando diferentes sistemas operativos con todo lo que esto implica (librerías, aplicaciones, etc). En el caso de Docker, cada contenedor es gestionado por el servicio de Docker y éste se aprovecha de las características del sistema operativo subyacente.
Esta breve introducción probablemente ya te la conoces y no es el objetivo de este post explicar cómo utilizar las funcionalidades básicas de Docker sino comentar algunas de las mejores prácticas o «tips» para utilizar esta tecnología. No obstante, si estás interesado en aprender las bases y todo lo necesario para dominar Docker y Docker-Compose, te recomiendo que le eches un vistazo al curso en Udemy: Docker y DevOps de Novato a Experto.
Usar ficheros .dockerignore.
Cuando se ejecuta el comando “docker build” todos los ficheros del PATH o URL indicada, se envían al servidor de Docker (Docker Engine). Es recomendable usar un directorio vacío, incluir en él solamente aquello que se vaya a necesitar y posteriormente construir la imagen con docker build. Es común encontrarse que el contenido de dicho directorio crezca en la medida que se van desarrollando o implementando nuevas características, en tal caso para mejorar el rendimiento y no enviar al Docker Engineficheros innecesarios se puede utilizar un fichero especial llamado .dockerignore. En este fichero se puede incluir por cada línea, un directorio o fichero que se excluirá de la imagen. Por ejemplo, se podrían excluir ficheros con una extensión concreta o nombre, algo parecido a lo que se hace con otras tecnologías como GIT.
No instalar paquetes innecesarios.
Para reducir la complejidad, dependencias, tiempo de creación y tamaño de la imagen, se debe evitar instalar paquetes y servicios innecesarios. Lo recomendable es comenzar con una imagen mínima, como por ejemplo “scratch” o «alpine» e instalar los paquetes que hagan falta partiendo de ella.
Minimizar el número de capas.
Tal como se ha indicado anteriormente, cada comando en el Dockerfile se encarga de generar una capa, la cual se puede borrar o cachear dependiendo de su uso en el proceso de construcción de la imagen. Es recomendable utilizar el menor número de comandos posible para reducir el número de capas intermedias y por ende, el procesamiento que debe realizar el Docker Engine a la hora de generar la imagen final.
En la medida de lo posible y para facilitar futuros cambios, hay que organizar los argumentos de las instrucciones que contengan múltiples líneas en una sola, esto evitará que durante el proceso de construcción de la imagen se deban construir múltiples capas intermedias y por supuesto, hará que el archivo sea más fácil de leer.
Por ejemplo, es mejor hacer esto:
RUN apt-get update
RUN apt-get install -y git
RUN apt-get install -y wget RUN apt-get install -y apache2 RUN apt-get install -y php5
Limitar los privilegios.
Cuando se inicia un contenedor, Docker se encarga de crear un grupo de namespaces, los cuales simplemente «acordonan” el contenedor para que no interfiera con procesos del sistema host u otros contenedores. Se trata del mecanismo estándar que incluye Docker para evitar que un contenedor mal configurado o con brechas de seguridad pueda ser utilizado para atacar el sistema host. Aunque los namespaces suponen un mecanismo de seguridad potente en Docker, cuando se habla de seguridad siempre hay que intentar aplicar el principio del “último privilegio”, el cual indica que la arquitectura de un sistema debe tener únicamente las características necesarias para su correcto funcionamiento y que dichas funciones deben de estar debidamente limitadas. Quiere decir que los contenedores y todos los elementos que incluyen deben tener un conjunto muy limitado de funciones, servicios, librerías y herramientas: Únicamente aquello que sea estrictamente necesario para su funcionamiento. Dicho esto, es recomendable ajustar los privilegios del contenedor, en primer lugar evitando que se ejecute como root y en segundo lugar ajustando las “capabilities” con opciones como “–cap-drop” y “–cap-add”.
Esto es todo de momento, en el siguiente post se verán algunas otras recomendaciones de seguridad a la hora de trabajar con Docker.
Los ficheros de log representan una buena forma de entender el funcionamiento del sistema y su comportamiento. Ya sea para labores de post-explotación, para analizar un incidente, para ver qué está pasando con alguna aplicación o simplemente para comprobar que todo funciona como se espera. Todos los sistemas operativos y servidores de uso habitual en internet cuentan con mecanismos de logging que permiten generar trazas en ficheros permanentes, temporales, en el syslog o en el stdout del proceso. Hay muchas maneras de generar eventos en forma de log. En este post se verán 15 ficheros de log interesantes en sistemas Linux. Se trata de un artículo de nivel básico que servirá como complemento a los conocimientos fundamentales de este sistema operativo.
/var/log/messages
Dependiendo de la distribución de Linux utilizada, es posible que este fichero no se encuentre disponible en el sistema pero si lo está, en él se podrán apreciar los mensajes globales del sistema incluyendo trazas que generan algunos servicios durante el arranque, trazas que dejan los programas que se ejecutan por parte del demonio CROND, logs sobre procesos de autenticación llevados a cabo por los usuarios, etc.
/var/log/syslog
Como se mencionaba antes, el fichero «messages» ya no se encuentra disponible en algunas distribuciones recientes de Linux como es el caso de Debian y Ubuntu, sin embargo esta misma información se puede encontrar en el syslog. El estándar syslog es uno de los más conocidos en sistemas Linux y se caracteriza por centralizar todas las trazas que se producen en el sistema, incluyendo aquellas que registra el kernel. Hay que tener en cuenta que el protocolo syslog por defecto almacena los mensajes del sistema en este fichero, pero es posible administrar los logs de varias formas. Por ejemplo, se pueden enviar a un servidor syslog externo o directamente a un SIEM, se pueden enviar a un búfer en memoria o incluso, guardar los mensajes en diferentes ficheros en función de su criticidad ya que cada log generado tiene un tipo que permite saber que tan «grave» es el mensaje.
/var/log/dmesg
Cuando un sistema Linux arranca, enseña información muy variada sobre los dispositivos detectados en el sistema y los módulos del kernel que se encargan de gestionarlos. Dichos logs se generan en el fichero /var/log/dmesg pero dependiendo de la distribución es posible que este fichero no exista, en todo caso el comando «dmesg» permite acceder a estas trazas, las cuales son especialmente útiles para depurar y ver si los dispositivos que están conectados al ordenador se detectan correctamente.
/var/log/auth.log
Se trata de un fichero que almacena los eventos relacionados con mecanismos de autorización, por ejemplo cuando un usuario inicia sesión en el sistema. Suele incluir detalles sobre el mecanismo utilizado y el resultado (si la autenticación ha sido correcta o no).
/var/log/daemon.log
Incluye logs de algunos de los servicios que se ejecutan en segundo plano.
/var/log/lastlog
Contiene información sobre los usuarios que han iniciado sesión recientemente en el sistema. No obstante, no es un fichero que se pueda leer en formato ASCII, para acceder a sus contenidos se utiliza la herramienta «lastlog».
/var/log/kern.log
Este fichero almacena los logs producidos por el kernel. Si por el motivo que sea es necesario compilar el kernel para añadir características o modificar algún parámetro será util para depurar.
/var/log/dpkg.log
En sistemas basados en Debian, cuando se instala/desinstala software utilizando la herramienta DPKG, los logs generados se almacenan en este fichero lo cual puede ser útil para saber qué programas se han ido instalando con esta utilidad.
/var/log/btmp
Este fichero incluye trazas sobre los intentos de autenticación fallidos en el sistema. Del mismo modo que ocurre con el fichero «lastlog», no se puede leer como un fichero de texto plano ASCII, es necesario ejecutar la utilidad «last» la cual permitirá acceder a sus contenidos.
/var/log/user.log
Incluye información sobre los eventos producidos en las sesiones de los usuarios, dichos eventos incluyen conexiones o interfaces de red que se encuentran activas o errores que se van produciendo en el Desktop Manager que esté usando el usuario.
/var/log/wtmp
Contiene información sobre qué usuarios se encuentran autenticados y usando el sistema actualmente. Este fichero es el que utilizan las herramientas «who» y «w» para enseñar sus resultados.
/var/log/boot.log
Incluye exactamente las mismas trazas que enseña el sistema durante el proceso de arranque.
/var/log/alternatives.log
Los registros que genera el comando «update-alternatives» se quedan almacenados en este fichero y puede ser útil para efectos de depuración o ver qué cambios se han hecho sobre el software instalado.
/var/log/cron
Se trata de un fichero de logs en donde se guardan las trazas producidas por las tareas programadas ejecutadas por el demonio CROND.
Directorios interesantes que pueden almacenar logs.
Los ficheros listados anteriormente son comunes en sistemas Linux, sin embargo es bastante frecuente encontrar servicios que generan sus propios ficheros de log en ubicaciones muy concretas y por supuesto, es recomendable revisar sus contenidos tanto para la administración del sistema como para detectar una posible intrusión. La ubicación exacta de cada directorio puede variar dependiendo de la distribución de Linux y de la forma en la que se haya instalado el programa, por ejemplo no es lo mismo instalar Apache HTTPD desde código fuente que con APT/YUM. En el primer caso los ficheros y directorios de configuración tendrán rutas más o menos estandar, pero si se ha instalado manualmente desde código fuente es posible indicar estos valores en el proceso de instalación. Dicho esto, algunos directorios que se deberían consultar ya que son habituales a la hora de almacenar logs son los siguientes:
/var/log/httpd/ o /var/log/apache2
/var/log/lighttpd/
/var/log/mail/
/var/log/samba/
/var/log/mysqld.log
/etc/rsyslog.d/ y /etc/rsyslog.conf
/var/log/audit/
Los ficheros log que se han enseñado aquí son probablemente los más interesantes desde el punto de vista de la seguridad en un sistema Linux, sin embargo no son los únicos. Hay bastantes secciones del sistema que incluyen trazas útiles y dependerá en gran medida del software instalado. ¿Qué ficheros de log echas en falta en este post? Escribe un comentario.
Para que podáis seguir el blog de una forma más cómoda, he decidido crear este post que marcaré como fijo y en el que podréis ver qué se irá publicando próximamente. Se actualizará con frecuencia en la medida en la que vaya escribiendo más artículos así que lo puedes usar como bitácora o referencia de futuras publicaciones. También puedes postear un comentario sobre ideas para mejorar, posts sobre algún tema que te gustaría ver publicado aquí o si estás interesado en escribir algún artículo en este espacio. Como siempre, las aportaciones son bien recibidas. Si quieres contactar conmigo para otro asunto, lo puedes hacer escribiendo a mi correo adastra@thehackerway.com
En este post se explica en qué consisten las vulnerabilidades de asignación masiva (Mass Assignment) en APIs Rest y se enseña un ejemplo.
05/05/2022
DevSecOps y detección de vulnerabilidades con Trivy.
Uso de la herramienta Trivy para la detección de vulnerabilidades en la etapa de deploy y release en el proceso de DevSecOps.
10/05/2022
Vulnerabilidad critica RCE en Spring Framework.
Explicación y pruebas sobre la última vulnerabilidad que se ha producido en Spring Framework y el motivo por el que las aplicaciones basadas en Java con este framework deben actualizar cuanto antes.
12/05/2022
PyScript: Ejecuta scripts en Python en tu navegador web – Parte 1 de 2
Primera parte en la que se explica el proyecto pyscript, el cual permite la ejecución de scripts en Python directamente en páginas HTML.
17/05/2022
PyScript: Ejecuta scripts en Python en tu navegador web – Parte 2 de 2
Segunda parte en la que se explora el proyecto y se descubren sus limitaciones, especialmente desde la perspectiva de un pentester o atacante.
En la entrada anterior se ha hablado sobre el proceso de instalación de Pupy y la generación de payloads, los cuales evidentemente se tendrán que ejecutar en las máquinas comprometidas. A partir de éste punto es posible ejecutar operaciones de post-explotación utilizando el Command and Control de Pupy una vez se reciba la conexión por parte de la víctima.
Post-explotación en sistemas Linux con Pupy
Una vez se ejecuta el payload en una máquina comprometida basada en Linux, es posible ver la sesión generada en el C&C de Pupy y ver las opciones disponibles con el comando “help”.
Con “help” únicamente aparecerán los comandos básicos, pero si se utiliza la opción “help -M” se podrá ver un listado completo de todas las alternativas disponibles de cara a realizar procedimientos de post-explotación en profundidad.
Por otro lado, los comandos ejecutados desde la consola de Pupy afectan a todas las sesiones que se encuentren abiertas, es decir, que se ejecutarán sobre todos los zombies. Para cambiar este comportamiento y especificar que los comandos deben ejecutarse sobre un único zombie o un subconjunto de ellos es necesario utilizar el comando “sessions” con la opción “-i” en donde es posible especificar un listado de identificadores de sesiones separados por coma. Si se indica un único identificador los módulos/comandos se ejecutarán contra ese zombie. Si se especifica una lista de identificadores separados por comas los comandos se ejecutarán contra todos y cada uno de los zombies relacionados con dichos identificadores.
A partir de éste momento es posible comenzar con la ejecución de algunos de los módulos disponibles en Pupy. A continuación se listan unos cuantos. • shell: Es un comando que funciona en todos los payloads independiente de si es Linux/Windows o Android. En ocasiones resulta conveniente tener una shell directa contra el sistema y ejecutar comandos de todo tipo. En éste caso es una shell interactiva, lo que significa que el canal de comunicación no se va a cortar en el caso de utilizar comandos como “sudo”, “passwd” o cualquier otro que requiera interacción. • mount: Permite listar todas las particiones en el sistema comprometido y los dispositivos que se encuentran montados. • migrate: Aquellos que habéis trabajado con Metasploit y Meterpreter seguramente ya sabréis de qué va éste comando. En el caso de Pupy, no solamente se encarga de migrar el payload a otro proceso más estable en el sistema sino que además permite crear un proceso nuevo en el caso de que haga falta. Todo esto sin escribir nada en disco para evitar la detección. • privesc_checker: Un módulo interesante que en sistemas basados en Linux permite encontrar defectos de configuración que puedan conducir a elevación de privilegios. Utiliza una herramienta muy conocida en este tipo de procesos llamada “LinEnum”.
• persistence. En todos los payloads disponibles en Pupy se encuentra habilitada la persistencia por defecto. En el caso de Linux utiliza un fichero de configuración para “systemd” que se cargará justo cuando arranque el sistema, de tal forma que se garantizan los accesos futuros. Cuando se ejecuta el módulo sin ningún parámetro simplemente se encarga de habilitar o deshabilitar la persistencia en el sistema comprometido. Cuenta con más opciones de configuración para sistemas Windows que para Linux. En el caso de que el payload sea para Linux solamente se puede utilizar el argumento “-s” para indicar que el mecanismo de persistencia utilizado deberá ser una librería compartida en lugar de un fichero de configuración Systemd. Finalmente, la opción “–remove” permite eliminar cualquier fichero relacionado con el mecanismo de persistencia, realizando una limpieza básica en el sistema comprometido.
• duplicate: Simplemente duplica el payload actual y genera un nuevo proceso con él. Con la opción “-m” intentará impersonalizar el token de usuario actual. Aunque se puede utilizar en sistemas Linux ya que el comando no dará ningún error, en realidad solo tiene sentido (y efecto) en sistemas Windows. Una vez se ejecuta el módulo es normal obtener una nueva sesión.
• exploit_suggester: Se trata de un módulo que basándose en información básica del objetivo, intenta determinar cuáles son los exploits públicos que podrían funcionar a la hora de elevar privilegios.
• tcpdump: Este módulo representa un subconjunto de las funcionalidades disponibles en la herramienta tcpdump. Entre otras cosas, permite la captura pasiva de tráfico utilizando filtros BPF y guardar los resultados en un fichero PCAP. • users: Permite obtener el listado de usuarios interactivos en el sistema. • port_scan: Se trata de un escáner de puertos muy básico basado en TCP. Puede ser útil en el caso de que no sea posible subir/instalar nmap u otra utilidad más potente al sistema comprometido.
• search: Ideal para realizar búsquedas de forma recursiva sobre un directorio. Admite expresiones básicas para buscar ficheros/directorios que coincidan con la cadena especificada. • download: Descarga uno o varios ficheros del sistema comprometido. También admite expresiones básicas, ficheros que se pueden incluir o excluir del proceso de descarga y también, realizar solamente el cálculo del tamaño de la descarga lo cual es muy útil para hacerse una idea de cuántos se descargaría en el caso de continuar.
• upload: Se trata de un módulo muy simple que se encarga de subir un fichero o directorio a una ruta concreta en la máquina comprometida.
Existen bastantes más módulos para sistemas Linux que merece la pena explotar. Como se ha mencionado antes, basta con ejecutar el comando “help -M” para ver los comandos y módulos disponibles. En el caso de Pupy enseña cada módulo en verde o gris lo que permite saber si dicho módulo se puede ejecutar sobre el sistema comprometido o no.
En el próximo post se hablará sobre el payload de Pupy para Windows y algunos módulos más que son específicos para estas plataformas.
Sobre los autores: Ernesto Sanchez (@ernesto_xload) y Joel Serna (@JoelSernaMoreno) son consultores en seguridad informática que han participado en eventos como: Navaja Negra, RootedCON, CCN-CERT, Mundo Hacker Day, etc.
Sabemos que hemos estado bastante tiempo sin aparecer por aquí, pero hemos estado liados con un proyecto de una duración de unos dos años, y sí, estamos aquí para contarlo.
Lo primero de todo, agradecer a todas las personas que han apoyado y ayudado en esto, sobre todo a las mencionadas aquí abajo:
Todo empezó a finales de 2017, donde Ernesto Sánchez y un servidor decidimos empezar un “proyecto” para demostrar que los dispositivos USB no son lo que realmente parecen.
La idea de troyanizar hardware, como bien se explica en una entrevista que nos hizo Guillermo Cid para el Confidencial (aquí), viene de que las personas confían en el hardware y nunca llegan a pensar que este puede haber sido alterado con fines maliciosos.
En los últimos años hemos podido observar que las personas tienen mas cuidado a la hora de conectar pendrives en sus equipos porque pueden contener malware, pero… ¿qué pasa con todo lo demás?
Todos los periféricos USB que utilizamos en nuestro día a día se pueden troyanizar. Así es como nació Evil Crow cable.
Evil Crow cable, como su propio nombre indica, es un cable de móvil con el famoso microcontrolador Attiny85 en su interior, junto a 3 resistencias y 2 diodos zener.
¿Qué se puede hacer con él? La finalidad del cable es simple, un dispositivo BadUSB como puede ser el USB Rubber Ducky. En este artículo no vamos a entrar otra vez en el tema de los dispositivos BadUSB, quien no sepa lo que es o esté interesado… aquí tiene los enlaces de los artículos anteriores que escribimos para este mismo blog: BadUSB Ultra Low Cost y Vuelve el patito Low Cost, ahora grazna como un USB Rubber Ducky original.
¿Aún no queda claro que es Evil Crow cable? No pasa nada, tenemos un repositorio específico donde está documentada toda su historia, desde el comienzo del desarrollo en una breadboard (utilizando un Attiny45 en las primeras pruebas, que al final no fue suficiente para nosotros y utilizamos Attiny85), hasta el cable completo que ha ido a producción gracias a la ayuda de Luca Bongiorni y a nuestro distribuidor April Brother:
La historia está muy bien y todo eso… pero, ¿donde puedo comprar el cable? Puedes comprarlo por unos 10$, tanto en la tienda del distribuidor en Tindie, como en Aliexpress… aquí dejamos el enlace de compra directo en Aliexpress: Evil Crow cable
Cabe destacar que Evil Crow cable es un proyecto sin ánimo de lucro, ¿que queremos decir con esto? Basicamente, todos estáis invitados a pagarnos unas cervezas si nos veis en alguna CON 😀
Ahora vamos a meternos en el asunto…
Configuración e instalación del software
Una vez hemos obtenido el dispositivo, tenemos que tener en cuenta que, primero tenemos que instalar el IDE de Arduino y también los drivers en el caso de Windows (aquí)
NOTA: no es aconsejable instalar el IDE de Arduino desde repositorios de nuestra distribución de Linux, suele ser una versión algo obsoleta y puede darnos problemas. Destacar que el funcionamiento del dispositivo es ligeramente distinto a cualquier otro Arduino con el que hayamos trabajado anteriormente y necesita ser desconectado y conectado para ser reprogramado (Hay disponible un dispositivo para hacer ésto por hardware mediante un interruptor disponible aquí, pero no creemos que sea tanta molestia conectar y desconectar el dispositivo cada vez). Lo primero es tener la última versión del arduino IDE (Aquí) y asegurarnos que está todo actualizado.
El segundo paso es bajar el paquete de compatibilidad con ésta placa y el IDE de Arduino para poder trabajar correctamente con ella, para ello tenemos que ir a Archivo -> Preferencias -> Gestor de URLs Adicionales de Tarjetas y añadiremos en una nueva linea lo siguiente (si tenemos alguna no es incompatible):
Simplemente aceptamos y vamos a Herramientas -> Placa -> Gestor de Tarjetas, aquí buscamos Digistump AVR Boards y procedemos a su instalación.
En caso de usar linux, es posible que tengas que tener la versión actual y legacy de libusb, así como añadir unas reglas nuevas de udev, hay un tutorial de Digistump aquí. Comentar que las librerías originales de Digistump solo poseen soporte para emular teclados con el layout en_US (Inglés de EEUU), con lo que es muy aconsejable descargar e instalar la librería con soporte para otros idiomas, disponible aquí.
Payloads y primer Hola Mundo
Evil Crow cable lleva un microcontrolador Attiny85 en su interior, entonces… podemos utilizar cualquier payload compatible con la famosa placa de 2$ Digispark. En el siguiente enlace podéis descargar más de 20 payloads compatibles y probados:
Una vez hemos descargado los payloads… tenemos que abrir el IDE de Arduino que hemos descargado y configurado anteriormente, también nos tenemos que asegurar que hemos configurado la placa correcta, para ello vamos a Herramientas -> Placa y seleccionamos “Digisparck (Default – 16.5 mhz)” y ningún puerto.
Lo siguiente es compilar y subir el código, primero podemos pulsar el botón de Verificar para asegurarnos de que no existe ningún error y después pulsar el botón Subir, sin conectar el dispositivo aún. A los pocos segundos, el IDE nos pedirá que conectemos el dispositivo y lo reprogramará como podemos ver en la siguiente captura. Ya está nuestro “hola mundo”, a los pocos segundos ejecutará el código, dicho código está guardado en la flash del Attiny85 con lo que se ejecutará cada vez que conectemos el dispositivo a un ordenador.
En el siguiente enlace podéis ver el vídeo del proceso de subir el payload a Evil Crow cable:
2. Acceder al directorio micronucleus/commandline con el siguiente comando: cd micronucleus/commandline
3. Compilar Micronucleus con el siguiente comando: make
4. Acceder al directorio .arduino15/packages/digistump/tools/micronucleus/2.0a4 con el siguiente comando: cd ~/.arduino15/packages/digistump/tools/micronucleus/2.0a4/
5. Crear un backup de Micronucleus con el siguiente comando: mv micronucleus micronucleus.old
6. Copiar la última versión de Micronucleus al directorio actual con el siguiente comando: cp ~/PATH/micronucleus/commandline/micronucleus .
Cambiar PATH por el directorio donde hemos descargado Micronucleus
7. Verificar y Subir el código otra vez
Máquina virtual para dummies
La instalación del software puede ser algo tediosa para algunas personas, por eso mismo hemos creado una máquina virtual con toda la configuración y software visto anteriormente.
Para descargar la máquina virtual tenéis que acceder al siguiente enlace (contraseña de la máquina virtual: evilcrowcable):
– En VMWare, hacemos click en la pestaña Settings.
– Hacemos click en el botón +Add…
– Seleccionamos Serial Port y hacemos click en finalizar
4. Añadir el controlador USB con los siguientes pasos:
– En VMWare, hacemos click en la pestaña Settings.
– Hacemos click en el botón +Add…
– Seleccionamos USB controllery hacemos click en finalizar
5. Iniciar la máquina virtual
6. Abrir un terminal (CTRL+ALT+T) y acceder al directorio del IDE de Arduino con el siguiente comando: cd arduino-1.8.10-linux64/arduino-1.8.10/
7. Ejecutar el IDE de Arduino con el siguiente comando: ./arduino
8. Abrir un payload en el IDE de Arduino. Nota: Los payloads están descargados en el home del usuario de la máquina virtual
9. Verificar y subir los payloads a Evil Crow cable.
Línea de datos
Cuando empezamos el proyecto a finales de 2017 y presentamos la charla “Troyanizando Hardware: ten cuidado con qué (USB) metes y donde” en la primera edición de la h-c0n, el cable BadUSB que teníamos en ese momento sólo permitía alimentación a través del puerto MicroUSB.
En el cable final de producción, hemos conseguido habilitar la línea de datos en modo “PoC”, utilizando el esquema básico que hay publicado en Internet.
¿Qué queremos decir con esto? Actualmente no tenemos control sobre la línea de datos de Evil Crow cable. Para conseguir control sobre la línea de datos necesitaríamos añadir un mini Hub USB dentro del conector USB del cable. Pero… ¿qué podemos hacer mientras esperamos una V2?
La línea de datos podrá/no podrá ser utilizada en las siguientes cuatro situaciones:
1. Si conectamos Evil Crow cable sólo a un ordenador, el payload se ejecutará correctamente.
2. Si conectamos Evil Crow cable junto a un dispositivo multimedia (teléfono, mp3, etc) a la vez a un ordenador, se habilitará la línea de datos y podremos acceder al almacenamiento del dispositivo multimedia, pero el payload no se ejecutará.
3. Primero conectamos Evil Crow cable a un ordenador y después de ejecutar el payload conectamos un dispositivo multimedia al puerto MicroUSB: La línea de datos será habilitada y podremos acceder al almacenamiento del dispositivo multimedia, pero tendremos que esperar unos 10-15 segundos después de la ejecución del payload antes de conectar el dispositivo multimedia. Si conectamos el dispositivo multimedia antes de esos 10-15 segundos, es posible que la línea de datos no funcione correctamente.
4. Primero conectamos Evil Crow cable y un dispositivo multimedia a un ordenador a la vez, la línea de datos será habilitada y tendremos acceso al almacenamiento del dispositivo multimedia (ver punto 2 de esta sección). Después, desconectamos el dispositivo multimedia mientras Evil Crow cable sigue conectado al ordenador: el payload se ejecuta correctamente.
Dejamos el siguiente enlace con la demostración en vídeo de la línea de datos para entenderlo mejor:
Actualmente estamos trabajando en la versión V2 de Evil Crow cable donde tendremos control total sobre la línea de datos, y posiblemente… control remoto sobre el propio cable, pero mientras tanto… se decidió habilitar esta PoC en todos los cables de producción para pruebas 😀
Para terminar, decir que tenéis toda la información de la instalación vista en el artículo y más información sobre la línea de datos en el siguiente repositorio:
Para ofrecer las mejores experiencias, utilizamos tecnologías como las cookies para almacenar y/o acceder a la información del dispositivo. El consentimiento de estas tecnologías nos permitirá procesar datos como el comportamiento de navegación o las identificaciones únicas en este sitio. No consentir o retirar el consentimiento, puede afectar negativamente a ciertas características y funciones.
Funcional
Siempre activo
El almacenamiento o acceso técnico es estrictamente necesario para el propósito legítimo de permitir el uso de un servicio específico explícitamente solicitado por el abonado o usuario, o con el único propósito de llevar a cabo la transmisión de una comunicación a través de una red de comunicaciones electrónicas.
Preferencias
El almacenamiento o acceso técnico es necesario para la finalidad legítima de almacenar preferencias no solicitadas por el abonado o usuario.
Estadísticas
El almacenamiento o acceso técnico que es utilizado exclusivamente con fines estadísticos.El almacenamiento o acceso técnico que se utiliza exclusivamente con fines estadísticos anónimos. Sin un requerimiento, el cumplimiento voluntario por parte de tu Proveedor de servicios de Internet, o los registros adicionales de un tercero, la información almacenada o recuperada sólo para este propósito no se puede utilizar para identificarte.
Marketing
El almacenamiento o acceso técnico es necesario para crear perfiles de usuario para enviar publicidad, o para rastrear al usuario en una web o en varias web con fines de marketing similares.