Cómo instalar y usar Radamsa para probar programas y servicios de red con fuzzing en Ubuntu 18.04

El autor seleccionó la Electronic Frontier Foundation Inc para recibir una donación como parte del programa Write for DOnations.

Introducción

Las amenazas de seguridad son cada vez más complejas, por lo que los desarrolladores y los administradores de sistemas deben adoptar un enfoque proactivo para defender y probar la seguridad de sus aplicaciones.

Un método frecuente para probar la seguridad de aplicaciones o servicios de red de clientes es el fuzzing, que implica enviar datos no válidos o con formato incorrecto a la aplicación en cuestión y analizar su respuesta. Es útil para ayudar a probar cuán resistente y sólida es una aplicación ante entradas inesperadas, como datos corruptos o ataques reales.

Radamsa es una herramienta de fuzzing de código abierto que puede generar casos de prueba basados en datos de entrada especificados por el usuario. Se puede programar mediante scripts por completo y se utiliza para detectar vulnerabilidades en aplicaciones reales, como Gzip, de forma exitosa.

A través de este tutorial, instalará y utilizará Radamsa para probar aplicaciones de línea de comandos y de red con fuzzing usando sus propios casos de prueba.

Advertencia: Radamsa es una herramienta de pruebas de penetración que le permite identificar vulnerabilidades o deficiencias en sistemas o aplicaciones determinados. No debe usar las vulnerabilidades que detecte Radamsa para ninguna forma de comportamiento imprudente, daño o explotación malintencionada. Las vulnerabilidades se deben informar de manera ética a la persona encargada del mantenimiento de la aplicación afectada y no se deben divulgar públicamente sin permiso explícito.

Requisitos previos

Para completar esta guía, necesitará lo siguiente:

  • Un servidor de Ubuntu 18.04 configurado siguiendo la Guía de configuración inicial de servidores para Ubuntu 18.04 con un usuario sudo no root y firewall habilitado para bloquear los puertos que no sean esenciales.
  • La aplicación de línea de comandos o de red que desee probar; por ejemplo, Gzip, Tcpdump, Bind, Apache, jq o cualquier otra que prefiera. En este tutorial, usaremos jq como ejemplo.

Advertencia: Radamsa puede hacer que aplicaciones o sistemas se ejecuten de forma inestable o se bloqueen, por lo que debe ejecutarlo únicamente en un entorno en el que esté preparado para esto, como un servidor dedicado. Asegúrese también de contar con el permiso explícito por escrito del propietario del sistema que probará con fuzzing antes proceder.

Una vez que tenga todo esto listo, inicie sesión en su servidor como usuario no root.

Paso 1: Instalar Radamsa

Primero, descargará y compilará Radamsa para comenzar a utilizarlo en su sistema. El código fuente de Radamsa está disponible en el repositorio oficial de GitLab.

Comience actualizando el índice de paquetes locales de modo que se refleje cualquier cambio anterior:

  • sudo apt update

Luego, instalará los paquetes gcc, git, make y wget necesarios para compilar el código fuente en un binario ejecutable:

  • sudo apt install gcc git make wget

Después de confirmar la instalación, apt descargará e instalará los paquetes específicos y todas sus dependencias necesarias.

A continuación, descargará una copia del código fuente de Radamsa clonándolo del repositorio alojado en GitLab:

  • git clone https://gitlab.com/akihe/radamsa.git

Al hacerlo, se creará un directorio llamado radamsa que contendrá el código fuente de la aplicación. Diríjase al directorio para comenzar a compilar el código:

  • cd radamsa

Luego, puede iniciar el proceso de compilación usando make:

  • make

Por último, puede instalar el binario de Radamsa compilado en su $PATH:

  • sudo make install

Una vez completado esto, puede verificar la versión instalada para asegurar que todo funcione:

  • radamsa --version

El resultado debe tener un aspecto similar al siguiente:

OutputRadamsa 0.6 

Si ve el error radamsa: command not found, verifique que todas las dependencias necesarias se hayan instalado y que no se haya habido errores durante la compilación.

