[原创] Realtek RTL8195A WIFI历史漏洞分析和新漏洞挖掘
前言
本文主要分析vdoo发现的一些RTL8195A WIFI模块的漏洞。
环境搭建
下载最新的SDK
https://github.com/ambiot/amb1_arduino/blob/master/Arduino_package/release/ameba_1-2.0.10-build20210203.tar.gz
解压后在下面目录里面有一堆.a文件,漏洞就存在与这些.a里面
ameba_1-2.0.10-build20210203\hardware\variants\rtl8195a
为了分析的方便,首先将.a链接成.so
ar -x lib_ameba.a
ar -x lib_codec.a
ar -x lib_hs_uart_redirect.a
ar -x lib_mdns.a
ar -x lib_p2p.a
ar -x lib_rtlstd.a
ar -x lib_sdcard.a
ar -x lib_usbh.a
ar -x lib_wlan.a
ar -x lib_xmodem.a
ar -x lib_arduino_alexa.a
ar -x lib_google_cloud_iot.a
ar -x lib_i2c_redirect.a
ar -x lib_mmf.a
ar -x lib_platform.a
ar -x lib_rtsp.a
ar -x lib_usbd.a
ar -x lib_websocket.a
ar -x lib_wps.a
rm console_i2c.o
rm alexa_mem.o
arm-none-eabi-gcc -w -shared *.o -o liball.so
然后就可以用IDA加载so进行分析了
漏洞分析
本节基于最新的SDK和ameba-2.0.4-build20180817有漏洞版本SDK进行分析,同时对补丁和漏洞进行分析
VD-1406 (CVE-2020-9395) – Stack-based buffer overflow vulnerability
ClientEAPOLKeyRecvd函数会调用CheckMIC来处理数据
CheckMIC(v5->EAPOLMsgRecvd, v5->PTK, &v5->EAPOLMsgRecvd)
EAPOLMsgRecvd为外部数据
bool __fastcall CheckMIC(OCTET_STRING EAPOLMsgRecvd, unsigned __int8 *key, int keylen)
{
v3 = EAPOLMsgRecvd.Octet;
v4 = EAPOLMsgRecvd.Octet[20];
v6 = &tmpbuf[95];
rtl_memcpy_0(tmpbuf, EAPOLMsgRecvd.Octet, EAPOLMsgRecvd.Length);
Octet为数据地址,Length为数据长度,这里没有检查Length,从而导致栈溢出。
最新版本的CheckMIC函数如下
bool __fastcall CheckMIC_constprop_14(int data, unsigned int length, int a3)
{
v6 = *(data + 20);
if ( length > 0x200 ) // 新增length的检查
return 0;
v8 = &stack[95];
freertos_memcpy_0(stack, data, length); //
freertos_memset_0(&stack[95], 0, 16);
在最新版的SDK里面会检查length不能超过0x200
调用点
CheckMIC_constprop_14(sta->EAPOLMsgRecvd.Octet, sta->EAPOLMsgRecvd.Length, sta->PTK) )
EAPOLMsgRecvd为外部数据,Octet为数据地址,Length为数据长度
VD-1407 – Read out of bounds vulnerability
问题还是位于CheckMIC函数
bool __fastcall CheckMIC(OCTET_STRING EAPOLMsgRecvd, unsigned __int8 *key, int keylen)
{
v3 = EAPOLMsgRecvd.Octet;
v4 = EAPOLMsgRecvd.Octet[20];
v6 = &tmpbuf[95];
rtl_memcpy_0(tmpbuf, EAPOLMsgRecvd.Octet, EAPOLMsgRecvd.Length);
flag = v4 & 7;
v8 = (ntohs_0(*&tmpbuf[16]) + 4); // 从外部数据取出长度 v8
if ( flag == 1 )
{
rt_md5_hmac_0(&tmpbuf[14], v8, key, 16, &tmpbuf[95]); // 作为 rt_md5_hmac参数
问题逻辑是,首先从数据包里面取出了2个字节作为长度存放到v8,然后没有检查v8是否会大于Length,就传给rt_md5_hmac去算一个hash,在rt_md5_hmac里面会越界读。
补丁版本
v9 = (ntohs_0(*&stack[16]) + 4);
if ( (length - 13) <= v9 ) // 检查长度
return 0;
if ( (v6 & 7) != 1 )
{
if ( (v6 & 7) == 2 )
{
v8 = digest;
rt_hmac_sha1_0(&stack[14], v9, a3, 16, digest);
return rtl_memcmp_0(v8, data + 95, 16) == 0;
}
增加了长度检查
VD-1408 – Stack-based buffer overflow vulnerability
漏洞应该是位于ClientEAPOLKeyRecvd,函数会调用DecWPA2KeyData
if ( !DecWPA2KeyData_0(
v5,
EapolKeyMsg + 95,
(EapolKeyMsg[94] + (EapolKeyMsg[93] << 8)),
&v5->PTK[16],
16,
decrypted_data) )
EapolKeyMsg为外部数据,这里3个参数表示长度,直接从外部数据中取出,然后在DecWPA2KeyData里面会解密数据
int __fastcall DecWPA2KeyData(WPA_STA_INFO *pStaInfo, unsigned __int8 *key, int keylen, unsigned __int8 *kek, int keklen, unsigned __int8 *kout)
{
*default_key_iv = 0xA6A6A6A6;
*&default_key_iv[4] = 0xA6A6A6A6;
if ( (pStaInfo->EapolKeyMsgRecvd.Octet[2] & 7) == 1 )
{
rtl_memcpy_0(tmp1, pStaInfo->EAPOLMsgRecvd.Octet + 63, 16);
rtl_memcpy_0(&tmp1[16], kek, keklen);
sub_14D5C(&rc4_ctx, tmp1, keklen + 16);
rt_arc4_crypt_0(&rc4_ctx, tmp2, tmp1, 256);
rt_arc4_crypt_0(&rc4_ctx, tmp2, pStaInfo->EapolKeyMsgRecvd.Octet + 95, keylen);
解密结果会存放在tmp2,tmp2是栈数组,大小为257,如果keylen比较大就会导致栈溢出。
补丁,在调用ClientEAPOLKeyRecvd时会检查取出的keylen.
v13 = (key_msg[94] + (key_msg[93] << 8));
if ( sta->EAPOLMsgRecvd.Length - 0x70 <= v13
|| !DecWPA2KeyData_0(sta, key_msg + 95, v13, &sta->PTK[16], 16, &stack, 255) )
VD-1409 – Stack-based buffer overflow vulnerability
这个漏洞位于 AES_UnWRAP 函数,由于函数的二进制代码位于rom,这里直接分析原文提供的代码
void AES_UnWRAP(unsigned char * cipher, int cipher_len,
unsigned char * kek, int kek_len,
unsigned char * plain)
{
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 );
}
主要问题是AES_UnWRAP循环解密时会不断把结果拷贝到栈数组R中,如果cipher_len过大,就会溢出数组R。
R的定义
unsigned __int8 R[32][8];
VD-1410 – Stack-based buffer overflow vulnerability
漏洞位于ClientEAPOLKeyRecvd,函数会调用DecWPA2KeyData
if ( !DecWPA2KeyData_0(
v5,
EapolKeyMsg + 95,
(EapolKeyMsg[94] + (EapolKeyMsg[93] << 8)),
&v5->PTK[16],
16,
decrypted_data) )
EapolKeyMsg为外部数据,这里3个参数表示长度,直接从外部数据中取出,然后在DecWPA2KeyData里面会解密数据
int __fastcall DecWPA2KeyData(WPA_STA_INFO *pStaInfo, unsigned __int8 *key, int keylen, unsigned __int8 *kek, int keklen, unsigned __int8 *kout)
{
v9 = kout;
rtl_memcpy_0(v9, v10, keylen);
DecWPA2KeyData解密完数据后会把keylen长度的数据拷贝到 kout,即decrypted_data 其大小为 128字节,所以可能导致栈溢出。
修复方案
!DecWPA2KeyData_0(sta, key_msg + 95, v13, &sta->PTK[16], 16, &stack, 0xFF)
额外增加了一个参数,表示Kout的大小,然后在DecWPA2KeyData里面会去校验
if ( key_len > kout_length || key_len >= 0x102 )
return 0;
VD-1411 – Stack-based buffer overflow vulnerability(未修复)
漏洞位于ClientEAPOLKeyRecvd
void __fastcall ClientEAPOLKeyRecvd(_adapter *padapter, sta_info *psta)
{
eapol_msg = v5->EAPOLMsgRecvd.Octet;
v5->EapolKeyMsgRecvd.Octet = eapol_msg + 18;
v7 = eapol_msg[20] & 8;
if ( (eapol_msg[20] & 8) == 0 )
{
v23 = v5->EapolKeyMsgRecvd.Octet;
v24 = (v23[2] >> 4) & 3;
if ( *v23 == 2 )
{
rtl_memcpy_0(decrypted_data, v21->GTK[v24], v23[94] + (v23[93] << 8));
其中 v23 指向外部数据,然后从v23里面取出2字节的数据作为长度,调用rtl_memcpy将数据拷贝到栈上,decrypted_data大小为128字节,栈溢出。
该漏洞在最新版本中依然存在
v27 = sta->EapolKeyMsgRecvd.Octet;
v28 = (v27[2] >> 4) & 3;
if ( *v27 == 2 )
{
freertos_memcpy_0(&stack, v25 + 32 * v28 + 232, v27[94] + (v27[93] << 8));// 栈溢出
新漏洞
在分析漏洞时,确定了外部数据的流动,从而开展漏洞挖掘,最终发现一些漏洞
https://github.com/ambiot/amb1_arduino/issues/2
参考链接
https://www.vdoo.com/blog/realtek-rtl8195a-vulnerabilities-discovered
[原创] Realtek RTL8195A WIFI历史漏洞分析和新漏洞挖掘的更多相关文章
- CVE-2017-11882 漏洞分析总结 新手漏洞分析详细教程
CVE-2017-11882分析总结 注: 这篇随笔记录了CVE-2017-11882漏洞分析的整个过程,并介绍了相关调试软件的使用 漏洞信息 CVE-2017-11882属于缓冲区溢出类型漏洞,产生 ...
- Windows SMBv3 CVE-2020-0796 漏洞分析和l漏洞复现
0x00 漏洞描述 漏洞公告显示,SMB 3.1.1协议中处理压缩消息时,对其中数据没有经过安全检查,直接使用会引发内存破坏漏洞,可能被攻击者利用远程执行任意代码.攻击者利用该漏洞无须权限即可实现远 ...
- CVE-2018-12613phpMyAdmin 后台文件包含漏洞分析
一. 漏洞背景 phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库.借由此Web接口可以成 ...
- FakeID签名漏洞分析及利用(二)
本文转自:http://blog.csdn.net/l173864930/article/details/38409521 继上一次Masterkey漏洞之后,Bluebox在2014年7月30日又公 ...
- 从CVE-2018-1273看漏洞分析
漏洞分析的边界 漏洞分析最应该关注的是漏洞相关的代码,至于其余的代码可以通过关键位置下断点,来理解大概功能. 其中最关键的就是了解数据流,找到离漏洞位置最近的 原始数据 经过的位置,然后开始往下分析, ...
- weblogic之CVE-2018-3191漏洞分析
weblogic之CVE-2018-3191漏洞分析 理解这个漏洞首先需要看这篇文章:https://www.cnblogs.com/afanti/p/10193169.html 引用廖新喜说的,说白 ...
- CVE-2010-3971 CSS内存破坏漏洞分析
看了仙果版主的议题演讲,其中提到cve-2010-3971是一个浏览器漏洞利用中的里程碑.于是找来POC,尝试分析一下. 1.漏洞重现 XP SP3+ie6.0环境 poc如下: poc.htm &l ...
- 从乌云的错误漏洞分析看Mifare Classic安全
前言 12年2月初国内著名安全问题反馈平台-乌云发布了有关某公司员工卡的金额效验算法破解的安全问题.从整个漏洞分析来看,漏洞的提交者把员工卡的数据分析得非常仔细,以至很多刚刚接触或者未曾接触的都纷纷赞 ...
- 帝国CMS(EmpireCMS) v7.5配置文件写入漏洞分析
帝国CMS(EmpireCMS) v7.5配置文件写入漏洞分析 一.漏洞描述 该漏洞是由于安装程序时没有对用户的输入做严格过滤,导致用户输入的可控参数被写入配置文件,造成任意代码执行漏洞. 二.漏洞复 ...
- 帝国CMS(EmpireCMS) v7.5 前台XSS漏洞分析
帝国CMS(EmpireCMS) v7.5 前台XSS漏洞分析 一.漏洞描述 该漏洞是由于javascript获取url的参数,没有经过任何过滤,直接当作a标签和img标签的href属性和src属性输 ...
随机推荐
- vue-i18n 8.28.2(完成)
https://kazupon.github.io/vue-i18n/zh/introduction.html 开始 如果使用模块系统 (例如通过 vue-cli),则需要导入 Vue 和 VueI1 ...
- Windows 调试工具课程
本文是我在集团内部上的课程记录而成的博客内容.在本次课程里面将和大家介绍一些在 Windows 上常用的调试工具,以及调查问题的常见套路.适合于伙伴们入门 Windows 调试 本文以下内容是采用原本 ...
- [Tkey] CodeForces 1267G Game Relics
太神了这题,膜拜出题人 orz. 思考一 首先是大家都提到的一点,先抽卡再买.这里来做个数学分析. 假设我们还剩 \(k\) 种没有买,其实我们是有式子来算出它的花费期望的.WIKI 上提到,假设一个 ...
- angularjs中控制视图的控制器的两种注入依赖项及服务的写法
在AngularJS中,控制器是用于控制视图行为的重要组件.当定义控制器时,有两种主要的方式注入依赖项: 1. 显式依赖注入,聚聚使用字符串数组形式来注入依赖项: myapp.controller(' ...
- 全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法
全网最适合入门的面向对象编程教程:54 Python 字符串与序列化-字符串格式化与 format 方法 摘要: 在 Python 中,字符串格式化是将变量插入到字符串中的一种方式,Python 提供 ...
- 如何解决token过期问题 ?
首先 token 过期会导致请求不到数据 , 就不能准确渲染页面 ,此时的错误配置项的token是过期的,只要更新了token 拿着原先的配置项重新请求数据即可 :但是如果更新token的时候请求错误 ...
- 一、java的简单介绍
Java语言 Java是一门面向对象的程序设计语言,在语法上Java与C和C++类似,但丢弃了其相对难理解的一些特性,如操作符重载.多继承.自动的强制类型转换,同时Java语言不使用指针,而是引用,并 ...
- 5.29 相约杭州!云原生 Meetup 第二期杭州站开启报名
以容器技术和容器编排为基础的云原生应用,被越来越多的企业用户接受和使用,并且在生产环境中使用容器技术的比例逐年增加.KubeSphere 作为一款面向应用的开源容器混合云,经过 3 年的发展和 10 ...
- nginx实现资源文件动静分离的记录
Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离.严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat ...
- WebStorm 和 Rider 现在对非商业用途免费
JetBrains 在程序员节这一天在官方博客上发布了一篇文章:<WebStorm 和 Rider 现在对非商业用途免费>宣布了JetBrains将WebStorm和Rider IDE对非 ...