易盛娱乐利用JA3和JA3S实现TLS指纹识别_偃师民声网

易盛娱乐

原文:

摘要

在这篇文章中,我们将为读者介绍如何使用JA3和JA3来提取和识别客户端和服务器之间的TLS协商的指纹。这种组合型的指纹识别技术,能够为特定客户端与其服务器之间的加密通信提供具有更高的识别度。例如:

标准Tor客户端:
JA3 = e7d705a3286e19ea42f587b344ee6865(Tor客户端)
JA3S = a95ca7eab4d47d051a5cd4fb7b6005dc(Tor服务器的响应)

由于Tor服务器总是以完全相同的方式来响应Tor客户端,所以,这一特征能够为确认相关流量来自于Tor提供更高的置信度。更多例子——

Trickbot恶意软件:
JA3 = 6734f37431670b3ab4292b8f60f29984 (trickbot)

JA3S = 623de93db17d313345d7ea481e7443cf(C2服务器的响应)

Emotet恶意软件:
JA3 = 4d7a28d6f2263ed61de88ca66eb011e3 ( Emotet )
JA3S = 80b3a14bccc8598a1f3bbe83e71f735f (C2服务器的响应 )

在这些恶意软件样本中,C2服务器始终以完全相同的方式来响应恶意软件客户端,应该说是分毫不差。因此,即使流量被加密,并且,即使不知道C2服务器的IP地址或域名,因为它们会不断变化,我们仍然可以通过指纹来识别客户端和服务器之间的TLS协商,以提高恶意通信识别结果的置信度。

实际上,JA3和JA3S工具现在已经开源,读者可以从下面的地址进行下载:

https://github.com/salesforce/ja3

JA3背景知识

我们在2017年的一篇文章中,公布了JA3软件的源码;简单来说,JA3就是一种在线识别TLS客户端指纹的方法:

实际上,对TLS客户端进行指纹识别的思想,最初来自于于2015年的一项研究成果,对这项研究感兴趣的读者可以参阅;与该思想相关的DerbyCon演讲可以参阅。如果没有Lee的研究论文和开放源码,我们也就不会开始研究JA3了。所以,在此要感谢Lee以及所有相关文章和开放源代码的作者们!

我们知道,不仅"良性的"应用程序会使用TLS及其前身SSL对其流量进行加密,而且恶意软件也常常这样做;前者这样做的目的是确保数据安全,而后者这样做的目的则是将其流量隐藏在噪声中。为了启动TLS会话,客户端将在TCP 3次握手后发送TLS客户端的Hello数据包。这个数据包及其生成方式取决于构建客户端应用程序时所使用的软件包和方法。如果接受TLS连接,服务器将使用基于服务器端库和配置以及Client Hello消息中的详细信息创建的TLS Server Hello数据包进行响应。由于TLS协商是以明文的方式传输的,所以,我们可以使用TLS Client Hello数据包中的详细信息对客户端应用程序进行指纹识别。

这张精心绘制的网络图为我们展示了SSL/TLS连接刚开始的通信模式。

JA3方法用于收集Client Hello数据包中以下字段的十进制字节值:版本、可接受的密码、扩展列表、椭圆曲线密码和椭圆曲线密码格式。然后,它将这些值串联在一起,使用“,”来分隔各个字段,同时,使用“-”来分隔各个字段中的各个值。

使用Wireshark展示的Client Hello数据包示例

这些字段的顺序如下所示:

TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats

例如:

769,47–53–5–10–49161–49162–49171–49172–50–56–19–4,0–10–11,23–24–25,0

如果Client Hello数据包中没有TLS扩展(TLS Extensions),则这些字段的值为空。

例如:
769,4–5–10–9–100–98–3–6–19–18–99,,,

然后,会计算这些字符串的MD5哈希值,以生成易于使用和共享的长度为32字符的指纹。它们就是JA3 TLS客户端的指纹。

769,47–53–5–10–49161–49162–49171–49172–50–56–19–4,0–10–11,23–24–25,0 → ada70206e40642a3e4461f35503241d5
769,4–5–10–9–100–98–3–6–19–18–99,,, → de350869b8c85de67a350c8d186f11e6

我们还需要引入一些代码来解释Google的GREASE(Generate Random Extensions And Sustain Extensibility),如这里所述。实际上,Google会使用这个机制来防止TLS生态系统中的可扩展性出现故障。不过,JA3会完全忽略这些值,以确保使用GREASE的程序仍然可以用单个JA3哈希值来完成指纹识别。

那么,JA3可以在TLS1.3上工作吗?当然了。

