Realtek RTL8195A Wi-Fi模块主要漏洞发现及修复

重访Realtek -发现的一组关键Wi-Fi漏洞

在最近的供应链安全评估中,JFrog安全研究团队(以前的Vdoo)分析了多个网络设备安全漏洞和曝光。在分析过程中,我们发现并负责任地披露了Realtek RTL8195A Wi-Fi模块中的六个主要漏洞,这些设备基于该模块。利用发现的漏洞的攻击者可以获得对Wi-Fi模块的远程root访问权限,并很可能从那里跳转到应用程序处理器(因为攻击者完全控制了设备的无线通信)。

RTL8195模块是一款针对嵌入式设备的非常紧凑、低功耗的Wi-Fi模块。它支持ARM、三星、谷歌、亚马逊等主要厂商的软件。例如,根据AWS的说法,它被用于众多行业,例如:

  • 农业
  • 汽车
  • 能源
  • 游戏
  • 医疗保健
  • 工业
  • 安全
  • 智能家居

在这篇博文中,我们讨论了漏洞的技术细节,分享了易受攻击组件的背景,提供了如何检测和解决漏洞的指导,并讨论了如何通过供应链安全评估发现这些漏洞的背景。

技术概述

RTL8195A是一个独立的Wi-Fi硬件模块,用于许多低功耗应用:

RTL8195A

Realtek提供他们自己的“阿米巴”API该设备允许任何开发人员通过Wi-Fi, HTTP, mDNS, MQTT等轻松通信。

作为该模块Wi-Fi功能的一部分,该模块支持WEP、WPA和WPA2认证模式。

在我们的安全评估中,我们发现WPA2握手机制容易受到各种堆栈溢出和读取越界问题的攻击。

虽然这些问题只在RTL8195A模块上得到了验证,但我们认为它们也与以下模块相关:

  • RTL8711AM
  • RTL8711AF
  • RTL8710AF

我们发现的最严重的问题是vd - 1406远程堆栈溢出,允许RTL8195模块附近的攻击者在不知道Wi-Fi网络密码(PSK)的情况下完全接管模块无论模块是作为Wi-Fi接入点还是客户端。攻击场景将在下一节“技术深度介绍”中详细介绍。

VD-1407和VD-1411也可以在不知道网络安全密钥(PSK,或者更准确地说是由此衍生的PMK)的情况下被利用,通过这种方式,可以在使用该Wi-Fi模块的WPA2客户端上执行远程代码执行或拒绝服务。

VD-1408, VD-1409和VD-1410要求攻击者知道网络的PSK作为攻击的先决条件,并且可以被滥用以获取使用该Wi-Fi模块的WPA2客户端上的远程代码执行。

Realtek已经发表发布安全公告,并在cd -1406上分配CVE。

技术深潜

VD-1406 (CVE-2020-9395) -基于堆栈的缓冲区溢出漏洞

此漏洞不需要了解网络的PSK。

这个问题允许利用Wi-Fi客户端和接入点(AP)设备。

作为WPA2 4路握手的一部分,密钥交换发生在“EAPOL”帧:

在此密钥交换中,Realtek WPA2客户端/服务器分别调用ClientEAPOLKeyRecvd和EAPOLKeyRecvd函数来处理数据包。

上述函数都调用CheckMIC()函数,该函数负责检查EAP包中MIC部分的完整性。

在CheckMIC()中可以触发不安全的副本:

rtl_memcpy (tmpbuf EAPOLMsgRecvd。八隅体,EAPOLMsgRecvd.Length);

lib_wlan.a中CheckMIC()函数的反编译

EAPOLMsgRecvd。Octet和EAPOLMsgRecvd。长度由攻击者控制。

EAPOLMsgRecvd。Octet包含以太网层(14字节)和802.1X认证层EAPOLMsgRecvd。长度直接来自802.1X身份验证的长度字段。

Tmpbuf是一个固定大小为512字节的本地缓冲区。

发送的数据包的大小可能大于tmpbuf(512字节堆栈缓冲区)的大小,并导致memcpy()复制的字节超过分配的字节,从而导致堆栈溢出。

