Estatísticas de uso do pacote de criptografia SSL com base nos dados capturados

1

Existe um método razoável de construir estatísticas de uso de criptografia SSL com base em pacotes capturados?

Digamos que meu servidor da web suporte um conjunto de cifras e gostaria de descobrir quantos clientes negociam cada conjunto de criptografia.

    
por Mike 27.03.2015 / 18:53

2 respostas

5

Sim . Se você tiver pacotes capturados , basta extrair a cifra negociada do Server Hello pacote de handshake :

cipher_suite

  The single cipher suite selected by the server from the list in
  ClientHello.cipher_suites.  For resumed sessions, this field is
  the value from the state of the session being resumed.

O pacote em si pode ser facilmente identificado, e a cifra selecionada está em um local definido, fácil de analisar. Portanto, capture os primeiros pacotes de todas as suas conexões SSL, extraia a cifra escolhida e você terá o que está procurando.

A ideia foi interessante o suficiente para que eu decidisse tentar. Com um pouco de hacking e slashing, consegui adaptar um script Python para fazer isso:

$ ./parser.py random2.pcap | sort -u
TLS 1.0 0x00,0x14
TLS 1.2 0x00,0x2f
TLS 1.2 0x00,0x30
$

Com essa informação, você pode correlacionar as IDs do conjunto de criptografia com os Registro do Conjunto de Cifras TLS da IANA:

$ ./parser.py random2.pcap  | sort -u | awk '{print $3}' | grep -if - ~/Downloads/tls-parameters-4.csv 
"0x00,0x14",TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,[RFC4346]
"0x00,0x2F",TLS_RSA_WITH_AES_128_CBC_SHA,Y,[RFC5246]
"0x00,0x30",TLS_DH_DSS_WITH_AES_128_CBC_SHA,Y,[RFC5246]
$ 

Aqui está o código. É uma verdadeira desmontagem de TLS Client Hello Tools então se você quiser brincar com ele, considere ir de volta para lá para uma versão menos drástica (e tenha em mente que o original foca no Client Hello enquanto nos importamos com o Server Hello).

#!/usr/bin/env python
# Hack-and-slash derived from https://github.com/pquerna/tls-client-hello-stats

import os, sys, dpkt
TLS_HANDSHAKE = 22

def pcap_reader(fp):
    return dpkt.pcap.Reader(fp)

def grab_negotiated_ciphers(cap):
    for ts, buf in cap:
        eth = dpkt.ethernet.Ethernet(buf)
        if not isinstance(eth.data, dpkt.ip.IP):
            continue
        ip = eth.data
        if not isinstance(ip.data, dpkt.tcp.TCP):
            continue

        tcp = ip.data
        if (tcp.dport != 443 and tcp.sport != 443) or (len(tcp.data) <= 0) or (ord(tcp.data[0]) != TLS_HANDSHAKE):
            continue

        records = []
        try:
            records, bytes_used = dpkt.ssl.TLSMultiFactory(tcp.data)
        except dpkt.ssl.SSL3Exception, e:
            continue
        except dpkt.dpkt.NeedData, e:
            continue

        if len(records) <= 0:
            continue

        for record in records:
            # TLS handshake only
            if (record.type == 22 and len(record.data) != 0 and ord(record.data[0]) == 2):
                try:
                    handshake = dpkt.ssl.TLSHandshake(record.data)
                except dpkt.dpkt.NeedData, e:
                    continue
                if isinstance(handshake.data, dpkt.ssl.TLSServerHello):
                    ch = handshake.data
                    print '%s\t0x%0.2x,0x%0.2x' %(dpkt.ssl.ssl3_versions_str[ch.version], (ch.cipher_suite&0xff00)>>8, ch.cipher_suite&0xff)
                else:
                    continue

def main(argv):
    if len(argv) != 2:
        print "Tool to grab and print TLS Server Hello cipher_suite"
        print ""
        print "Usage: parser.py <pcap file>"
        print ""
        sys.exit(1)

    with open(argv[1], 'rb') as fp:
        capture = pcap_reader(fp)
        stats = grab_negotiated_ciphers(capture)

if __name__ == "__main__":
    main(sys.argv)
    
por 27.03.2015 / 20:06
2

Se o seu objetivo é descobrir quais conjuntos de criptografia os clientes do seu servidor da Web estão usando, pode haver métodos mais fáceis.

Por exemplo, o módulo ssl do Nginx tem diversas variáveis como $ssl_cipher e $ssl_protocol , que você pode também registro :

log_format ssl '$remote_addr - $remote_user [$time_local] "$request" $status '
               '$body_bytes_sent "$http_referer" "$http_user_agent" '
               '$ssl_protocol $ssl_cipher';

access_log /var/log/nginx/ssl.log ssl;
2001:db8::1 - - [27/Mar/2015:21:11:04 +0000] "GET /index.html HTTP/1.1" 200
12345 "-" "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0"
TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256

(A propósito, é seguro usar esse formato de log para o tráfego HTTP também. As variáveis ssl serão mostradas como - .)

    
por 27.03.2015 / 22:08