2015/01/22

Entre POODLE y legacy

En esta oportunidad relataré una experiencia de varios meses de tediosa investigación finalizada abruptamente con la aparición de POODLE.

Como siempre, al tratarse de una historia verídica con información potencialmente sensible, hay un cierto enmascaramiento y falta a la verdad en los detalles. Sí es conceptualmente cierta.

Mi problemática


Tenía un servidor con SSLv3 y TLS v1.0 y en la agenda a mediano plazo eliminar SSLv3, tranquilo. Había hecho el análisis de user-agents para ver como impactaría en el tráfico y encontré que un 2% no soportaba TLS y 8% no podía saber.

Luego examiné un log que para cada conexión me dice si se utilizó SSL o TLS y me dió 99.98% SSL. Evidentemente había algún problema de configuración, así que RTFM y a corregir.

Cambié el orden de los cipher y pasó a 93% TLS, bastante bueno, pero yo esperaba menos de 3%.

Correlacioné el log de SSL/TLS con el de la aplicación para hallar el User-Agent responsable, que esperaba fuera IE 6 o inferior pero no encontré correlación.

Pensé que no habían suficientes ciphersuites, pero no podía activar nuevas por problemas de legacy, así que consideré reactivar ciphersuites TLS con short keys.


Conocimientos útiles previos.

El protocolo SSL/TLS dicta que el cliente ofrece ciphersuites y el servidor elige la que le gusta.


Una ciphersuite es un conjunto de protocolos para establecer y utilizar una conexión segura.

Primero el protocolo de autenticación que por lo general es del servidor pero tambien puede ser del cliente.

Luego el de intercambio de una clave simétrica que se usa en combinación con el protocolo de encriptación y por último el de autenticación de mensajes, pues que algo esté encriptado no significa que no pueda ser alterado por un atacante.

 

¿Qué es POODLE?


Es un ataque relacionado con el padding que son los bits que se ponen al final para hacer que los mensajes tengan una cantidad entera de bloques de encriptación. Mejor descripción que [1] no he hallado.

Pero si yo tengo y prefiero TLS en el servidor, no hay problema, sólo para los antediluvianos clientes que sólo soporten SSL, ¿no?

Pues no. Lo único que tiene que hacer un atacante es romper algunos de los paquetes para que se renegocie automáticamente a SSL.


¿Cuál es el problema con TLS export (short keys)?

Cuando se consideraba al cifrado de datos "munición de guerra", el gobierno de EEUU prohibió que se exportaran protocolos con demasiada fortaleza. Las leyes han cambiado y la capacidad de ataque tambien, así que por un lado los protocolos se usan indistintamente en todo el mundo y las longitudes inferiores a 96 no son consideradas seguras.


Comparando SSL con POODLE vs TLS con 56 bit keys


He preguntado en algunas listas y a algunas personas que es peor: SSL con POODLE o TLS con keys de 56 bits

Las respuestas que he recibido en general no han sido útiles, pero una persona de una lista de criptografía opinó que frente a un contrincante fuerte como una agencia de inteligencia da lo mismo, no así con criminales comunes, en cuyo caso optaría por TLS débil [2].

Luego pensé que en realidad es peor TLS débil, pues para hacer POODLE es necesario MITM, generar tráfico y hasta podría ser detectable, aunque el costo
sea inferior. Para romper TLS débil alcanza con capturar el tráfico y machacarlo, puede llevar más tiempo pero termina siendo más sencillo.

Con el primero se obtiene la cookie de sesión de valor efímero y con el segundo la clave, mucho más valiosa.

Si el tiempo del segundo ataque es de N días, habría que forzar rotación de contraseñas cada N - 1 días.

Para ratificar o rectificar esta incertidumbre, habría que efectuar ambos ataques y medir, lo cual está fuera de mis capacidades actuales. Si espero a efectuar el experimento, no sé cuando publicaré esta nota y cuanto más tiempo pase menos útil será, así en el momento en que lo haga lo agregaré en otra entrada. Como siempre, lo perfecto es enemigo de lo bueno.

Lo mejorcito que hallé es un estudio que afirma que para 40 bits se puede hacer el ataque en tres días [3].

Analizando el tráfico


Paralelamente, me interesaba conocer el motivo de tanto tráfico SSL, así que recurrí a mirar las negociaciones de protocolos.


El tráfico se captura con algo como

