IDS Snort regla para atrapar a Slow-Loris

1

Estoy tratando de escribir una regla para atrapar un ataque de Slow-Loris, esto es lo que tengo -

alert tcp any any -> any any (msg:"Possible Slow Loris attack"; classtype: denial-of-service; flow: to_server, established; pcre: !"/\x0D\x0A\x0D\x0A$/H"; threshold: type threshold, track by_dst, count 10, seconds 5; sid 3000009; rev:1;)

(Puede que haya confundido un poco la sintaxis, pero eso es porque al intentar formatearla aquí, estoy seguro de que la sintaxis está bien en mi extremo)

También intenté jugar con el RE un poco, probé "/\x0D\x0A$/H" y tampoco funcionó

El Slow-Loris que intenté escribirme y el Slow Loris que descargué desde algún lugar envían paquetes con encabezados HTTP "incompletos", por lo que no terminan con \r\n\r\n como un encabezado terminado. Pero no consigo capturar ninguno de los dos.

Miró los paquetes en Wireshark y terminaron con 0D 0A

Miré las reglas descargadas y la regla no está allí. Hizo cola para snort.conf y no hay errores allí. Si service nsm status vio, tal vez el servicio en sí no subió correctamente, pero todo es OK . EDITAR: faltaba : , lo arreglé y ahora aparece en las reglas descargadas. Sin embargo, todavía no queda atrapado

No estoy realmente seguro de lo que estoy haciendo mal, agradecería algo de ayuda.

    
pregunta GoodKingRene 27.11.2017 - 20:06
fuente

1 respuesta

2

Parece que hay un par de cosas en tu firma que no funcionarán:

  1. El uso de la opción /H en PCRE utiliza el preprocesador HTTP y dice que el contenido debe coincidir con el http_header . Cuando el preprocesador analiza una solicitud GET, |0d 0a 0d 0a| significa el final del encabezado; lo que significa que no puedes buscar eso dentro del encabezado.

  2. Cuando se usa flow o cualquier preprocesador HTTP, la secuencia de TCP se vuelve a ensamblar (de forma predeterminada, a menos que se especifique lo contrario). Esto significa que para hacer coincidir el contenido en el encabezado, todos los paquetes que conforman la solicitud HTTP deben observarse y la solicitud debe finalizar antes de que el preprocesador pueda analizar todas las partes que conforman la solicitud ( por ejemplo, http_method , http_uri , http_header ).

Honestamente, no estoy seguro de cuál sería el mejor método para escribir una firma para detectar esta actividad [genéricamente], simplemente porque se sale de los límites normales de lo que Snort está diseñado para detectar.

Sin embargo, lo que recomendaría en esta situación sería encontrar todas las herramientas disponibles públicamente para SlowLoris (comenzando con enlace : disponible para instalar a través de pip3), ejecútelos en un entorno de prueba y analice lo que realmente ocurre por cable.

Hice eso y este es el tráfico que genera:

GET /?1153 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0
Accept-language: en-US,en,q=0.5
X-a: 1350
X-a: 210
X-a: 518
X-a: 4622
X-a: 2951
X-a: 2666
X-a: 149
X-a: 1756
X-a: 4994
X-a: 2688

Esto sucede en varias conexiones hasta el número máximo de sockets especificados (150 de forma predeterminada). Cada conexión se mantendría activa con una solicitud HTTP GET incompleta al enviar un campo de encabezado X-a adicional de vez en cuando.

La forma en que escribiría una firma para detectar esta actividad sería:

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SlowLoris.py DoS attempt"; \
    flow:established,to_server,no_stream; content:"X-a:"; dsize:<15; \
    detection_filter:track by_dst, count 3, seconds 30; \
    classtype:denial-of-service; sid:1; rev:1; )

event_filter gen_id 1, sig_id 1, type limit, track by_src, count 1, seconds 5

Cosas importantes acerca de esta regla:

  1. Se agregó la opción no_stream a flow . Esto le dice al preprocesador Stream5 que no se moleste en verificar cómo se relaciona el contenido en el contexto de la secuencia reensamblada. Básicamente solo mira el paquete en sí. Importante al usar la opción dsize .
  2. Añadido dsize:<15 . Las líneas que contienen los encabezados X-a se envían en paquetes individuales. Observé un paquete típico para parecerse a:

    0000 58 2d 61 3a 20 32 36 38 38 0d 0a X-a: 2688..

    Con cuatro dígitos aleatorios para el valor, la longitud del contenido es de 11 bytes. Solo decidí decir <15 por si acaso.

  3. Se agregó detection_filter . Encuentro que una combinación de detection_filter en la regla combinada con un event_filter da un mejor control para la limitación de la tasa de alerta y el umbral. Las opciones detection_filter que especifiqué se aseguran de solo disparar alertas si 3 o más ocurren desde la misma fuente dentro de la ventana de 30 second.
  4. Se agregó un event_filter para limitar la cantidad de alertas que se activan una vez que se alcanza el detection_filter . Al limitar las alertas a 1 cada 5 segundos, las alertas seguirán siendo lo suficientemente locas como para informarle que algo está sucediendo sin inundarlo con alertas extrañas.

A continuación se muestra una salida de muestra de las pruebas en vivo con Snort v2.9.9.0 durante 3 minutos

SlowLoris.py

(Python3) λ slowloris -p 80 192.168.126.128
[05-12-2017 13:45:01] Attacking 192.168.126.128 with 150 sockets.
[05-12-2017 13:45:01] Creating sockets...
[05-12-2017 13:45:05] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:45:24] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:45:43] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:46:02] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:46:21] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:46:40] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:46:59] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:47:18] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:47:37] Sending keep-alive headers... Socket count: 7
[05-12-2017 13:47:56] Sending keep-alive headers... Socket count: 7
^C

Registro del servidor HTTP

user@host:~$ sudo python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?1061 HTTP/1.1" 200 -
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?524 HTTP/1.1" 200 -
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?1171 HTTP/1.1" 200 -
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?984 HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('192.168.126.1', 61831)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 290, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 318, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 654, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 713, in finish
    self.wfile.close()
  File "/usr/lib/python2.7/socket.py", line 283, in close
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 307, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?634 HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('192.168.126.1', 61832)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 290, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 318, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 654, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 713, in finish
    self.wfile.close()
  File "/usr/lib/python2.7/socket.py", line 283, in close
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 307, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?296 HTTP/1.1" 200 -
192.168.126.1 - - [05/Dec/2017 13:48:01] "GET /?640 HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('192.168.126.1', 61834)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 290, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 318, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 654, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 713, in finish
    self.wfile.close()
  File "/usr/lib/python2.7/socket.py", line 283, in close
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 307, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------

Snort Alerts

12/05-13:45:05.348446  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61831 -> 192.168.126.128:80
12/05-13:45:24.351347  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:45:43.355735  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:46:02.358688  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:46:21.363346  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:46:40.365834  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:46:59.369221  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:47:18.372293  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:47:37.374814  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80
12/05-13:47:56.378355  [**] [1:1:1] SlowLoris.py DoS attempt [**] [Priority: 0] {TCP} 192.168.126.1:61828 -> 192.168.126.128:80

Espero que esto ayude!

    
respondido por el Damian T. 05.12.2017 - 20:03
fuente

Lea otras preguntas en las etiquetas