是否有一个合理的方法来build立基于捕获的数据包的SSL密码使用统计信息?
假设我的Web服务器支持一组密码,我想知道有多less客户端协商每个密码套件。
是的 。 如果您已经捕获了数据包 ,只需从Server Hello握手数据包中提取协商的密码即可:
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.
数据包本身可以很容易地识别,选定的密码在其中的一个设置位置,很容易parsing。 因此,捕获所有SSL连接的前几个数据包,提取所选的密码,然后获得所需的数据。
这个想法很有趣,我决定尝试一下。 随着一些黑客和削减我能够适应一个Python脚本来做到这一点:
$ ./parser.py random2.pcap | sort -u TLS 1.0 0x00,0x14 TLS 1.2 0x00,0x2f TLS 1.2 0x00,0x30 $
通过这些信息,您可以将密码套件ID与IANA的TLS密码套件registry相关联:
$ ./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] $
这是代码。 这是一个真正的TLS客户端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)
如果您的目标是找出您的Web服务器客户端使用的密码套件,则可能会有更简单的方法。
例如,Nginx的ssl模块有几个variables,比如$ssl_cipher和$ssl_protocol , 你也 可以login :
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
(顺便说一下,HTTPstream量也使用这种日志格式是安全的,sslvariables会显示为- 。)