sudo /usr/sbin/tcpdump -i eth0 -p -s 0 -w captura.pcap "tcp port 443"


luego, con

tshark -r captura.pcap -n -V | less

se puede ver la disección. Lo que hay que buscar es donde dice

Secure Socket Layer
    SSL Record Layer: Handshake Protocol: Client Hello
        ...
        Handshake Protocol: Client Hello
            ...
            Cipher Suites (73 suites)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)

                   .....

y luego

Secure Socket Layer
    TLSv1 Record Layer: Handshake Protocol: Server Hello
        ...
        Handshake Protocol: Server Hello
            ...
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)




Se puede extraer con:

 tshark -r captura.pcap -n -V | awk '/Handshake Protocol.*Hello$/ {print $0} /Cipher Suite:/ {print $0}'


Es un buen ejercicio usando los encabezados [4] analizar y correlacionar la salida de los siguientes comandos:

hexdump -C captura.pcap

00000000  0a 0d 0d 0a 6c 00 00 00  4d 3c 2b 1a 01 00 00 00  |....l...M<+.....|
00000010  ff ff ff ff ff ff ff ff  03 00 17 00 4c 69 6e 75  |............Linu|
00000020  78 20 33 2e 31 33 2e 30  2d 32 34 2d 67 65 6e 65  |x 3.13.0-24-gene|
00000030  72 69 63 00 04 00 29 00  44 75 6d 70 63 61 70 20  |ric...).Dumpcap |
00000040  31 2e 31 30 2e 36 20 28  76 31 2e 31 30 2e 36 20  |1.10.6 (v1.10.6 |
00000050  66 72 6f 6d 20 6d 61 73  74 65 72 2d 31 2e 31 30  |from master-1.10|
00000060  29 00 00 00 00 00 00 00  6c 00 00 00 01 00 00 00  |).......l.......|
00000070  58 00 00 00 71 00 00 00  ff ff 00 00 02 00 03 00  |X...q...........|
00000080  61 6e 79 00 09 00 01 00  06 00 00 00 0b 00 0e 00  |any.............|
00000090  00 74 63 70 20 70 6f 72  74 20 34 34 33 20 00 00  |.tcp port 443 ..|
000000a0  0c 00 17 00 4c 69 6e 75  78 20 33 2e 31 33 2e 30  |....Linux 3.13.0|
000000b0  2d 32 34 2d 67 65 6e 65  72 69 63 00 00 00 00 00  |-24-generic.....|
000000c0  58 00 00 00 06 00 00 00  6c 00 00 00 00 00 00 00  |X.......l.......|
000000d0  20 0d 05 00 64 da 8a 8a  4c 00 00 00 4c 00 00 00  | ...d...L...L...|
000000e0  00 00 03 04 00 06 00 00  00 00 00 00 00 00 08 00  |................|
000000f0  45 00 00 3c 0d ed 40 00  40 06 a8 b2 c0 a8 01 66  |E..<..@.@......f|
00000100  c0 a8 01 66 da 37 01 bb  cb 46 91 ac 00 00 00 00  |...f.7...F......|
00000110  a0 02 aa aa 84 4b 00 00  02 04 ff d7 04 02 08 0a  |.....K..........|
00000120  00 44 9c 41 00 00 00 00  01 03 03 07 6c 00 00 00  |.D.A........l...|
00000130  06 00 00 00 6c 00 00 00  00 00 00 00 20 0d 05 00  |....l....... ...|
00000140  7f da 8a 8a 4c 00 00 00  4c 00 00 00 00 00 03 04  |....L...L.......|
00000150  00 06 00 00 00 00 00 00  00 00 08 00 45 00 00 3c  |............E..<|
00000160  00 00 40 00 40 06 b6 9f  c0 a8 01 66 c0 a8 01 66  |..@.@......f...f|
00000170  01 bb da 37 96 47 33 e9  cb 46 91 ad a0 12 aa aa  |...7.G3..F......|
00000180  84 4b 00 00 02 04 ff d7  04 02 08 0a 00 44 9c 41  |.K...........D.A|
00000190  00 44 9c 41 01 03 03 07  6c 00 00 00 06 00 00 00  |.D.A....l.......|
000001a0  64 00 00 00 00 00 00 00  20 0d 05 00 a4 da 8a 8a  |d....... .......|
000001b0  44 00 00 00 44 00 00 00  00 00 03 04 00 06 00 00  |D...D...........|
000001c0  00 00 00 00 00 00 08 00  45 00 00 34 0d ee 40 00  |........E..4..@.|
000001d0  40 06 a8 b9 c0 a8 01 66  c0 a8 01 66 da 37 01 bb  |@......f...f.7..|
000001e0  cb 46 91 ad 96 47 33 ea  80 10 01 56 84 43 00 00  |.F...G3....V.C..|
000001f0  01 01 08 0a 00 44 9c 41  00 44 9c 41 64 00 00 00  |.....D.A.D.Ad...|
00000200  06 00 00 00 98 01 00 00  00 00 00 00 20 0d 05 00  |............ ...|




