Defensas frente a ataques STP

Continuando con las medidas de seguridad en capa 2 que hemos visto en entradas anteriores, en este post nos centraremos en STP (Spanning Tree Protocol), protocolo usado en la red para evitar bucles a nivel 2 en nuestra topología.

Es habitual ver tráfico similar a este cuando capturas tu propia interfaz (no entro a valorar si dispones de permisos de administrador o si el equipo es un servidor o un equipo de usuario):

13:44:16.651348 STP 802.1d, Config, Flags [none], bridge-id 8001.00:24:f7:31:65:00.8016, length 43
	message-age 0.00s, max-age 20.00s, hello-time 2.00s, forwarding-delay 15.00s
	root-id 8001.00:24:f7:31:65:00, root-pathcost 0
13:44:18.660589 STP 802.1d, Config, Flags [none], bridge-id 8001.00:24:f7:31:65:00.8016, length 43
	message-age 0.00s, max-age 20.00s, hello-time 2.00s, forwarding-delay 15.00s
	root-id 8001.00:24:f7:31:65:00, root-pathcost 0
13:44:20.661034 STP 802.1d, Config, Flags [none], bridge-id 8001.00:24:f7:31:65:00.8016, length 43
	message-age 0.00s, max-age 20.00s, hello-time 2.00s, forwarding-delay 15.00s
	root-id 8001.00:24:f7:31:65:00, root-pathcost 0
13:44:22.666010 STP 802.1d, Config, Flags [none], bridge-id 8001.00:24:f7:31:65:00.8016, length 43
	message-age 0.00s, max-age 20.00s, hello-time 2.00s, forwarding-delay 15.00s
	root-id 8001.00:24:f7:31:65:00, root-pathcost 0
13:44:24.670848 STP 802.1d, Config, Flags [none], bridge-id 8001.00:24:f7:31:65:00.8016, length 43
	message-age 0.00s, max-age 20.00s, hello-time 2.00s, forwarding-delay 15.00s
	root-id 8001.00:24:f7:31:65:00, root-pathcost 0

Como se puede ver en la captura, el tráfico se corresponde con tramas BPDU (Bridge Protocol Data Units) del protocolo STP.

Sin entrar en detalles en el funcionamiento del protocolo, recibir este tipo de tráfico implica que en los switches de capa de acceso no existen medidas de seguridad para gestionar dicho tráfico hacia los equipos finales, lo cual podría permitir a un atacante enviar a la red tramas BPDU falsas, de forma que los dispositivos tengan que recalcular sus rutas, consumiendo recursos y creando una inestabilidad en la red, la cual, en última instancia, podría provocar una denegación de servicio, o por el contrario, podríamos intentar cambiar la topología de la red para que parte del tráfico hacia el exterior se envíe hacia un equipo atacante, donde se inspeccione y se vuelva a enviar a la red. Por suerte, los dispositivos suelen disponer de unas medidas de seguridad que podemos aplicar para mitigar este tipo de ataques.

Para nuestra prueba, usaremos un switch Cisco 2960 y lanzaremos los ataques mediante Yersinia, aunque también podríamos intentar crear los paquetes de forma manual con Scapy si fuera necesario.

Posiblemente, a nivel de puerto de acceso, la funcionalidad relacionada con el protocolo STP más usada es el modo portfast (o edge port). Esta funcionalidad evita que se negocien las distintas operaciones de STP al conectar un dispositivo al puerto donde está configurado, de forma que evitamos el timeout durante el cual el puerto no está operativo. Esto suele ser necesario en equipos de arranque rápidos como VDI, que por ejemplo solicitan IP por DHCP antes de que acabe ese timeout por defecto.

En la situación inicial, el switch es la raíz (root) del árbol, y tenemos nuestro equipo conectado en la interfaz 24.

Switch# show spanning-tree 

VLAN0001
  Spanning tree enabled protocol ieee
  Root ID    Priority    32769
             Address     0024.f731.6500
             This bridge is the root
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    32769  (priority 32768 sys-id-ext 1)
             Address     0024.f731.6500
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec
             Aging Time 300