可以利用此漏洞通过覆盖CheckMIC()的返回地址来获得远程代码执行或拒绝服务。

请注意,没有任何缓解因素(堆栈金丝雀、ASLR甚至不可执行的堆栈),因此利用是微不足道的。

为了攻击WPA2客户端和WPA2接入点,可以在两种不同的情况下触发该漏洞:

  1. Realtek设备的受害者是客户端(CheckMIC()是从clientteapolkeyrecvd()调用的)。
    在这种情况下,攻击者可以通过以下方式利用受害客户端设备:

    1. 嗅探Wi-Fi数据包,查看受害设备连接的无线网络,并获取该网络的SSID。
    2. 准备一个恶意接入点,该接入点将执行攻击并具有确切的SSID。
    3. 向受害设备发送死亡数据包,并比原始网络更大声地广播,以便设备连接到恶意接入点。
  2. Realtek设备的受害者是接入点(CheckMIC()是从EAPOLKeyRecvd()调用的)
    在这种情况下,攻击者客户端可以简单地连接到受害AP并利用它。

VD-1407 (CVE-2020-25853) -读取越界漏洞

此漏洞不需要了解网络的PSK。

此问题存在于cd -1406中提到的CheckMIC()函数中:

v3__Octet = EAPOLMsgRecvd.Octet;v4 = EAPOLMsgRecvd.Octet[20];V5__key = key;V6__tmpbuf_at_95 = &tmpbuf[95];rtl_memcpy (tmpbuf EAPOLMsgRecvd。八隅体,EAPOLMsgRecvd.Length);Rtl_memset (&tmpbuf[95], 0, 0x10u);V7 = v4 & 7;// USER-CONTROLLED SIZE -> v8__len = (unsigned __int16)(ntohs(*(uint16_t *)&tmpbuf[16]) + 4);如果(v7 = = 1) {_rt_md5_hmac_veneer (&tmpbuf [14], v8__len, v5__key, 16日&tmpbuf [95]);返回rtl_memcmp(v6__tmpbuf_at_95, vv3__octet + 95, 0x10u) == 0; } if ( v7 != 2 ) return 0; v6__tmpbuf_at_95 = sha1digest; _rt_hmac_sha1_veneer((int)&tmpbuf[14], v8__len, (int)v5__key, 16, (int)sha1digest);

lib_wlan.a中CheckMIC()函数的反编译

从EAP包中读取一个无符号短报文——802.1X认证的长度字段,它以&tmpbuf[16]结尾。

V8__len稍后用作_rt_md5_hmac_veneer()或_rt_hmac_sha1_veneer()的大小参数。如果v8__len足够大(tmpbuf的固定大小为512字节),这些函数将读取超出tmpbuf的范围。在某些情况下,这可能导致拒绝服务。

请注意,在计算v8__len时也有一个整数溢出,但这不会导致任何可利用的问题。

VD-1408 (CVE-2020-25854) -基于堆栈的缓冲区溢出漏洞

利用这个问题需要了解网络的预共享密钥(PSK)。

这个问题允许利用Wi-Fi客户端设备。

在DecWPA2KeyData()有一个堆栈溢出:

_rt_arc4_crypt_veneer(&rc4_ctx, tmp2, v7->EapolKeyMsgRecvd。Octet + 95, v10__keylen);

DecWPA2KeyData()函数的反编译

其中EapolKeyMsgRecvd包含802.1x认证层,除了前4个字节,v10__keylen是&EapolKeyMsgRecvd[93]的大端无符号短(当从ClientEAPOLKeyData()调用时),tmp2是257字节大小的本地缓冲区。

rt_arc4_crypt_veneer()或_AES_UnWRAP_veneer()将解密v7->EapolKeyMsgRecvd中的数据。将Octet + 95转换为tmp2,并使用用户控制的keylen的加密文本大小(密钥正在解密,因此它实际上是加密的文本大小)。

如果使用AES,也会发生类似的问题:

_AES_UnWRAP_veneer(v8__key, keylen, kek, keklen, tmp2);

其中_AES_UnWRAP_veneer()将解密数据在v7->EapolKeyMsgRecvd。将Octet + 95转换为tmp2,并使用用户控制的keylen的加密文本大小(密钥正在解密,因此它实际上是加密的文本大小)。

