Matando al Patito o Cómo proteger nuestros puertos USB

Hoy en día el uso de los dispositivos USB está muy extendido y como nos ha mostrado nuestro compañero Alvaro es un elemento en la seguridad que no podemos descuidar.
Dispositivos como el Rubber Ducky hacen temblar los cimientos de toda nuestra seguridad ya que es como dar acceso libre a que un atacante se siente delante de nuestro ordenador y ejecute a placer, el único limite es su imaginación. Si os lo habéis perdido no olvidéis darle una lectura al articulo sobre rubber ducky.

En este articulo vamos a repasar algunas de las técnicas que nos pueden ayudar a evitar estas situaciones. Centrándonos en protegernos contra ataques HID vamos a ver dos puntos de vista, primero desde un entorno empresarial y después un método mas casero.

En un entorno de directorio activo podemos deshabilitar el uso de pendrives y dispositivos USB desde las Políticas de Grupo con la ventaja de centralizar la solución para toda la organizacion. También podríamos aplicar estas políticas localmente pero perderíamos la potencia de despliegue de directorio activo.

Creando una nueva política “Prevent Installation of devices not described by other policy settings” (Computer configuration → Administrative Templates → System → Device Installation → Device Installation Restriction) limitamos la instalación de nuevos dispositivos como es el caso del Rubber Ducky.

policy_newdeviceinstallation

También podemos crear una nueva política “All Removable Storage Classes: Deny all access” (Computer configuration → Administrative Templates → System → Removable Storage Access) para limitar el uso de los dispositivos de almacenamiento.

policy_usbdeny

 

Ahora vamos a probar un método mas casero del compañero Shargon, monitorizar los puertos USB y bloquear nuestro equipo al detectar un nuevo dispositivo y evitar así el uso de Rubber ducky, Mouse Digglers y otros dispositivos malintencionados.

Como método para proteger nuestros laptops o pc hemos creado un par de pruebas de concepto, en Powershell para sistemas Windows y en Python para sistemas Linux.

En el caso de Windows primero guardamos los dispositivos conectados al inicio para después registrar un evento wmi que se disparará cuando se pinche un nuevo dispositivo, entones comprobamos si se corresponde con la lista inicial y de no ser así bloqueamos la sesión del usuario.

Como extra hemos incluido la funcionalidad de contar con una lista blanca para incluir algún pendrive de uso común o algún dispositivo de confianza.

Código Powershell

#$DebugPreference = "Continue"
$white_list = "USBSTOR\DISK&VEN_&PROD_USB_DISK_3.0&REV_PMAP\07450324FA276B10&0","USBSTOR\DISK&VEN_&PROD_USB_DISK_3.0&REV_PMAP\03450324FA276A11&0"

function Get-DevicesID {
    Get-WmiObject Win32_USBControllerDevice | Foreach-Object { [Wmi]$_.Dependent | Select -ExpandProperty DeviceID }
    }

function Check-NewDevice {
    $actual_dev = Get-DevicesID
    Write-Debug ("New Devices = "+$actual_dev)
    $test = Compare-Object $actual_dev $global:init_dev
    if($test) {
        if($test.InputOBJECT -notcontains $white_list) {$true}
        }
    }

function Run-Action {
    Write-Debug "Run-Action"
    if(Check-NewDevice) {
        Write-Debug "Lock"
        rundll32.exe user32.dll, LockWorkStation
        }
    }

$global:init_dev = Get-DevicesID
Write-Debug ("Init Devices = "+$init_dev)
$query_event = "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"
Register-WMIEvent -SourceIdentifier "USB_Monitor" -Query $query_event -Action { Run-Action } | Write-Debug

 

VIDEO POC WINDOWS

 

También hemos realizado una POC sencilla en Python para ilustrar el mismo método en sistemas Linux, en este caso revisamos los puertos USB cada medio segundo y si se detecta alguna variación se bloquea la sesión de Kali Linux.

Código Python

from os import walk, system
from time import sleep

usb_devices = "/dev/bus/usb"

init_devices = []
actual_devices = []

for (dirpath, dirnames, filenames) in walk(usb_devices):
	if filenames:
		init_devices.extend([dirpath,filenames])

while True:
	actual_devices = []
	for (dirpath, dirnames, filenames) in walk(usb_devices):
		if filenames:
			actual_devices.extend([dirpath,filenames])
	if sorted(init_devices) != sorted(actual_devices):
		print "LOCK!"
		#system("gdmflexiserver")
		system("loginctl lock-session 2")
		exit()
	sleep(0.5)

 

VIDEO POC LINUX

Ademas para sistemas GNU Linux podéis probar la magnifica prueba de concepto Patito Hunter de Miguel A. Arroyo.

 

LASTER

Un cuarto método sería mediante Laster, una herramienta OpenSource desarrollada por Shargon. Está disponible en GitHub en la siguiente dirección github.com/shargon/Laster, se trata de una ETL (Extract-Transform-Load) que mediante la configuración de ejemplo (disponible en github.com/shargon/Laster/tree/master/Samples/RubberDucky) podemos obtener resultados similares

Laster

 

Podemos ver en la imagen, que dispone de una entrada que se ejecuta de forma automática, dicha entrada devolverá los identificadores de los dispositivos Plug&Play disponibles, y cuando se modifique alguno (de igual forma que hacíamos un poco antes, en el ejemplo de powershell), se refresca. Dicha acción desencadena la ejecución de un script. Este script, esta realizado de la siguiente manera

Codigo C#

List <string> WhiteList = null;

public override IData ProcessData(IDataProcess sender, IData data, EEnumerableDataState state) 
{
 // Read whiteList
 if (WhiteList == null)
  WhiteList = new List<string>(
   SerializationHelper.DeserializeFromJson <string[]> (
    File.ReadAllText(@"WhiteList.txt"))
  );

 // Search not found
 List <object> errors = new List<object> ();
 foreach(object o in data)
 if (!WhiteList.Contains(o.ToString()))
  errors.Add(o.ToString());

 return Reduce(EReduceZeroEntries.Break, errors);
}

 

Básicamente, la primera vez que se ejecuta lee los dispositivos del archivo WhiteList.txt, y en posteriores ejecuciones, comprueba que los dispositivos estén en dicha lista, de lo contrario devolverá los dispositivos no encontrados, en caso de estar todos, finalizará el script y no llamará a las acciones descendientes de él. Si por un casual devolviese algún dispositivo no encontrado, se ejecutarán 2 acciones mas, un lock station (rundll32.exe user32.dll,LockWorkStation) y el serializado y posterior adición de la fecha y hora actual al archivo de Errores, de forma que sea mas fácil añadir a una lista blanca los dispositivos no encontrados.

Si despues de estos 4 métodos de cazar al pato, acabas precisamente… pagando el pato. Será que no has puesto en práctica los conocimientos del conejo blanco 🙂

Patos

shargon & belane