下面给出了两个不同浏览器的TLS1.3Client Hello数据包,我们可以看到,不仅每个Hello数据包对其加密算法和扩展的排序各不相同,而且,它们也包含(或排除)了不同的加密算法和扩展。因此,JA3对于每个客户端来说仍然是唯一的。

JA3S

创建JA3之后,我们可以利用同样的方法对TLS握手的服务器端进行指纹识别,即对TLS Server Hello消息进行指纹识别。JA3S方法会收集Server Hello数据包中以下各个字段的十进制字节值:版本、可接受的加密算法和扩展列表。然后,它将这些值串联在一起,使用“,”来分隔各个字段,并通过“-”来分隔每个字段中的各个值。

这些字段的顺序如下所示:

TLSVersion,Cipher,Extensions

例如:
769,47,65281–0–11–35–5–16

如果Server Hello数据包中没有TLS扩展(TLS Extensions),则这些字段的值为空。

例如:
769,47,

然后,会计算这些字符串的MD5哈希值,以生成易于使用和共享的长度为32字符的指纹。它们就是JA3S的指纹。

769,47,65281–0–11–35–5–16 → 4835b19f14997673071435cb321f5445

我们之所以使用MD5算法,是因为这样可以分别向Client Hello或Server Hello中添加任意数量的加密算法或扩展,而我们的经验法则是,如果指纹不能放入tweet中,那么说明它就太长了。除此之外,之所以选择MD5算法,是因为这样一来,JA3方法可以更容易地集成到现有技术中。请记住,JA3是一种旨在可用于任意硬件上的任意应用程序中的方法。当然,我承认,模糊哈希算法的强度会更好一些,不过,由于我们希望使用的是一种可以集成到当前部署的技术中的方法,考虑到当前的大多数技术还不支持模糊哈希技术,而即使是最古老的NetScreen防火墙也可以支持大批量的MD5计算,所以,我们还是选择了MD5算法。此外,考虑到有限的数据集,这里根本就不需要考虑哈希值的碰撞问题。我知道,MD5的安全性在安全社区中一直是一个有争议的问题,所以,有必要解释一下我们采用它的原因。

我们的代码不仅考虑到了记录整个字符串,同时还要记录用于指纹分析的哈希值。所以,我强烈建议,如果有可能的话,最好记录JA3和JA3的整个指纹字符串及其哈希值。这样,指纹分析功能就可以派上用场了。但是,如果您所在公司的日志空间不足的话,那么只记录哈希值就可以了。

JA3S的工作原理

我们发现,同一台服务器会根据Client Hello消息及其内容以不同的方式创建其Server Hello消息。因此,这里不能像客户端和JA3那样,仅仅根据服务器的Hello消息来对其进行指纹识别。因此,有些人认为这种方法在这里没有什么价值。但我们还是这样做了了,因为Salesforce对于咖啡的供应是无限量的。经过一段时间后,我们发现,尽管服务器对不同客户端的响应不同,但它们对同一客户端的响应总是一致的。

在这个网络图中,我们可以看到,客户端正在发送TLS Client Hello数据包,其中数据都是A。因此,服务器会的响应的内容也是由A构成,并将始终用A来提供同样的响应。

这里,另一个客户端也在发送数据包,并且内容都是B。类似的,服务器现在会用B进行响应,并且总是用B组成的B串进行响应。可以看到,对于不同的客户端,服务器会给予不同的响应,但是对于每个客户端来说,总是以相同的方式进行相应。

真实世界中的例子:

在这个日志输出中,JA3位于左侧,JA3S位于右侧

在本例中,我使用同一客户端与同一服务器交互了4次。然后,我再次使用不同的客户端进行了4次以上的交互。不难发现,服务器的响应方式对于同一客户端总是相同的,但对于不同的客户端却是不同的。

安全用途

如果攻击方构建了定制的恶意软件可执行文件,那么,JA3指纹很可能对该可执行文件来说是唯一的。例如,下面是渗透测试人员定制的恶意软件所发送的Client Hello消息:

您可以看到,只有一个强度可接受的加密算法套件是异常的,并且生成的JA3在我们的环境中是唯一的,这使得无论目的地如何,都很容易检测到。

对于其他渗透测试工具(如PupyRAT)来说,它们也会指定自己的加密算法以及相应的排序方法,具体如下面的Pupy代码所示:

这使得Client Hello中的加密算法显得非常与众不同并且独一无二,从而可以得到一个独特的JA3:

然后,我们能够围绕JA3来提高自己的“猎捕”能力或响应能力。

