Cómo registrar qué USBs se han conectado en Linux

Publicado el 19 febrero 2018 por Drassill
La recopilación de información es cada día más importante; en servidores siempre lo ha sido, pero en los equipos de sobremesa ha ido cobrando importancia paulatinamente  y hoy en día se ha demostrado que es importante tener registrada toda la información por si en un futuro nos pudiese llegar a ser útil. Hoy quiero hablar sobre el registro de USBs en Linux. Linux tiene la gran ventaja de tener una enorme cantidad de logs, pero los logs no siempre te registran todos los datos que uno desea y corremos el peligro de que dichos logs sean borrados o se roten mediante utilidades tales como logrotate; utilidades especialmente comunes en servidores. Por eso puede ser interesante tener una herramienta corriendo en segundo plano cuya única función sea registrar qué USBs se han conectado/desconectado, la hora en la que lo han hecho, datos útiles tales como el número de serie y de paso, registrar su actividad a ser posible.

En este caso no optaremos a herramientas de terceros sino que tiraremos de conceptos de Linux y los aglutinaremos en un script que automatice todo ello... Además, en este caso, no almacenaremos la información en un fichero en texto plano, sino que vamos a almacenarla en una mini base de datos en formato SQLite... El motivo por el cual se ha optado por dicha opción es simple: SQLite requiere instalar pocas herramientas en el equipo lo cual es perfecto en equipos de sobremesa; además es una base de datos que consume muy pocos recursos por parte del equipo y al mismo tiempo tiene la gran ventaja de seguir siendo una base de datos basada en el lenguaje SQL, con lo cual podríamos hacer consultar de su información mediante consultas SQL mediante SELECTs con sus respectivos filtros, etc... Haciendo que la consulta de la información en el futuro sea muchísimo más eficiente, con la contrapartida de que se requieren unos conocimientos básicos de SQL para poder sacarle partido.
Teniendo esto en cuenta, comencemos con la instalación de las dependencias necesarias para que nuestra solución funcione... Dependiendo de qué distribución tengamos y las herramientas que tengamos instaladas, puede ser que ya tengamos todo lo necesario, pero para asegurarnos haremos:
apt-get install sqlite
Teniendo todo preparado, pasaríamos a crearnos primero la mini base de datos que almacenará la información de los USBs. En mi caso en particular he creado la base de datos en /var y la he llamado listaUsbs.db con lo que su creación sería tal que así:
sqlite /var/listaUSBs.db
Esto no solo crearía la base de datos, sino que estaríamos dentro de ella, con lo que pasaríamos a crear la tabla en cuestión. En mi caso he llamado a la tabla listausbs y su creación (junto con sus respectivas columnas) sería la siguiente:
CREATE TABLE lista_usbs (NOMBRE,FECHA_DETECT,FECHA_DESCONEX,
IDVENDOR,IDPRODUCT,MANUFACT,IPRODUCT,SERIAL);
En esta base de datos guardaremos toda la información importante tal como el nombre completo, la fecha de detección del USB, el fabricante y el numero de serie... Información que puede sernos útil en el futuro. Con esto claro, podemos crear un script en el que por un lado monitoricemos en tiempo real toda la actividad USB mediante tcpdump, y por otro lado también podemos tener constancia de qué USB se ha conectado en qué momento; esto lo podemos lograr mediante el siguiente script, al cual yo he llamado registrador_usbs.sh y que ha sido probado en Debian 8:
#!/bin/bash
#CAPTURAMOS TODO EL TRAFICO USB
modprobe usbmon
nohup tcpdump -i usbmon1 -w /tmp/captura.cap &
while true;
do
#COMPROBAMOS SI SE HA CONECTADO ALGUN USB NUEVO
if [ ! -f /tmp/listausbs2.txt ];
then
touch /tmp/listausbs2.txt
fi
lsusb > /tmp/listausbs.txt
diff /tmp/listausbs.txt /tmp/listausbs2.txt
if [ $? -eq 1 ]
then
diff /tmp/listausbs.txt /tmp/listausbs2.txt > /tmp/cambio.txt
cat /tmp/cambio.txt |tail -n +2 > /tmp/cambio2.txt
while read CAMBIO;
do
echo ${CAMBIO} > /tmp/cambio3.txt
cat /tmp/cambio3.txt |grep "<"
if [ $? -eq 0 ];
then
#SI ES UNA CONEXION NUEVA LA REGISTRAMOS
NOMBRE="$( cat /tmp/cambio3.txt |cut -d '<' -f 2 |cut -d ':' -f 2- | cut -d 'D' -f 2- )"
echo $NOMBRE
lsusb -D /dev/bus/usb/$(lsusb |grep "${NOMBRE}" |awk {'print $2'})/$(lsusb |grep "${NOMBRE}" |awk {'print $4'} |cut -d ":" -f 1) > /tmp/usb_detallado.txt
FECHA_DETECT=$(date)
FECHA_DESCONEX=''
IDVENDOR=$(cat /tmp/usb_detallado.txt |grep idVendor |awk '{for (i=2; i<NF; i++) printf $i " "; if (NF >= 2) print $NF; }')
IDPRODUCT=$(cat /tmp/usb_detallado.txt |grep idProduct |awk '{for (i=2; i<NF; i++) printf $i " "; if (NF >= 2) print $NF; }')
MANUFACT=$(cat /tmp/usb_detallado.txt |grep iManufacturer |awk '{for (i=2; i<NF; i++) printf $i " "; if (NF >= 2) print $NF; }')
IPRODUCT=$(cat /tmp/usb_detallado.txt |grep iProduct |awk '{for (i=2; i<NF; i++) printf $i " "; if (NF >= 2) print $NF; }')
SERIAL=$(cat /tmp/usb_detallado.txt |grep iSerial |awk '{for (i=2; i<NF; i++) printf $i " "; if (NF >= 2) print $NF; }')
sqlite /var/listaUSBs.db "INSERT INTO lista_usbs VALUES ('${NOMBRE}','${FECHA_DETECT}','${FECHA_DESCONEX}','${IDVENDOR}','${IDPRODUCT}','${MANUFACT}','${IPRODUCT}','${SERIAL}');"
rm /tmp/usb_detallado.txt
fi
cat /tmp/cambio3.txt |grep ">"
if [ $? -eq 0 ];
then
#SI ES UNA DESCONEXION ACTUALIZAMOS LOS DATOS CORRESPONDIENTES
NOMBRE="$( cat /tmp/cambio3.txt |cut -d '>' -f 2 |cut -d ':' -f 2- | cut -d 'D' -f 2- )"
FECHA_DESCONEX=$(date)
sqlite /var/listaUSBs.db "UPDATE lista_usbs SET FECHA_DESCONEX='${FECHA_DESCONEX}' WHERE FECHA_DESCONEX='' AND NOMBRE='${NOMBRE}';"
fi
done < /tmp/cambio2.txt
rm /tmp/cambio.txt
rm /tmp/cambio2.txt
rm /tmp/cambio3.txt
fi
mv /tmp/listausbs.txt /tmp/listausbs2.txt
done

Con este script, solamente ejecutándolo en segundo plano estaríamos monitorizando en tiempo real toda la actividad mediante tcpdump, y registrándola en nuestra base de datos SQLite. Solamente habría que escribir:
/registrador_usbssh >/dev/null &
Dicha información podría ser consultada en el futuro mediante consultas SQL tales como:
Para ver todos los registros:
sqlite /var/listaUSBsdb "SELECT * FROM lista_usbs;"
Para ver un numero de serie concreto:
sqlite /var/listaUSBsdb "SELECT * FROM lista_usbs WHERE 
SERIAL
='3 20060413092100000';"
Para eliminar todos los registros:
sqlite /var/listaUSBsdb "DELETE FROM lista_usbs;"

Con ello tendríamos todo monitorizado y registrado en nuestro equipo ganando un gran control sobre la actividad USB en nuestro equipo. Obviamente dicho script sería solamente un ejemplo teórico que puede ser modificado a nuestro gusto para que se adapte lo mejor posible a nuestras necesidades.
Espero que os haya resultado útil.
Saludos.