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

重新访问Realtek - Set的关键Wi-Fi漏洞发现

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

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已经发表安全公告,并在VD-1406上分配了一个CVE。

技术深潜

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

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

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

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

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

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

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

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

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

EAPOLMsgRecvd。八隅体和EAPOLMsgRecvd。长度由攻击者控制。

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

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

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

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

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

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

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

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

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

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

此问题存在于VD-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, v3__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身份验证的长度字段中读取unsigned short,并在&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);

from: DecWPA2KeyData()函数的反编译

其中EapolKeyMsgRecvd包含802.1x身份验证层,除前4个字节外,v10__keylen是在&EapolKeyMsgRecvd[93](当从ClientEAPOLKeyData()调用时)的大端无符号short, 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大小的past,因为keylen是用户控制的,这将导致堆栈溢出,从而导致拒绝服务或代码执行。

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

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

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

  1. 攻击者知道受害设备所连接的WPA2 Wi-Fi网络的密码。
  2. 攻击者向受害设备发送一个死亡报文,在大多数情况下,受害设备将尝试重新连接。
  3. 攻击者嗅探EAP数据包,以获取从密码短语计算PTK所需的anonce和snonce。
  4. 攻击者准备一个恶意AP,它将执行攻击,并具有确切的SSID和确切的PTK(通过使用已知的密码短语和捕获snonce和anonce)。恶意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 =密码;v7__alignd_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__alignd_cipher_len - 1 > 0) {v8__R = R;v9__cipher = (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() -参阅VD-1408了解更多详细信息。

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

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

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

DecWPA2KeyData()中有一个memcpy,可能导致ClientEAPOLKeyRecvd()的堆栈溢出。

memcpy:

Rtl_memcpy (v11__kout, v12__tmp2, v10__keylen);

from: 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)

from:编译ClientEAPOLKeyRecvd()函数

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

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

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

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

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

V21__wpa_global_info = &v4-> securityprivi .wpa_global_info;v22 = v4 - > securitypriv.wpa_global_info。MulticastCipher == 2 ?32: 16;if (!DecGTK(v5__WPA_STA_INFO->EAPOLMsgRecvd, &v5__WPA_STA_INFO->PTK[16], 16, v22, v21__wpa_global_info->GTK[(v5__WPA_STA_INFO->EapolKeyMsgRecvd。Octet[2] >> 4) & 3])) goto exit;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));if (decrypted_data[0] == 221 && !rtl_memcmp(&decrypted_data[2], GTK_KDE_OUI_0, 4u)) {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)); } }

from:编译ClientEAPOLKeyRecvd()函数

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

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

鸣谢

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

常见问题解答

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

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

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

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

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

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

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

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

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

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

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

问题吗?想法吗?有关安全漏洞的任何问题,请通过research@m.si-fil.com联系我们。

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