但是,如果客户端应用程序使用公共库或操作系统套接字进行通信(如Python或Windows套接字),那么又该怎么办呢?JA3在环境中很常见,因此对检测不太有用。这就是JA3S可以帮助识别恶意通信的地方。

例如,MetaSploit的Meterpreter和CobaltStrike的Beacon都使用Windows套接字来启动TLS通信。对于Windows10来说,JA3=72a589da586844d7f0818ce684948eea(转到IP地址时),JA3=a0e9f5d64349fb13191bc781f81f42e1(转到域名时)。由于Windows上的其他合法应用程序都使用相同的套接字,因此,我们很难识别其中的恶意通信。但是,Kali Linux上的C2服务器对该客户端应用程序的响应方式与Internet上的普通服务器对该套接字的响应方式相比来说是独一无二的。因此,如果我们结合JA3+JA3,那么我们就能够识别这种恶意通信,而不用考虑目的地IP、域名或证书等细节信息。在撰写本文时,如果搜索相关的数据,结果如下所示:

Metasploit Win10 至Kali:
(JA3=72a589da586844d7f0818ce684948eea 或 JA3=a0e9f5d64349fb13191bc781f81f42e1) 且 JA3S=70999de61602be74d4b25185843bd18e

Cobalt Strike Win10 至 Kali:
(JA3=72a589da586844d7f0818ce684948eea 或 JA3=a0e9f5d64349fb13191bc781f81f42e1) 且 JA3S=b742b407517bac9536a77a7b0fee28e9

需要说明的是,这种判断方法也存在着误判的风险。我们可以将JA3看作用户代理字符串的TLS等效项。即使某软件或恶意软件具有一个特定的字符串,那也不意味着该字符串永远是该软件所特有的。其他软件也可能使用相同的字符串。但是,这仍然不足以构成拒绝使用该字符串来增强我们的指纹分析和检测的理由。就像其他网络元数据一样,通过加入JA3,能够进一步丰富我们的数据信息。在使用JA3的情况下,当寻找特定内容的时候,JA3S可以显著降低误报水平。

渗透测试示例

在另一个示例中,我们让渗透测试人员使用Empire的Python版本作为恶意软件样本。在这个例子中,JA3是Python版本的,所以,它在任何开发人员环境中都不是唯一的。

如果我们在整个环境中搜索这个JA3,结果会是这样的:

但是,渗透测试人员的C2服务器会以一种独特的方式来响应Python客户端。因此,当我们搜索Python的JA3及其C2服务器响应的JA3时,结果如下所示:

不过,我当时忘了截图,所以,你得相信我,这就是Splunk的样子。

输出结果是恶意软件对其C2服务器的beacons。正如您所看到的,JA3和JA3相组合,实际上就是构成了客户端和服务器之间加密协商的指纹。

在完成渗透测试之后,他们将C2的镜像移动到了另一个IP地址和域名。但是,恶意软件和服务器还是相同的应用程序,因此,指纹也是不变的。因此,之前的指纹识别方法可以立即奏效。最后,渗透测试人员购买了一个完全不同的服务提供商的空间、一个新的貌似正规的证书以及一个新的域名,并将他们的C2镜像移动到那里。结果,该恶意软件还是立刻就被发现了。

由于该检测方法是基于特定的基础设施和技术的,而不是基于目的地IP地址、域名或证书的,所以,我们不再需要依赖更容易改变的传统IOC。这种检测方法将对手逼迫到了David Bianco的痛苦金字塔的顶端,同时,还增加了对手的攻击成本。

小结

JA3和JA3S是一种基于TLS指纹的安全分析方法。JA3指纹能够指示客户端应用程序通过TLS通信的方式,而JA3指纹能够指示服务器响应。如果两者结合起来,实质上就生成了客户端和服务器之间的加密协商的指纹。虽然基于TLS的检测方法不一定是灵丹妙药,也不一定能保证映射到客户端应用程序,但它们始终是安全分析的轴心所在。

我们设计这些方法,主要是为了让它们能够容易地融入现有的技术中,并让生成的指纹易于使用和共享。同时,BSD3条款许可使其易于实现。我们只是想让事情简单些。这样做,我们的希望是,它成为贵国防御性武器库中的一个宝贵的补充,并激励其他人建立起我们的研究,推动工业向前发展。

Zeek/BRO和Python版本的JA3和JA3可以从

JA3作者:


对于客户端到JA3或HASHH的自动映射方面的介绍,请参阅https://github.com/salesforce/bro-sysmon/上的。

如有任何问题或意见,请随时给我发)。