tcpdump -r captura.pcap -n -XX


23:44:58.023524 IP 192.168.1.102.55863 > 192.168.1.102.443: Flags [S], seq 3410399660, win 43690, options [mss 65495,sackOK,TS val 4496449 ecr 0,nop,wscale 7], length 0
    0x0000:  0000 0304 0006 0000 0000 0000 0000 0800
  ................
    0x0010:  4500 003c 0ded 4000 4006 a8b2 c0a8 0166  E..<..@.@......f
    0x0020:  c0a8 0166 da37 01bb cb46 91ac 0000 0000  ...f.7...F......
    0x0030:  a002 aaaa 844b 0000 0204 ffd7 0402 080a  .....K..........
    0x0040:  0044 9c41 0000 0000 0103 0307            .D.A........
23:44:58.023551 IP 192.168.1.102.443 > 192.168.1.102.55863: Flags [S.], seq 2521248745, ack 3410399661, win 43690, options [mss 65495,sackOK,TS val 4496449 ecr 4496449,nop,wscale 7], length 0
    0x0000:  0000 0304 0006 0000 0000 0000 0000 0800  ................
    0x0010:  4500 003c 0000 4000 4006 b69f c0a8 0166  E..<..@.@......f
    0x0020:  c0a8 0166 01bb da37 9647 33e9 cb46 91ad  ...f...7.G3..F..
    0x0030:  a012 aaaa 844b 0000 0204 ffd7 0402 080a  .....K..........
    0x0040:  0044 9c41 0044 9c41 0103 0307            .D.A.D.A....
23:44:58.023588 IP 192.168.1.102.55863 > 192.168.1.102.443: Flags [.], ack 1, win 342, options [nop,nop,TS val 4496449 ecr 4496449], length 0
    0x0000:  0000 0304 0006 0000 0000 0000 0000 0800  ................
    0x0010:  4500 0034 0dee 4000 4006 a8b9 c0a8 0166  E..4..@.@......f
    0x0020:  c0a8 0166 da37 01bb cb46 91ad 9647 33ea  ...f.7...F...G3.
    0x0030:  8010 0156 8443 0000 0101 080a 0044 9c41  ...V.C.......D.A
    0x0040:  0044 9c41                                .D.A
23:44:58.023843 IP 192.168.1.102.55863 > 192.168.1.102.443: Flags [P.], seq 1:306, ack 1, win 342, options [nop,nop,TS val 4496449 ecr 4496449], length 305
    0x0000:  0000 0304 0006 0000 0000 0000 0000 0800  ................
    0x0010:  4500 0165 0def 4000 4006 a787 c0
