Verificación de hola del cliente para la clasificación https

7

Necesito detectar paquetes https en el tráfico de red. Hasta ahora estaba marcando todos los "443" como https pero ya no quiero usar la información del puerto para estos.

¿Será suficiente revisar el mensaje de saludo del cliente como:

//Check 22 and version info 0300 0301 or 0302
if (packet->payload[0] == 0x16 && packet->payload[1] == 0x03
  && (packet->payload[2] == 0x00 || packet->payload[2] == 0x01 || packet->payload[2] == 0x02)

{
    int temp = ntohs(get_u16(packet->payload, 3)) + 5;//Get lenght 
//Check lenght is valid and 6th byte is client hello(which is 1)
    if (temp < packet->payload_length && temp > 50 && packet->payload[5]) == 1) 
        MARK AS HTTPS 
}

Debido al diseño de mi proyecto, no puedo verificar más de un paquete. ¿Puede por favor avisar si simplemente verificando el cliente como está arriba está bien o no?

    
pregunta Kadir Erdem Demir 24.04.2013 - 15:58
fuente

3 respuestas

12

En SSL / TLS , los mensajes se envían como parte de los registros . Lo que se debe esperar es que el cliente envíe primero un mensaje ClientHello que está contenido en uno o varios registros.

El formato de grabación es:

record type: 1 byte (0x16 for "records contains some handshake message data")
protocol version: 2 bytes (0x03 0x00 for SSL 3.0, 0x03 0x01 for TLS 1.0, and so on)
record length: 2 bytes (big endian)
then the record data...

Para el primer registro (de cliente a servidor), el cliente primero enviará un mensaje ClientHello que es un tipo de mensaje de intercambio, por lo tanto, se encapsula en un registro como se muestra arriba (el primer byte del registro será 0x16 ). Teóricamente , el cliente puede enviar el ClientHello dividido en varios registros, y puede comenzar con uno o varios registros vacíos, pero esto no es muy probable. El mensaje ClientHello comienza con su propio encabezado de cuatro bytes, con un byte para el tipo de mensaje (0x01 para ClientHello ), luego la longitud del mensaje sobre tres bytes (nuevamente, big-endian).

Una vez que el cliente haya enviado su ClientHello , espera una respuesta del servidor, por lo que ClientHello estará solo en su registro.

Por lo que podría esperar una carga útil que comience con los siguientes 9 bytes:

0x16 0x03 X Y Z 0x01 A B C

con:

  • X será 0, 1, 2, 3 ... o más , dependiendo de la versión de protocolo utilizada por el cliente para este primer mensaje. Actualmente , las versiones de SSL / TLS definidas son SSL 3.0 , TLS 1.0 , TLS 1.1 y TLS 1.2 . Otras versiones pueden ser definidas en el futuro. Ellos probablemente usarán el esquema de numeración 3. X , por lo que puede esperar que el segundo byte de encabezado permanezca en 0x03, pero no debe limitar arbitrariamente el tercer byte.

  • Y Z es la codificación de la longitud del registro; A B C es la codificación de la longitud del mensaje ClientHello . Como el mensaje ClientHello comienza con un encabezado de 4 bytes (no incluido en su longitud) y se supone que está solo en su registro, debe tener: A = 0 y 256 * X + Y = 256 * B + C + 4 .

Si ve 9 bytes, que verifican estas condiciones, es probable que esto sea un ClientHello de un cliente SSL.

Algunos clientes SSL no muy recientes también pueden admitir una versión de protocolo más antigua, llamada SSL 2.0. Estos clientes emitirán un ClientHello que sigue las reglas de SSL 2.0, donde los mensajes y registros se fusionan de alguna manera. Ese mensaje SSL 2.0 ClientHello indicará que el cliente también conoce SSL 3.0 o más reciente, pero no comenzará con la secuencia de 9 bytes explicada anteriormente.

La estructura de

SSL 2.0 ClientHello se explica en apéndice E.2 o RFC 5246 . Aunque estos clientes son raros (hay un RFC sobre la prohibición total de la compatibilidad con SSL 2.0), todavía hay muchos implementados ahí fuera.

Tu código tiene algunos problemas:

  • No detecta un mensaje SSL 2.0 ClientHello .
  • Comprueba que el tercer byte del encabezado ( X en mi descripción anterior) es igual a 0, 1 o 2, lo que descarta TLS 1.2. Esto es demasiado restrictivo.
  • Supone que todo ClientHello estará en un solo registro (lo que es una suposición razonable) y que este ClientHello se codificará en un solo paquete (que es una suposición mucho menos razonable).
  • No intenta ver la longitud en el mensaje de saludo y lo corrobora con la longitud del registro.