Interface           Role Sts Cost      Prio.Nbr Type
------------------- ---- --- --------- -------- --------------------------------
Fa0/24              Desg LIS 19        128.24   P2p 


Switch# show spanning-tree root 
                                        Root    Hello Max Fwd
Vlan                   Root ID          Cost    Time  Age Dly  Root Port
---------------- -------------------- --------- ----- --- ---  ------------
VLAN0001         32769 0024.f731.6500         0    2   20  15                  

Lo que vamos a hacer es usar Yersinia para enviar tramas BPDU. Yersinia las envía cada dos segundos con la misma prioridad a nivel de root, pero con una dirección MAC numéricamente inferior, de forma que intentemos generar un cambio en la topología hacia el nuevo root.

Nos conectamos a la consola de Yersinia y tras modificar los parametros de STP, identificando la interfaz de red sobre la que queremos realizar el envío, lanzamos un ataque NONDOS attack Claiming Root Role (4), de forma que el switch registra un cambio de topología reflejado en la aparición de un nuevo root en el puerto 24.

Switch# show spanning-tree root 

                                        Root    Hello Max Fwd
Vlan                   Root ID          Cost    Time  Age Dly  Root Port
---------------- -------------------- --------- ----- --- ---  ------------
VLAN0001         32769 0024.f730.6500        19    2   20  15  Fa0/24    

Como podemos ver, el identificador obtenido por la interfaz 24 es inferior al del propio switch, por lo que se convierte en el nuevo root.

bpduguard

Para evitar esto podemos activar la funcionalidad bpduguard, función que al detectar que se reciben tramas BPDU en un puerto lo deshabilita en modo err-disable, de forma que tengamos que habilitarlo de forma manual.

Switch(config)# interface  fastEthernet  0/24
Switch(config-if)# spanning-tree bpduguard enable

Al lanzar de nuevo el ataque, el puerto queda deshabilitado:

*Mar  1 01:46:36.481: %SPANTREE-2-BLOCK_BPDUGUARD: Received BPDU on port Fa0/24 with BPDU Guard enabled. Disabling port.
*Mar  1 01:46:36.481: %PM-4-ERR_DISABLE: bpduguard error detected on Fa0/24, putting Fa0/24 in err-disable state
*Mar  1 01:46:37.487: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/24, changed state to down
*Mar  1 01:46:38.494: %LINK-3-UPDOWN: Interface FastEthernet0/24, changed state to down
Switch#show  interfaces  fa 0/24 status 

Port      Name               Status       Vlan       Duplex  Speed Type
Fa0/24                       err-disabled 1            auto   auto 10/100BaseTX

Por lo tanto, el puerto queda sin servicio. No obstante, el problema de este modo de funcionamiento es que nosotros mismos estamos facilitando la denegación de servicio ya que el atacante puede ir conectándose a distintas interfaces, de forma que tras lanzar el ataque se van deshabilitando y el siguiente usuario (legítimo) no tendría conexión a la red (aquí entrarían otras medidas de seguridad adicionales como controles de seguridad físicos, port-security, 802.1x, etc).

Como esto puede generar un caos mientras se identifica el origen del problema, tenemos la opción de que la interfaz levante automáticamente después de un timeout, de forma que si el atacante se va o para el ataque, se recuperará el acceso normal a la red. Para ello, configuramos lo siguiente:

Switch(config)# errdisable recovery cause bpduguard 
Switch(config)# errdisable recovery interval 30

Switch# show  errdisable   recovery 
ErrDisable Reason            Timer Status
-----------------            --------------
bpduguard                    Enabled

Timer interval: 30 seconds

De este modo la interfaz se levantaría 30 segundos después y si el ataque ha parado, quedaría operativa:

*Mar  1 01:52:21.445: %PM-4-ERR_RECOVER: Attempting to recover from bpduguard err-disable state on Fa0/24
*Mar  1 01:52:25.858: %LINK-3-UPDOWN: Interface FastEthernet0/24, changed state to up
*Mar  1 01:52:26.864: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/24, changed state to up

Dado que nos interesa conocer este tipo de situaciones, deberíamos configurar el envío de un trap SNMP para alertarnos del ataque y analizar si es algo intencionado, como es el caso de nuestro ataque, o algo no intencionado como puede ser que un usuario conecte un switch para disponer de más conexiones (algo que debería venir previamente autorizado), sin pensar que pueda afectar al resto de la red.

guard root

Otra opción que podemos utilizar es la funcionalidad guard root. Esta opción es similar a la anterior, pero solo bloquea si se reciben tramas BPDU indicando la presencia de un equipo más prioritario el cual sería una nueva raíz del árbol.

Switch(config)# interface  fastEthernet  0/24
Switch(config-if)# spanning-tree guard root
*Mar  1 02:25:23.329: %SPANTREE-2-ROOTGUARD_CONFIG_CHANGE: Root guard enabled on port FastEthernet0/24.

De esta forma, si enviamos una BPDU de ataque de root, el puerto se bloquea:

*Mar  1 02:26:26.689: %SPANTREE-2-ROOTGUARD_BLOCK: Root guard blocking port FastEthernet0/24 on VLAN0001.
*Mar  1 02:26:27.695: %LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan1, changed state to down

Pero si paramos el ataque o lanzamos un ataque distinto con Yersinia como podría ser NONDOS attack Claiming Other Role (5), automáticamente volvemos a recuperar la conexión o no se llegaría a bloquear:

*Mar  1 02:27:01.719: %SPANTREE-2-ROOTGUARD_UNBLOCK: Root guard unblocking port FastEthernet0/24 on VLAN0001   

Esta funcionalidad es interesante en los puertos troncales que conectan nuestro core con los equipos de acceso final, de forma que ningún switch de acceso pueda convertirse en la raíz del árbol, pero permitiendo que los switches de acceso participen en la topología.

bpdufilter

La última funcionalidad de la que hablaremos es bpdufilter, con la que conseguimos dejar de transmitir o recibir BPDU por el puerto donde está conectado el equipo final, de forma que en la captura de tráfico ya no aparecerán BPDU de STP:

Switch(config)# interface  fastEthernet  0/24
Switch(config-if)# spanning-tree bpdufilter enable

Finalmente, si tenemos que aplicarlo a todos los puertos, podemos crearnos una macro para facilitarnos la tarea, donde podremos añadir nuevas medidas de seguridad adicionales en el futuro (como podría ser portsecurity):

Switch(config) macro name  ProtectL2
Enter macro commands one per line. End with the character '@'.
spanning-tree portfast
spanning-tree bpduguard enable

@

Switch# show  parser macro name ProtectL2
Macro name : ProtectL2
Macro type : customizable
spanning-tree portfast
spanning-tree bpduguard enable

Switch(config)# interface  fastEthernet  0/24
Switch(config-if)# macro  apply ProtectL2

y comprobamos que está aplicada correctamente:

Switch# show  parser  macro  description
Interface    Macro Description(s)
--------------------------------------------------------------
Fa0/24       ProtectSTP
--------------------------------------------------------------

Siempre que apliquemos medidas de seguridad debemos probarlas previamente en un entorno controlado, conocer las diferencias entre aplicar una medida a nivel de interfaz o a nivel global, las diferencias en aplicarlo en un puerto de acceso o en un puerto troncal y por supuesto, tener claro el comportamiento deseado, ya que por ejemplo, si activamos bpdufilter, al no procesar tramas BPDU, podríamos crear un bucle en la red o por otra parte, si configuramos en una misma interfaz bpduguard y bpdufilter, este último tiene preferencia ya que filtrará las tramas BPDU y bpduguard no actuaría.

Espero que estas medidas de seguridad os ayuden a continuar avanzando en una red más eficiente y segura.