在这两种情况下,解密过程可以写入超过tmp2的大小,因为keylen是由用户控制的,这将导致堆栈溢出,从而导致拒绝服务或代码执行。

为了在解密过程(AES或RC4)之后拥有受控数据,我们需要知道KEK参数,否则我们将无法解密v7->EapolKeyMsgRecvd中的数据。Octet + 95正确溢出堆栈,然后我们将无法正确重写返回地址。

我们可以计算KEK,因为ClientEAPOLKeyRecvd()将PTK作为KEK参数传递。PTK是由Wi-Fi网络的密码PMK衍生而来。因此,假设我们知道密码,我们可以在设备上远程运行任意代码。

由于DecWPA2KeyData()仅从ClientEAPOLKeyRecvd()调用,攻击场景将如下:

  1. 攻击者知道受害设备所连接的WPA2 Wi-Fi网络的密码。
  2. 攻击者向受害设备发送死亡报文,在大多数情况下,设备会尝试重新连接。
  3. 攻击者嗅探EAP数据包,以便捕获从密码短语计算PTK所需的anonce和snonce。
  4. 攻击者准备了一个恶意AP,它将执行攻击,并具有确切的SSID和确切的PTK(通过使用已知的密码短语和一次又一次的捕获)。恶意AP的广播声音必须大于原有网络。
  5. 攻击者向受害设备发送额外的死亡报文。
  6. 受害设备将尝试连接到恶意AP,并通过这样做将解析我们的恶意EAP数据包并运行任意代码。

VD-1409 (CVE-2020-25855) -基于堆栈的缓冲区溢出漏洞

利用这个问题需要了解网络的预共享密钥(PSK)。这个问题允许利用Wi-Fi客户端设备。

在AES_UnWRAP() (from lib_rom.a)中存在堆栈溢出:

V5__cipher_len = (cipher_len + 7) & (cipher_len >> 32);If (cipher_len >= 0) v5__cipher_len = cipher_len;V6__cipher = cipher;V7__aligned_cipher_len = v5__cipher_len >> 3;Nblock = v7__aligned_cipher_len - 1;Aes_set_key (&ctx, kek, 128);memcpy(A, v6_cipher, 8u);if (v7__aligned_cipher_len - 1 > 0) {v8__R = R;V9__cipher_ptr = (int)(v6__cipher + 8);V10__block_counter = 0; do { v11__R = v8__R; v12__cipher_ptr = (const void *)v9__cipher_ptr; ++v10__block_counter; ++v8__R; v9__cipher_ptr += 8; // STACK OVERFLOW --> memcpy(v11__R, v12__cipher_ptr, 8u); } while ( v10__block_counter != nblock ); }

from: AES_UnWRAP()函数的反编译

这里有一个循环,将8个字节复制到数组,这是一个本地缓冲区,定义为:

unsigned __int8 R[32][8];

问题是循环迭代次数可以由用户控制(它恰好是cipher_len/8),并且不受R(32)中的最大条目的限制。

这个函数从DecWPA2KeyData()调用,用户控制的cipher_len (keylen)参数来自DecWPA2KeyData() -参见cd -1408了解更多细节。

VD-1410 (CVE-2020-25856) -基于堆栈的缓冲区溢出漏洞

利用这个问题需要了解网络的预共享密钥(PSK)。

这个问题允许利用Wi-Fi客户端设备。

DecWPA2KeyData()中有一个内存会导致ClientEAPOLKeyRecvd()的堆栈溢出。

memcpy:

Rtl_memcpy (v11__kout, v12__tmp2, v10__keylen);

DecWPA2KeyData()函数的反编译

其中v12__tmp2是257字节大小的本地缓冲区,v10__keylen是用户控制的(请参阅之前的VD-1408了解更多细节和利用限制),v11__kout作为kout参数从ClientEAPOLKeyRecvd()传递给DecWPA2KeyData():

DecWPA2KeyData(v5__WPA_STA_INFO, v9__EapolKeyMsgRecvd + 95, (unsigned __int16)(v9__EapolKeyMsgRecvd[94] + (v9__EapolKeyMsgRecvd[93] << 8)), &v5__WPA_STA_INFO->PTK[16], 16, decrypted_data)

来自:clientteapolkeyrecvd()函数的反编译

其中decrypted_data作为kout参数传递给DecWPA2KeyData()。

(decrypted_data是一个固定大小为128字节的本地缓冲区)

VD-1411 (CVE-2020-25857) -基于堆栈的缓冲区溢出漏洞

此漏洞不需要了解网络的PSK。

ClientEAPOLKeyRecvd()中有一个堆栈溢出,它可以被滥用于拒绝服务:

V21__wpa_global_info = &v4-> securityprivo .wpa_global_info;V22 = v4-> securityprivo .wpa_global_info. V22 = v4-> securityprivo .wpa_global_info. V22MulticastCipher == 2 ?32:16;if (!DecGTK(v5__WPA_STA_INFO->EapolKeyMsgRecvd, &v5__WPA_STA_INFO->PTK[16], 16, v22, v21__wpa_global_info->GTK[(v5__WPA_STA_INFO->EapolKeyMsgRecvd.)];Octet[2] >> 4) & 3]))v23__EapolKeyMsgRecvd = v5__WPA_STA_INFO->EapolKeyMsgRecvd.Octet;if (*v23__EapolKeyMsgRecvd == 2) {// STACK OVERFLOW --> rtl_memcpy(decrypted_data, v21__wpa_global_info->GTK[(v23__EapolKeyMsgRecvd[2] >> 4) & 3], v23__EapolKeyMsgRecvd[94] + (v23__EapolKeyMsgRecvd[93] << 8));rtl_memcmp(&decrypted_data[2], GTK_KDE_OUI_0, 4)) {v24 = decrypted_data[1];V25 = decrypted_data[6] & 3;v4 - > securitypriv.wpa_global_info。GN = v25;rtl_memcpy(v21__wpa_global_info->GTK[v25], &decrypted_data[8], (unsigned __int8)(v24 - 6)); } }

来自:clientteapolkeyrecvd()函数的反编译

请注意,内存的长度完全由用户控制(因为v23__EapolKeyMsgRecvd完全由用户控制)

其中v23__EapolKeyMsgRecvd是EapolKeyMsgRecvd。Octet,它包含802.1x认证层,除了前4个字节,目的缓冲区是decrypted_data,这是一个固定大小为128字节的本地缓冲区。源缓冲区是GTK,但它不是用户控制的,因此我们不能用一个有效的地址覆盖ClientEAPOLKeyRecvd()的返回地址。由于此限制,无法利用此漏洞执行代码(只能拒绝服务)。

鸣谢

我们要感谢Realtek的安全团队高效、及时地处理了这一安全问题,以及他们专业的沟通行为。

常见问题解答

Q1。我如何知道我的设备是否易受攻击?

2020年4月21日之后构建的任何版本都针对上述所有问题进行了完全修补。

2020年3月3日之后构建的任何版本都针对VD-1406打了补丁,但仍然容易受到所有其他问题的影响。

构建日期通常可以从二进制固件中提取为一个简单的字符串。

例如,通过运行以下命令查找固件中的任何构建日期,并观察类似的输出:

# strings realtek_firmware.bin | grep -P '2021|2020|2019|2018|2017' 2020/09/30-17:14:47

Q2。我可以应用哪些补丁来解决这个问题?

可以下载Ameba SDK的更新版本来自Realtek的网站

最新版本的Ameba Arduino(2.0.8)包含针对上述所有问题的补丁。

第三季。如果我无法更新设备的固件,如何降低风险?

使用一个强大的,私有的WPA2密码短语将防止利用问题VD-1408, VD-1409和VD-1410

问题吗?想法吗?与安全漏洞有关的任何查询,请在research@www.si-fil.com与我们联系。

除了发现并负责任地披露漏洞作为我们日常活动的一部分之外,JFrog安全研究团队还通过授权组织通过自动安全分析发现漏洞来增强软件安全性。有关JFrog DevOps平台安全特性的更多信息和更新-点击这里