El USB Dumping consiste en copiar el contenido de un USB introducido en un ordenador, sin que la víctima se entere.
En Ubuntu, podemos conseguir que se ejecute el script que llevará a
cabo el robo de información, cuando se conecte un dispositivo USB. Para
ello, deberemos crear alguna regla de udev
.
udev
y sysfs
udev
se encarga de crear los nodos en /dev
para los dispositivos
presentes en el sistema. Para ello, se basa en la información
prorcionada por sysfs
y una serie de reglas proporcionadas por el
usuario. sysfs
devuelve información de los dispositivos conectados al
sistema, y udev
lo utiliza para crear los nodos /dev
.
Reglas
Las reglas se guardan en ficheros de configuración dentro del directorio
/etc/udev/rules.d
. Los nombres de los ficheros pueden tener un número
al comienzo, en función de la prioridad y de algunos privilegios que les
queramos otorgar. En el archivo README que hay en ese directorio hay una
pequeña explicación de esto. A nosotros nos basta con saber que, como no
nos importa el orden, nuestro fichero de reglas no necesita llevar
prefijo numérico. Podría llamarse, por ejemplo:
/etc/udev/rules.d/usb-dumping.rules
.
Las reglas podrán ser aplicadas inmediatamente después de haber guardado el fichero, ya que no es necesario reiniciar el demonio.
Para nuestro caso, la regla sería:
KERNEL=="sd[b-d]1", ACTION=="add", RUN+="/home/karpoke/usb-dumping.sh %k"
donde
KERNEL=="sd[b-d]1"
, especifica que la regla se debe ejecutar cada vez que el kernel asigne un nombre comosdb1
,sdc1
ósdd1
. Evitamos el/dev/sda
porque es donde está montado el sistema. También hemos evitado interesarnos por otras particiones que pudiera haber en el disco:sdb2
,sdb5
, etc...ACTION=="add"
, especifica que la regla se debe ejecutar cuando se conecte el dispositivo. Lo contrario sería remove.RUN+="..."
, especifica el script que hay que ejecutar cuando se cumplen las condiciones.%k
, es el nombre que le asigna el kernel al dispositivo y se lo pasamos al script como parámetro.
En el fichero /var/log/messages
, podremos obtener información útil
acerca de los dispositivos conectados y de si no encuentra nuestro
script o no puede ejecutarlo, pero, ¡ojo!, no saldrá nada si nuestro
script no hace lo que toca o si tiene algún error de sintaxis.
Volcado
dd
El script, que se ejecuta como root
, es importante que esté marcado
como ejecutable y contenga el shebang en la primera línea, ya que
udev
no lo ejecutará en un terminal ni en una consola. Podría ser algo
tan sencillo como:
#!/bin/sh
devname="$1" # p.ej: sdb1
dd if=/dev/$devname of=/tmp/$devname.dd &
Debemos utilizar el &
para asegurarnos de que la ejecución del
script continúa en segundo plano. La ventaja de usar dd
es que no
bloquea el dispositivo, por lo que si la víctima lo retira no pasará
nada. Otra ventaja es que se podrían copiar archivos que la víctima haya
eliminado de su USB. El principal inconveniente es que se creará un
fichero del mismo tamaño que el USB entero, aunque éste estuviera vacío,
con el tiempo que eso puede conllevar. [haciendo pruebas, me ha tardado
1 minuto y 15 segundos para un USB de 1 GByte]
Para recuperar la información del archivo volcado, deberemos montarlo en un directorio:
$ mkdir ~/usb_fs
$ sudo mount -o loop,ro,noexec,nodev /tmp/sdb1.dd ~/usb_fs
La opción noexec
para el mount
es importante, ya que no nos gustaría
que ese USB estuviera infectado y programado para ejecutar algún tipo de
script al montarse.
cp
En lugar de usar dd
podríamos utilizar cp
, con la ventaja de que
sólo copia los ficheros y directorios existentes en el USB. En este
caso, el inconveniente es que se bloquea el USB, y no dejará que el
dispositivo se expulse de forma segura hasta que haya terminado la
copia.
Hay que tener en cuenta que no podemos utilizar cp
directamente con
/dev/sdb1
, sino que primero deberemos montar el dispositivo.
#!/bin/sh
devname="$1" # p.ej: sdb1
mkdir /mnt/$devname
mount /dev/$devname /mnt/$devname
cp -fr /mnt/$devname /tmp &
Sin embargo, esto tiene otro problema, y es que al haber montado el dispositivo, Ubuntu no lo vuelve a montar y, por tanto, no se muestra al usuario. Podríamos abrir el directorio en un ventana de Gnome con algo como:
export DISPLAY=:0.0
nautilus /mnt/$devname
Por otro lado, si lo hacemos así, el directorio de montaje no se llamará como el nombre del volumen del USB, cosa que podría llamar la atención del usuario.
Además, deberíamos asegurarnos de eliminar el directorio recién creado y
desmontar el dispositivo cuando éste se extraiga. Esto lo podríamos
hacer con otra regla en nuestro fichero de reglas para udev
:
KERNEL=="sd?1", ACTION=="remove", RUN+="/home/karpoke/usb-dumping-umount.sh '%k'"
y en este script para demontar la unidad tendríamos algo como:
umount /dev/$devname
rm -fr /mnt/$devname
¿Y si pudiéramos matar el proceso de copia del primer script desde
este último script, con un pkill
, por ejemplo? No sirve, ya que este
script se ejecuta cuando el dispositivo ya ha sido desconectado, y en
el caso de que utilicemos la opción con cp
y el usuario no podrá sacar
el USB de forma segura antes de que la copia haya terminado.
Protección
La única solución que se me ocurre para protegernos de una forma segura de este tipo de ataques es, o bien no utilizar nuestro USB en ningún otro ordenador, cosa harto improbable si lo que queremos con el USB es tener nuestros archivos independientemente del ordenador en el que estemos, o bien cifrar el contenido del USB, en todo o en parte.