Ahora que instaló Radamsa, puede comenzar a generar algunos casos de prueba de muestra para comprender el funcionamiento de Radamsa y sus aplicaciones.

Paso 2: Generar casos de prueba con fuzzing

Ahora que instaló Radamsa, puede usarlo para generar casos de pruebas con fuzzing.

Un caso de prueba es información que se utilizará como entrada para el programa que someta a prueba. Por ejemplo, si prueba con fuzzing un programa de archivo, como Gzip, un caso de prueba puede ser un archivo de almacenamiento que intente descomprimir.

Nota: Radamsa manipula los datos de entrada de una gran variedad de formas inesperadas, como la repetición extrema, la inversión de bits y la inserción de caracteres de control, entre otras. Antes de proceder, tenga en cuenta que esto puede hacer que su sesión de terminal se interrumpa o se vuelva inestable.

Primero, pase un texto sencillo a Radamsa para ver lo que sucede:

  • echo "Hello, world!" | radamsa

Con esto, se manipularán (o expondrán a fuzzing) los datos ingresados y se generará un caso de prueba, como el siguiente:

OutputHello,, world! 

En este caso, Radamsa agregó una coma adicional entre Hello y world. A pesar de que no parezca un cambio significativo, en algunas aplicaciones, esto puede hacer que los datos se interpreten de forma incorrecta.

Hagamos un nuevo intento ejecutando el mismo comando. Obtendrá un resultado distinto:

OutputHello, '''''''wor'd! 

Esta vez, se insertaron varias comillas simples (') en la cadena, entre ellas, una que sobrescribió la l en world. Las posibilidades de que este caso de prueba en particular genere problemas en aplicaciones son más altas, dado que se suelen utilizar comillas simples y dobles para separar diferentes porciones de datos de una lista.

Probemos una vez más:

OutputHello, $+$PATHu0000`xcalc`world! 

En este caso, Radamsa insertó una cadena de inserción de shell, que será útil para realizar pruebas en busca de vulnerabilidades de inserción de comandos en la aplicación que pruebe.

Usó Radamsa para someter a fuzzing una cadena de entrada y producir una serie de casos de prueba. A continuación, utilizará Radamsa para someter a fuzzing una aplicación de línea de comandos.

Paso 3: Someter a fuzzing una aplicación de línea de comandos

En este paso, utilizará Radamsa para aplicar fuzzing a una aplicación de línea de comandos e informar los bloqueos que se produzcan.

La técnica exacta para hacer pruebas con fuzzing varía en gran medida de un programa a otro, así como la eficacia de cada método. Sin embargo, en este tutorial usaremos jq como ejemplo, que es un programa de línea de comandos para procesar datos de JSON.

Puede usar cualquier otro programa similar siempre y cuando aplique el principio general de tomar algún tipo de datos estructurados o no estructurados, hacer algo con ellos y luego producir un resultado. Por ejemplo, este caso también funcionaría con Gzip, Grep, bc y tr, entre otros.

Si aún no instaló jq, puede hacerlo usando apt:

  • sudo apt install jq

De esta manera, jq quedará instalado.

Para comenzar la prueba con fuzzing, cree un archivo JSON de ejemplo que utilizará como entrada para Radamsa:

  • nano test.json

Luego, añada los siguientes datos de JSON de ejemplo al archivo:

test.json

{   "test": "test",   "array": [     "item1: foo",     "item2: bar"   ] } 

Puede analizar este archivo usando jq si desea verificar que la sintaxis de JSON sea válida:

  • jq . test.json

Si el JSON es válido, jq mostrará el archivo. De lo contrario, mostrará un error que puede usar para corregir la sintaxis cuando sea necesario.

A continuación, aplique fuzzing al archivo JSON de prueba usando Radamsa y, luego, páselo a jq. Esto hará que jq lea el caso de prueba sometido a fuzzing o manipulado en lugar de los datos JSON originales válidos.

  • radamsa test.json | jq

Si Radamsa muestra los datos de JSON de una forma que siga siendo válida desde el punto de vista sintáctico, jq mostrará los datos, pero con los cambios que le haya realizado Radamsa.

Alternativamente, si Radamsa hace que los datos de JSON no sean válidos, jq mostrará un error que corresponda. Por ejemplo:

Outputparse error: Expected separator between values at line 5, column 16 

El resultado alternativo sería que jq no pudiera manejar los datos sometidos a fuzzing de forma correcta, lo cual haría que se bloqueara o no funcionara de forma adecuada. Esto es lo que realmente se busca con el método de fuzzing, ya que podría indicar una vulnerabilidad de seguridad, como un desbordamiento de búfer o una inserción de comandos.

Para realizar pruebas de detección de vulnerabilidades como estas de forma más eficiente, se puede usar una secuencia de comandos de Bash a fin de automatizar el proceso de fuzzing, incluidos los procesos de generar casos de prueba, pasarlos al programa de destino y detectar cualquier resultado pertinente.

Cree un archivo llamado jq-fuzz.sh:

  • nano jq-fuzz.sh

El contenido exacto de la secuencia de comandos variará según el tipo de programa que someta a fuzzing y los datos de entrada. Sin embargo, en el caso de jq y otros programas similares, la secuencia de comandos siguiente será suficiente.

Copie la secuencia de comandos a su archivo jq-fuzz.sh:

jq-fuzz.sh

#!/bin/bash while true; do   radamsa test.json > input.txt   jq . input.txt > /dev/null 2>&1   if [ $? -gt 127 ]; then     cp input.txt crash-`date +s%.%N`.txt     echo "Crash found!"   fi done 

Esta secuencia de comandos contiene while para hacer que el contenido se repita reiteradamente. Cada vez que se repita la secuencia de comandos, Radamsa generará un caso de prueba basado en test.json y lo guardará en input.txt.

Luego, el caso de prueba input.txt se ejecutará en jq y todo el resultado estándar y de error se reenviará a /dev/null para evitar saturar la pantalla del terminal.

Por último, se verifica el valor de salida de jq. Si el valor de salida es superior a 127, esto indica una interrupción irrecuperable (un bloqueo), por lo que los datos de entrada se guardan para su análisis posterior en un archivo llamado crash- seguido de la fecha actual en segundos y nanosegundos de Unix.

Marque la secuencia de comandos como ejecutable y ejecútela para comenzar a probar jq con fuzzing de forma automática:

  • chmod +x jq-fuzz.sh
  • ./jq-fuzz.sh

Puede pulsar CTRL+C en cualquier momento para finalizar la secuencia de comandos. Luego, puede verificar si se encontraron errores utilizando ls para mostrar una lista de directorios en la que se encuentran los archivos de bloqueos que se hayan creado.

Se recomienda mejorar los datos de JSON de entrada, dado que probablemente el uso de un archivo de entrada más complejo mejore la calidad de los resultados de la aplicación de fuzzing. Evite usar un archivo grande o uno que contenga muchos datos repetidos; lo ideal es usar un archivo de entrada que sea pequeño y, no obstante, tenga la mayor cantidad de elementos “complejos” posible. Por ejemplo, un buen archivo de entrada debe contener muestras de datos almacenados en todos los formatos, incluso cadenas, enteros, booleanos, listas, objetos y datos anidados si es posible.

Utilizó Radamsa para probar una aplicación de línea de comandos con fuzzing. A continuación, utilizará Radamsa para probar solicitudes a servicios de red.

Paso 4: Probar solicitudes a servicios de red con fuzzing

Radamsa también se puede utilizar para probar servicios de red, ya sea como cliente o servidor de red. En este paso, utilizará Radamsa para probar un servicio de red con fuzzing y Radamsa funcionará como cliente.

El propósito de probar servicios de red con fuzzing es determinar cuán resistente es un servicio de red en particular ante el envío de datos maliciosos o con formato incorrecto. Muchos servicios de red, como los servidores web o DNS, suelen estar expuestos a Internet, lo cual los convierte en un objetivo común para los atacantes. Un servicio de red que no sea suficientemente resistente a la recepción de datos con formato incorrecto puede bloquearse o, lo que sería peor aún, fallar en estado abierto. Esto podría permitir a los atacantes leer datos confidenciales, como claves de cifrado o datos de usuarios.

Si bien la técnica específica para probar servicios de red con fuzzing varía en gran medida según el servicio de red, en este ejemplo usaremos Radamsa para probar un servidor web básico que proporciona contenido HTML estático.

Primero, debe configurar el servidor web para su uso en pruebas. Puede hacerlo usando el servidor de desarrollo incorporado que viene con el paquete php-cli. También necesitará curl para probar su servidor web.

Si no tiene php-cli ni curl instalados, puede instalarlos usando apt:

  • sudo apt install php-cli curl

A continuación, cree un directorio para almacenar los archivos de su servidor web y posiciónese en él:

  • mkdir ~/www
  • cd ~/www

Luego, cree un archivo HTML que contenga texto de ejemplo:

  • nano index.html

Añada lo siguiente al archivo:

index.html

<h1>Hello, world!</h1> 

Ahora, podrá ejecutar su servidor web de PHP. Tendrá que poder ver el registro del servidor web mientras siga utilizando otra sesión de terminal. Por ello, abra otra sesión y aplique SSH al servidor para lo siguiente:

  • cd ~/www
  • php -S localhost:8080

Con esto, se mostrará algo similar a lo siguiente:

OutputPHP 7.2.24-0ubuntu0.18.04.1 Development Server started at Wed Jan  1 16:06:41 2020 Listening on http://localhost:8080 Document root is /home/user/www Press Ctrl-C to quit. 

Ahora, podrá regresar a su sesión de terminal original y verificar que el servidor web esté funcionando mediante curl:

  • curl localhost:8080

Con esto, se mostrará el archivo de ejemplo index.html que creó anteriormente:

Output<h1>Hello, world!</h1> 

Solo se debe poder acceder a su servidor web de forma local, por lo que no debe abrir ningún puerto en su firewall para él.

Ahora que configuró su servidor web de prueba, podrá comenzar a realizar pruebas con fuzzing utilizando Radamsa.

Primero, deberá crear una solicitud HTTP de ejemplo a fin de usarla como información de entrada para Radamsa. Cree un archivo nuevo para almacenar esto en la siguiente ubicación:

  • nano http-request.txt

Luego, copie la siguiente solicitud HTTP de ejemplo al archivo:

http-request.txt

GET / HTTP/1.1 Host: localhost:8080 User-Agent: test Accept: */* 

A continuación, puede usar Radamsa para enviar esta solicitud HTTP a su servidor web local. Para hacerlo, deberá usar Radamsa como cliente TCP, lo que se puede hacer especificando una dirección IP y un puerto para establecer conexión:

  • radamsa -o 127.0.0.1:8080 http-request.txt

Nota: Tenga en cuenta que usar Radamsa como cliente TCP, puede hacer que se transmitan datos maliciosos o con formato incorrecto a través de la red. Esto puede provocar errores; por ello, debe asegurarse de acceder únicamente a las redes que tenga permitido probar o, preferentemente, aténgase a utilizar la dirección de host local (127.0.0.1).

Por último, si ve los registros de salida de su servidor web local observará que recibió las solicitudes, pero probablemente no las haya procesado porque no eran válidas o tenían un formato incorrecto.

Los registros de salida se mostrarán en su segunda ventana de terminal:

Output[Wed Jan  1 16:26:49 2020] 127.0.0.1:49334 Invalid request (Unexpected EOF) [Wed Jan  1 16:28:04 2020] 127.0.0.1:49336 Invalid request (Malformed HTTP request) [Wed Jan  1 16:28:05 2020] 127.0.0.1:49338 Invalid request (Malformed HTTP request) [Wed Jan  1 16:28:07 2020] 127.0.0.1:49340 Invalid request (Unexpected EOF) [Wed Jan  1 16:28:08 2020] 127.0.0.1:49342 Invalid request (Malformed HTTP request) 

Para obtener resultados óptimos y asegurarse de que los bloqueos se registren, es conveniente escribir una secuencia de comandos de automatización similar a la que se utilizó en el paso 3. También debe considerar la posibilidad de usar un archivo de entrada más complejo, que puede contener elementos añadidos, como encabezados HTTP adicionales.

De esta manera, probó un servicio de red con fuzzing usando Radamsa como cliente TCP. A continuación, probará a un cliente de red utilizando Radamsa como servidor.

Paso 5: Probar aplicaciones clientes de red con fuzzing

En este paso, utilizará Radamsa para probar una aplicación cliente de red con fuzzing. Esto se logra interceptando respuestas de un servicio de red y sometiéndolas a fuzzing antes de que las reciba el cliente.

El propósito de este tipo de fuzzing es probar la resistencia de las aplicaciones clientes de red a la recepción de datos maliciosos o de formato incorrecto de servicios de red. Por ejemplo, probará un navegador web (cliente) que recibirá HTML con formato incorrecto de un servidor web (servicio de red) o un cliente DNS que recibirá respuestas DNS con formato incorrecto de un servidor DNS.

Al igual que en el caso de aplicaciones de línea de comandos o servicios de red, la técnica exacta para probar con fuzzing cada aplicación cliente de red varía considerablemente. Sin embargo, en este ejemplo utilizará whois, una aplicación de envío y recepción simple basada en TCP.

La aplicación whois se utiliza para enviar solicitudes a servidores WHOIS y recibir registros WHOIS como respuesta. WHOIS funciona a través del puerto TCP 43 con texto no cifrado, por lo que es ideal para realizar pruebas con fuzzing en redes.

Si aún no cuenta con whois, puede instalarlo usando apt:

  • sudo apt install whois

Primero, deberá adquirir una respuesta whois de muestra para usarla como dato de entrada. Puede hacerlo enviando una solicitud whois y guardando el resultado en un archivo. Puede usar cualquier dominio que desee, dado que probará el programa whois de forma local con datos de muestra:

  • whois example.com > whois.txt

A continuación, deberá configurar Radamsa como un servidor que proporcione versiones distorsionadas de esta respuesta whois. Deberá poder continuar usando su terminal una vez que Radamsa esté en ejecución en el modo de servidor, por lo que se recomienda abrir otra sesión de terminal y conexión SSH con su servidor para lo siguiente:

  • radamsa -o :4343 whois.txt -n inf

Con esto, Radamsa se ejecutará en el modo de servidor TCP y enviará una versión de whois.txt sometida a fuzzing cada vez que se establezca una conexión con el servidor, independientemente de los datos de solicitud que se reciban.

Ahora, puede proceder con la prueba de la aplicación cliente whois. Deberá realizar una solicitud whois normal para cualquier dominio que prefiera (no es necesario que sea el mismo al que se aplican los datos de muestra), pero con whois apuntando a su servidor de Radamsa local:

  • whois -h localhost:4343 example.com

Recibirá como respuesta sus datos de muestra, aunque distorsionados por Radamsa. Puede continuar realizando solicitudes al servidor local mientras Radamsa esté en ejecución. Este enviará una respuesta diferente en cada ocasión.

Al igual que con los servicios de red, para mejorar la eficacia de estas pruebas del cliente de red con fuzzing y asegurarse de que se registren los bloqueos, es conveniente escribir una secuencia de comandos de automatización similar a la que se utilizó en el paso 3.

En este paso final, utilizó Radamsa para probar una aplicación cliente de red con fuzzing.

Conclusión

A través de este artículo, configuró Radamsa y lo utilizó para probar una aplicación de línea de comandos, un servicio de red y un cliente de red. Ahora tiene los conocimientos básicos necesarios para probar sus propias aplicaciones con fuzzing y mejorar su solidez y resistencia contra ataques.

Si desea explorar Radamsa en mayor profundidad, puede revisar el archivo README de Radamsa de forma detallada; contiene más información técnica y ejemplos relacionados con los usos posibles de la herramienta:

  • Archivo README de Radamsa

También puede probar otras herramientas de fuzzing como American Fuzzy Lop (AFL), una herramienta de fuzzing avanzada diseñada para probar aplicaciones binarias con una velocidad y una precisión sumamente altas:

  • American Fuzzy Lop