Correspondientemente, eludir la detección será fácil (al usar un SSL 2.0 ClientHello , al usar un registro etiquetado con la versión TLS 1.2, al hacer un gran mensaje ClientHello que no cabe en un solo paquete ... los métodos son numerosos); y algunos clientes implementados existentes no serán detectados: no solo uno puede evitar la detección a propósito , sino que también es posible sin querer .

    
respondido por el Tom Leek 24.04.2013 - 16:33
fuente
1
  

Debido al diseño de mi proyecto, no puedo verificar más de un paquete. ¿Puede por favor avisar si solo está comprobando si el cliente es correcto o no?

Si no espera que el cliente evite su detección, podría ser suficiente verificar los bytes típicos al principio del cliente, hola dentro del primer paquete que reciba. Pero, si usara esto para bloquear el tráfico https pero permitiera cualquier otra cosa, sería fácil eludir su detección distribuyendo los primeros bytes del cliente a través de múltiples paquetes TCP. Esto es posible porque https usa TCP como el protocolo subyacente y TCP es un transporte continuo que no se preocupa por los límites de los paquetes.

Tenga en cuenta también que hay algunas aplicaciones que tratan de parecerse al tráfico https para engañar a los cortafuegos y dejarlos pasar. Un ejemplo típico es Skype cuando intenta hacer un túnel a través de un proxy HTTP (s).

Además, realmente no comprueba si hay https, sino solo SSL. HTTPS es HTTP dentro de un túnel SSL, pero no puede detectar si el protocolo en el túnel es realmente HTTP u otro protocolo como IMAP, POP, SMTP, etc.

    
respondido por el Steffen Ullrich 20.10.2014 - 22:32
fuente
0

Tom tu respuesta es muy detallada y útil. Estoy muy agradecido . Consideré puntos y traté de mejorar mi implementación. Porque es un poco grande, estoy escribiendo como una nueva respuesta. Se hizo un poco largo, no espero que nadie lo analice, pero si tal vez alguien lo necesita, puede ser útil.

if (flow_special_packet_counter == 0)
{
    //SSLv2 no server name extension I don't have to mark it now I will wait for server hello 
    if (pkt->pllen >= 27 && pkt->pl[2] == 0x01 && pkt->pl[3] == 0x03
    && (pkt->pl[4] == 0x00 || pkt->pl[4] == 0x01 || pkt->pl[4] == 0x02 || pkt->pl[4] == 0x03)
    && (pkt->pllen - pkt->pl[1]) == 2)
    // SSLv2 Record
    {
        flow_special_packet_counter++;
        return;
    }
    //SSLv3 client hello is important for me I will try to mark it if only package lenght is bigger I will wait for server hello 
    else if (pkt->pllen >= 47 && pkt->pl[0] == 0x16 && pkt->pl[1] == 0x03
      && (pkt->pl[2] == 0x00 || pkt->pl[2] == 0x01 || pkt->pl[2] == 0x02 || pkt->pl[2] == 0x03 ))
    // SSLv3 Record
    {
        if (pkt->pl[5] != 0x02)//No client hello 
             return;

        unsigned short sslv3ClientHelloLength = ntohs(getU16n2h(pkt->pl[3]));
        if (sslv3ClientHelloLength > (pkt->pllen - 5))//client hello bigger than payload than wait for second 
        {
            flow_special_packet_counter++;  
            return;
        }
        else 
        {
            if((pkt->pllen - sslv3ClientHelloLength) == 5)
               MARKS AS HTTPS return;
            else 
               return;
        }

    }
    else if (flow_special_packet_counter == 0 && flow_pktcount > 10) //Enough checking this flow is not https 
    {
        NEVER HTTPS return; 
    }
}
else if (flow_special_packet_counter == 1)
{
    if (flow_pktcount > 20)
    NEVER HTTPS return;
    if (pkt->pllen >= 47 && pkt->pl[0] == 0x16 && pkt->pl[1] == 0x03
      && (pkt->pl[2] == 0x00 || pkt->pl[2] == 0x01 || pkt->pl[2] == 0x02 || pkt->pl[2] == 0x03 && pkt->pl[5] == 0x02))
      {
            MARKS AS HTTPS return;//Double records been check I think that is enough now time for testing :) 
      }  
}
    
respondido por el Kadir Erdem Demir 25.04.2013 - 15:46
fuente

Lea otras preguntas en las etiquetas