a8 0166  E..e..@.@......f
    0x0020:  c0a8 0166 da37 01bb cb46 91ad 9647 33ea  ...f.7...F...G3.
    0x0030:  8018 0156 8574 0000 0101 080a 0044 9c41  ...V.t.......D.A
    0x0040:  0044 9c41 1603 0101 2c01 0001 2803 0371  .D.A....,...(..q
    0x0050:  9c5b 33b0 0b86 f866 2a59 e3a2 5be3 a625  .[3....f*Y..[..%
    0x0060:  3974 024f 5d2d 45b7 6794 82b8 1c16 e400  9t.O]-E.g.......
    0x0070:  0092 c030 c02c c028 c024 c014 c00a 00a3  ...0.,.(.$......
    0x0080:  009f 006b 006a 0039 0038 0088 0087 c032  ...k.j.9.8.....2
    0x0090:  c02e c02a c026 c00f c005 009d 003d 0035  ...*.&.......=.5
    0x00a0:  0084 c012 c008 0016 0013 c00d c003 000a  ................
    0x00b0:  c02f c02b c027 c023 c013 c009 00a2 009e  ./.+.'.#........
    0x00c0:  0067 0040 0033 0032 009a 0099 0045 0044  .g.@.3.2.....E.D
    0x00d0:  c031 c02d c029 c025 c00e c004 009c 003c  .1.-.).%.......<
    0x00e0:  002f 0096 0041 c011 c007 c00c c002 0005  ./...A..........
    0x00f0:  0004 0015 0012 0009 0014 0011 0008 0006  ................
    0x0100:  0003 00ff 0100 006d 000b 0004 0300 0102  .......m........
    0x0110:  000a 0034 0032 000e 000d 0019 000b 000c  ...4.2..........
    0x0120:  0018 0009 000a 0016 0017 0008 0006 0007  ................
    0x0130:  0014 0015 0004 0005 0012 0013 0001 0002  ................
    0x0140:  0003 000f 0010 0011 0023 0000 000d 0020  .........#......
    0x0150:  001e 0601 0602 0603 0501 0502 0503 0401  ................
    0x0160:  0402 0403 0301 0302 0303 0201 0202 0203  ................
    0x0170:  000f 0001 01 

    

tshark -r captura.pcap -n -V

Frame 1: 76 bytes on wire (608 bits), 76 bytes captured (608 bits) on interface 0
    Interface id: 0
    Encapsulation type: Linux cooked-mode capture (25)
    Arrival Time: Jan 20, 2015 23:44:58.023524000 ART
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1421808298.023524000 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 76 bytes (608 bits)
    Capture Length: 76 bytes (608 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: sll:ip:tcp]
Linux cooked capture
    Packet type: Unicast to us (0)
    Link-layer address type: 772
    Link-layer address length: 6
    Source: 00:00:00:00:00:00 (00:00:00:00:00:00)
    Protocol: IP (0x0800)
Internet Protocol Version 4, Src: 192.168.1.102 (192.168.1.102), Dst: 192.168.1.102 (192.168.1.102)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
    Total Length: 60
    Identification: 0x0ded (3565)
    Flags: 0x02 (Don't Fragment)
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (6)
    Header checksum: 0xa8b2 [validation disabled]
        [Good: False]
        [Bad: False]
    Source: 192.168.1.102 (192.168.1.102)
    Destination: 192.168.1.102 (192.168.1.102)
    [Source GeoIP: Unknown]
    [Destination GeoIP: Unknown]
Transmission Control Protocol, Src Port: 55863 (55863), Dst Port: 443 (443), Seq: 0, Len: 0
    Source port: 55863 (55863)
    Destination port: 443 (443)
    [Stream index: 0]
    Sequence number: 0    (relative sequence number)
    Header length: 40 bytes
    Flags: 0x002 (SYN)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Nonce: Not set
        .... 0... .... = Congestion Window Reduced (CWR): Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...0 .... = Acknowledgment: Not set
        .... .... 0... = Push: Not set
        .... .... .0.. = Reset: Not set
        .... .... ..1. = Syn: Set
            [Expert Info (Chat/Sequence): Connection establish request (SYN): server port 443]
                [Message: Connection establish request (SYN): server port 443]
                [Severity level: Chat]
                [Group: Sequence]
        .... .... ...0 = Fin: Not set
    Window size value: 43690
    [Calculated window size: 43690]
    Checksum: 0x844b [validation disabled]
        [Good Checksum: False]
        [Bad Checksum: False]
    Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
        Maximum segment size: 65495 bytes
            Kind: MSS size (2)
            Length: 4
            MSS Value: 65495
        TCP SACK Permitted Option: True
            Kind: SACK Permission (4)
            Length: 2
        Timestamps: TSval 4496449, TSecr 0
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 4496449
            Timestamp echo reply: 0
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        Window scale: 7 (multiply by 128)
            Kind: Window Scale (3)
            Length: 3
            Shift count: 7
            [Multiplier: 128]



Vas mirando las tres salidas y los encabezados y con una paciencia inhumana identificás cada parte.

Te propongo como ejercicio que hagas tu captura y analices las tres salidas simultáneamente junto a la documentación. Con suma gentileza te he marcado 0800 que indica que es un frame ethernet, 4 que indica que es IP y el 6 que es TCP. Paciencia, despues de un rato parece menos imposible.


Hacer esto te sirve tanto para comprender mucho los protocolos y luego al leer las explicaciones de las vulnerabilidades, como Heartbleed, te sentís en territorio no tan hostil. De últimas para alardear diciendo a tus amigos "mirá, hay están los mensajes TLS".

Como tshark no tiene la opción de "follow TCP stream", lo anterior sólo sirve como prueba de concepto y estudio pues con tráfico real se te puede llegar a mezclar con otras comunicaciones si no ajustás bien los filtros. Usar la GUI de wireshark se complica para quienes sólo tienen terminal y por que obligaría a analizar manualmente cada stream.


Analizando User-Agent

 

Lamentablemente no puedo compartir el código, pero si la idea general.

Primero hay que extraer del log de la aplicación los User-Agents, eso se hace con grep/cut/sed/awk, lo que más te guste.


A continuación, para cada entrada
    parsear()
    corregir()
    graduar()
    printf("%s;%s;%s;.....\n",$r->security->tls10, $r->security->tls11,....

La parte de parsear() significa que hay que normalizar, pues hay muchos User-Agents que son equivalentes. Eso se hace con ua-parser [5] y devuelve un objeto con datos como ua->family, ua->major, os->family, os->major, os->minor

corregir() toma la ua->family y hace que "Chrome Mobile", "Chrome Mobile iOS" sea "Chrome" y "Iceweasel" sea "Firefox"

graduar() toma los datos de parseados y corregidos y devuelve un objeto o estructura con varios atributos:

class Security {
    public $group;
    public $tls10;
    public $tls11;
    public $tls12;
    public $msg;

    public function Security($group='?', $tls10='?', $tls11='?', $tls12='?', $msg='') {
        $this->group = $group;
        $this->tls10 = $tls10;
        $this->tls11 = $tls11;
        $this->tls12 = $tls12;
        $this->msg   = $msg;
    }
}


por ejemplo:

'Firefox 23', 'Yes','Disabled','No'

según la lógica que se deduce de la tabla de navegadores [6]. Un fragmento de la lógica de ejemplo:

switch ($r->ua->family) {
  case 'Chrome':
    if ($r->ua->major<=21) {
      $r->security = new Security('Chrome 0-21','Yes','No','No');
...
    } else {
      $r->security = new Security('Chrome 30-','Yes','Yes','Yes');
    }
  break;
  case 'Firefox':
...
  case 'IE':
    if ($r->ua->major==6) {
      $r->security = new Security('IE 6', 'Disabled','No','No');
      return;
    }
    if ($r->os->family=='Windows XP') {
      if ($r->ua->major >= 7 && $r->ua->major <= 8) {
        $r->security = new Security('IE 7-8 Windows XP','Yes','No','No');
        return;
      }
      $r->security=new Security('IE '.$r->ua->major.'Win XP','???','???','???');
      return;
    }
    if ($r->os->family=='Windows Vista') {
....
      return;
    }
....
    $r->security = new Security(
      'IE Desconocido ' . $r->os->family,
      '???',
      '???',
      '???'
    );
  break;
  default:
....
    if (preg_match ('/mobile\/Android4/',$r->originalUserAgent)) {
      $r->security=new Security(
        'Mobile Android 4.x',
        'Yes?','Yes?','Yes?'
      );
      return;
    }
....
  break;
}    

No recuerdo la diferencia entre el '?' que da el constructor por default y '???' me parece que tiene que ver con si lo que ignoro es que User-Agent es o si ese User-Agent soporta el protocolo.

Y por último, más magia de cut/sort/uniq o lo que te guste y podrá obtener tus estadísticas.

Referencias

[1] https://nakedsecurity.sophos.com/2014/10/16/poodle-attack-takes-bytes-out-of-your-data-heres-what-to-do/

[2] "Either way, you're screwed, especially if your adversary is the NSA or similar agency with comparable resources. All other things being equal and not knowing any specific details, I'd probably go with the 56 bit keys as that is more likely to protect you from the common criminal element (e.g., organized crime) IMO. Got to figure POODLE attacks are automated and take less resources than brute forcing 56 bit keys."

[3] https://www.os3.nl/_media/2013-2014/courses/rp2/p56_report.pdf

[4] Links útiles

http://en.wikipedia.org/wiki/Ethernet_frame#Ethernet_II
http://en.wikipedia.org/wiki/IPv4#Packet_structure
http://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_record
http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
http://wiki.wireshark.org/Development/PcapNg?action=AttachFile&do=view&target=ntartest.c

[5] https://github.com/tobie/ua-parser

[6] http://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers