本文中,我们将使用Bro入侵检测软件(IDS)作为客户端指纹探测技术工具。
众所周知,在最初的TLS握手过程(特别常用于浏览器中的HTTPS协议)中,会交换一条名为“ClientHello”的消息;在这条消息中,客户端列举了所支持的密码组件(即所谓的密码套件)。
例如,使用Wireshark协议解析软件来分析Linux系统中的Firefox50.1.0浏览器所发送的一条“ClientHello”消息,如下图所示。

有一些网站可以告诉我们所用浏览器的TLS协议特征,比如 Qualys SSL Labs SSL Client Test。
有趣的是,不同的TLS客户端往往使用不同的密码套件集合。比如,对于wget命令而言:
其握手数据报文(“ClientHello”消息)如下图所示。

如图可知,wget命令发送了68个不同的密码套件(而之前的Firefox浏览器发送了15个),而且两者的次序也不同。
因此,除了其他参数(比如同时存在于消息中的,所用的TLS协议版本),密码套件的数目及次序为我们提供了客户端的指纹。
Firefox浏览器和Chrome浏览器有不同的指纹;同样,Tor客户端(不用于断点续传)的指纹不同于Python脚本,微软WEB请求APIs,或者Delphi编程实现的RAT,等等。
事实上,我们可以利用其识别非授权程序,或者检测是否有恶意软件,为了操控或者窃密活动而潜伏伪装成用于组织内部的HTTPS浏览器。
走进Bro软件
要解析ClientHello消息并不是复杂的事情;可以使用p0f插件(参考文章:ac1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6A6k6r3g2S2i4K6u0W2M7r3!0H3j5$3!0#2L8Y4c8Q4x3X3g2G2M7X3N6Q4x3V1j5J5x3o6p5J5i4K6u0V1x3o6k6Q4x3X3b7I4y4#2)9J5k6s2y4K6L8q4)9J5k6r3k6A6L8X3N6W2M7Y4m8J5K9h3&6@1K9h3&6Y4i4K6u0V1k6X3!0J5i4K6u0V1M7o6m8X3i4K6u0r3)和专用工具比如FingerprintTLS(参考文章:8f9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2M7%4q4#2j5i4u0W2L8r3g2E0L8$3&6Q4x3X3g2U0L8$3#2Q4x3V1k6@1L8s2y4Q4x3X3c8X3K9h3&6Y4k6i4u0H3M7X3W2F1N6r3W2F1k6#2)9J5c8R3`.`.)。正如所料,Bro IDS软件也可以解析TLS协议;我们可以在文件/usr/local/bro/share/bro/base/protocols/ssl/consts.bro中找到所用的若干常量。
TLS协议版本幻数和对应的名字映射如下:
同样,在文件略微偏后的位置处,能看到不同的密码套件和cipher_desc数据结构:
如前文(网址:afaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2K6k6h3y4#2M7X3W2@1P5h3q4J5N6s2N6G2M7X3E0Q4x3X3g2W2M7#2)9J5c8U0t1H3x3e0N6Q4x3V1j5H3x3g2)9J5c8U0p5I4i4K6u0r3j5Y4u0G2i4K6u0V1K9h3c8K6i4K6u0V1N6r3W2H3M7#2)9J5k6r3q4F1k6q4)9J5k6s2c8J5K9h3y4C8M7#2)9J5c8W2!0q4c8W2!0n7b7#2)9^5z5g2!0q4y4W2)9^5z5g2)9^5x3q4!0q4z5q4!0n7c8W2!0n7x3q4!0q4c8W2!0n7b7#2)9^5b7#2!0q4y4g2!0n7c8q4)9&6x3#2!0q4y4q4!0n7z5q4)9^5x3q4!0q4y4q4!0n7z5q4!0m8b7g2!0q4y4W2)9^5y4q4)9&6c8W2!0q4y4g2)9^5y4g2!0n7y4q4!0q4z5q4!0n7y4W2!0m8x3#2!0q4y4#2)9&6b7g2)9^5y4q4!0q4y4q4!0n7b7g2)9^5b7W2!0q4y4q4!0n7b7W2!0n7y4W2!0q4y4g2)9^5c8W2)9&6x3g2!0q4y4#2)9&6y4q4)9&6c8W2!0q4y4W2)9&6y4#2!0n7y4W2!0q4c8W2!0n7b7#2)9^5b7@1u0J5L8#2!0q4z5q4!0n7c8q4!0m8c8W2!0q4y4q4!0n7b7W2!0n7y4W2!0q4y4W2)9^5c8q4)9&6y4g2!0q4z5q4)9^5c8g2!0n7y4#2!0q4y4q4!0n7z5q4)9^5x3q4!0q4y4q4!0n7z5q4!0m8b7g2!0q4y4g2!0m8c8W2!0n7z5g2!0q4y4g2!0n7b7g2)9&6y4q4!0q4y4q4!0n7b7g2)9^5c8f1y4D9K9h3g2F1N6p5S2W2L8r3I4G2i4@1f1$3i4@1t1$3i4K6R3^5i4@1f1$3i4K6R3I4i4@1q4r3i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1@1i4@1u0m8i4K6S2n7i4@1f1@1i4@1u0n7i4@1t1$3i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1#2i4@1p5$3i4K6R3J5i4@1f1@1i4@1t1^5i4K6S2n7i4@1f1$3i4K6R3&6i4K6R3H3i4@1f1%4i4@1p5@1i4@1u0m8i4@1g2r3i4@1u0o6i4K6R3^5i4@1f1#2i4@1q4q4i4K6W2m8i4@1f1@1i4@1t1&6i4K6R3&6i4@1f1@1i4@1u0m8i4K6S2q4i4@1f1$3i4K6V1$3i4K6R3%4i4@1f1@1i4@1u0n7i4@1t1$3i4K6u0r3N6i4y4J5i4K6u0r3L8r3!0U0j5h3I4Q4x3V1k6T1M7X3!0Q4x3V1k6K6K9r3q4J5k6g2)9J5c8X3u0J5L8#2)9J5c8X3u0S2M7$3g2Q4x3V1k6T1K9h3k6Q4x3V1k6H3L8s2g2Y4K9h3&6K6i4K6u0r3b7Y4u0G2i4K6g2X3f1#2y4x3i4K6u0W2k6i4k6W2L8Y4c8K6i4K6u0W2j5X3W2X3i4K6u0W2j5Y4u0G2i4@1g2r3i4@1u0o6i4K6R3&6i4@1g2r3i4@1u0o6i4K6W2m8
至此,我们已经备齐了所有用于执行指纹识别的材料;脚本框架如下所示:
事件原型中的ciphers向量所存放的索引,可用于访问消息中的不同密码套件,同时我们可以用cipher_desc结构表将它们映射到对应的文本字符串。我们使用join_string_vec()函数(类似于Perl,Python或者其他语言的join()函数/方法)来以逗号分隔的方式显示它们。若将脚本保存到文件log_cipher_suites.bro,则我们在之前所捕获的文件tls.pcap上应用该脚本来实现一次快速测试。具体命令与输出如下所示:
可以看出,Firefox浏览器使用TLSv1.2协议发送了15个密码套件。
日志记录框架
执行print命令,则当Bro软件作为守护进程运行时所有信息将被存储到stdout.log文件中;然而,如果我们想要将输出发送到另一个文件中,或者发送到Elasticsearch搜索引擎呢?为此,Bro软件提供了日志记录框架。其用法非常简单,一学就会;-)
要讲之前的“测试”脚本改造成最终版本,首先我们需要创建一个名为TlsFingerprint的模块,命令如下:
然后,我们需要定义两个变量,它们将被模块导出到Bro软件的其他部分;简便起见,将其命名为LOG和Info。具体代码如下:
[培训]科锐逆向工程师培训第53期2025年7月8日开班!