Revista Tecnología

RedTeaming: Command and Control con Pupy Parte I

Publicado el 18 abril 2020 por Debadastra @jdaanial

Pupy es una herramienta que está pensada principalmente para procesos de post-explotación en sistemas Linux, Windows y Android. Funciona como un entorno Command and Control (C&C) en donde el atacante tendrá un servicio ejecutándose en su máquina y podrá comunicarse con uno o varios sistemas comprometidos. Actualmente hay una buena cantidad de herramientas de éste estilo y aunque a simple vista no parece muy interesante, cuando se mira con detenimiento las características que soporta la cosa cambia. En primer lugar como se ha comentado antes, permite la generación de agentes en múltiples sistemas operativos lo que permite crear muestras especificas para el entorno que corresponda a la víctima. Además en el caso de sistemas basados en GNU/Linux y Windows soporta la misma técnica utilizada por Meterpreter a la hora de ejecutarse conocida como Reflective DLL Injection, la cual no es más de una rutina que se encarga de cargar las librerías y cualquier otra dependencia necesaria de forma dinámica sin escribir absolutamente nada en disco, lo que le permite “camuflarse” en el contexto de un proceso en ejecución y evitar la detección por parte de un AV.

Por si fuese poco, es capaz de importar remotamente (sin tocar el disco) el interprete completo de Python en el sistema comprometido y las librerías que hagan falta para la ejecución de scripts que permitan realizar labores de post-explotación. También cuenta con algunos scripts en bash para que la instalación de la herramienta se pueda ejecutar con Docker o docker-compose que se encuentran en el directorio raíz del proyecto, aunque se puede utilizar directamente el fichero “Dockerfile” y “docker-compose.yml” que se encuentran en el directorio <PUPY_INSTALL>/pupy/conf/. Si queréis saber un poco más sobre cómo construir imágenes con Docker y despliegue de microservicios con Docker-compose os recomiendo apuntaros al siguiente curso introductorio en Udemy.

El proceso de instalación es bastante simple y debería de funcionar en cualquier distribución basada en Linux sin ningún problema, ya que solamente es necesario ejecutar el script “install.sh” y éste se encargará de instalar todo lo necesario para ejecutar el componente servidor. Es una buena práctica ver qué hacen este tipo de programas cuando los descargas de cualquier sitio en Internet, espero que el lector no sea de los que se descarga un repositorio de GitHub y simplemente lanza el script “startup.sh” o “install.sh” sin ver qué acciones va a realizar sobre su sistema 🙂
En éste caso hace varias cosas que a lo mejor no resultan tan convenientes (dependiendo del sistema, claro). En primer lugar instala la dependencia “python-curl” la cual en sistemas basados en Debian descargará la librería para la versión de Python 2.7. Luego configura el repositorio de la última versión comunitaria de Docker disponible, habilita el servicio de Docker en el sistema para que se arranque de forma automática y posteriormente añade al usuario actual al grupo de “docker”. Posteriormente se descarga todas las plantillas y dependencias del repositorio de Github para los payloads de Pupy y finalmente, se descarga la imagen de Pupy del repositorio de DockerHub, solo la descarga sin crear un contenedor. Para poder utilizar Pupy hay tres alternativas. Crear un contenedor en Docker partiendo de la imagen que ha descargado el script “install.sh”, utiizar Docker-compose para crear el contenedor anteriormente indicado de forma automática o ejecutar el script “pupysh.py” el cual se encuentra ubicado en <PUPY_INSTALL>/pupy/

Cualquiera de los tres mecanismos es valido. Por simplicidad se puede ejecutar el comando “pupysh.py” después de haber instalado las dependencias incluidas en el fichero “requirements.txt” ubicado en el mismo directorio. Para ello se puede usar PIP teniendo en cuenta que Pupy funciona sobre Python 2.7.

Por defecto la configuración del servidor de Pupy se encuentra ubicada en <PUPY_INSTALL>/pupy/pupy.conf.default y en dicho fichero se controla todo el comportamiento del servidor aunque hay que tener en cuenta que cuando se ejecute el comando “pupysh.py” intentará abrir el puerto 443 y para ello evidentemente son necesarios privilegios de root, por lo tanto es probable que el lector prefiera cambiar éste puerto en el fichero de configuración.

RedTeaming: Command and Control con Pupy Parte I

Al ejecutar el comando “pupysh.py” desde una terminal se puede apreciar que el servidor web arranca en los puertos 9000 y 443. A partir de éste momento es posible interactuar con Pupy por medio de los comandos disponibles en el interprete que se acaba de habilitar. Sin embargo, de momento no se tiene ninguna víctima conectada por lo tanto es poco lo que se puede hacer ahora mismo. El siguiente paso consiste en generar un payload que deberá ser distribuido a una o varias víctimas las cuales serán controladas desde el interprete de Pupy. Para hacer esto existe un script que partiendo de una serie de argumentos genera un payload perfectamente funcional para diferentes distribuciones.

Generación de payloads en Pupy

Los payloads en Pupy se generan con el script “pupygen.py” ubicado en <PUPY_INSTALL>/pupy/ y admite varias opciones entre las que se incluyen el tipo de payload, sistema operativo de la víctima, host donde se encuentra el servidor de Pupy en ejecución y al que el payload se debe conectar, entre otras opciones interesantes. Cuando se ejecuta sin argumentos genera un ejecutable para Windows en una arquitectura x86. Dicho binario será guardado por defecto en <USER_DIR>/.conf/pupy/output

RedTeaming: Command and Control con Pupy Parte I

A continuación se crearán algunos payloads para Windows, Linux y Android, tal como se puede apreciar en la siguiente imagen.

RedTeaming: Command and Control con Pupy Parte I

La opción “-O” permite indicar el tipo de payload, “-A” la arquitectura y “-o” la ruta donde se guardará en payload. Todos estos parámetros son opcionales y tal como se ha mencionado unos párrafos más arriba si no se especifica ninguna generará por defecto un ejecutable para Windows con arquitectura x86.

Existen otras opciones de configuración que no se incluyen directamente en el comando, sino que es necesario editar el fichero de configuración “pupy.conf.default”. Por ejemplo, si el servidor de Pupy se encuentra en una máquina diferente a la que se está utilizando para generar el payload o en una IP concreta, es necesario editar la propiedad “address” que se encuentra en la sección [pupyd].

En dicho fichero de configuración hay varias características interesantes. A continuación se listarán solamente algunas.

– igd: Permite realizar peticiones IGD/UPNP para obtener la dirección IP externa y añadir los mapeos correspondientes a la IP que se encuentra en la red interna. Esto es útil especialmente cuando el servidor de Pupy se encuentra en una red domestica con salida a Internet por medio de un router y los clientes/víctimas provienen desde el exterior.

dnscnc: Permite que Pupy funcione sobre DNS. En éste caso crea un túnel DNS para evadir restricciones entre la víctima y el servidor (DNS Command And Control). La configuración de dicho túnel se debe ajustar en la sección [dnscnc] ubicada un poco más abajo en el mismo fichero de configuración.

[listeners]: Se trata de una sección en la que se establecen los puertos de los diferentes servicios que se levantarán en el servidor. Desde aquí se pueden cambiar dichos valores por defecto si es necesario.

– [webserver]: Como su nombre indica, es una sección en la que se define toda la configuración del servidor web que levanrá Pupy. Hay que tener en cuenta que por defecto utiliza Tornado, una librería en Python para crear clientes reactivos muy parecida a Twisted de la que ya en su día se comento en éste blog.

[gen]: Es ésta sección se definen las opciones por defecto que tendrá la utilidad “pupygen” si falta alguno de los parámetros descritos anteriormente.

[paths]: Rutas por defecto en las que se encontrarán ficheros de logs, plantillas, el directorio raíz del servidor web, etc.

– [on_connect]: Permite especificar los comandos que se van a ejecutar justo en el momento en el que se establezca una conexión entre el servidor y el zombie.

– [bypassuac]: Utiliza algunos de los métodos descritos en el proyecto WinPwange (https://github.com/rootm0s/WinPwnage) para llevar a cabo un bypass del UAC.

– [persistence]: Nuevamente se utiliza el proyecto WinPwange para ejecutar métodos para el establecimiento de backdoors en sistemas basados en Windows.

En el próximo post hablaré más sobre ésta herramienta y se explorará aún más las opciones disponibles, que no son pocas.

Un saludo y Happy Hack
Adastra.


Volver a la Portada de Logo Paperblog