NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

admin 2022年8月15日21:28:29评论57 views字数 3416阅读11分23秒阅读模式

关于漏洞

此漏洞允许网络相邻攻击者在多个 NETGEAR 路由器的受影响安装上执行任意代码。利用此漏洞不需要身份验证。该特定缺陷存在于 httpd 服务中,该服务默认侦听 TCP 端口 80。解析字符串文件时,该过程在将用户提供的数据复制到固定长度的基于堆栈的缓冲区之前未正确验证其长度。攻击者可以利用此漏洞在 root 上下文中执行代码。

( www.zerodayinitiative.com )

看完描述后,尝试使用 Bindiff,结合漏洞描述,在 http_d() 函数处撤销作用域。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

通过bindiff的流程图和IDA上的反编译代码,我发现String Table Upload的参数解析段被去掉了。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

易受攻击的版本

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

补丁版本

我可以确定漏洞在字符串文件表上传中。经过一段时间的搜索,我发现了 Create_Hashtable() 函数中的漏洞。该漏洞发生在 gui_region 被复制到堆栈上的数组而没有事先检查大小时。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

新创建错误


首先我将简单地谈谈字符串文件表上传。String File Table Upload用于上传语言、版本等配置文件,该函数提交的文件内容将由http_d()函数处理。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

字符串文件表上传的内容

http_d() 函数将接收来自套接字的请求。检查请求是否针对文件上传功能。如果为true,将执行文件上传函数,否则将调用sub_10764() 函数。sub_10764() 负责解析 HTTP 请求、执行身份验证、调度请求等。


虽然这个版本已经去掉了strtblupload.cgi,但是我发现String File Table Upload的参数和其他上传文件函数的参数在同一个地方执行,没有检查URL是否正确。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

看了httpd()函数的http请求的参数解析,发现可以利用upgrade_check.cgi函数进入String File Table Upload的参数解析。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

我将编辑请求的某些部分,以便 http_d() 跳转到字符串文件表上传函数。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

解析请求参数后,文件内容将分为header和body。标头包含 file_size 和校验和。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

正文部分被复制到文件 /tmp/strtbl 然后重命名为 /tmp/strtbl.bz2 并通过文件检查。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

完成后,文件被解压缩并带有 2 个主要参数:语言和版本。语言参数将被传递给 reloadHashTable()。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

然后将调用 reloadHashTbl() 函数。该函数的主要功能是解析文件,为文件中的语言、版本等参数创建一个hash,创建一个单独的内存区域,并将这些参数的内容保存在相应的内存区域中。但是 reloadHashTbl() 函数在将参数内容保存到内存时不会检查大小,因此我可以通过语言参数将有效负载发送到 gui_region。


reloadHashTbl() 函数完成后, stringOut() 函数将用于获取存储在语言和版本的哈希字符串区域中的内容,然后将内容传递给 langSaveNvram() 函数以将语言的内容复制到 gui_region ,并将版本的内容放入 str_tbl_non_en_ver。现在我们的有效载荷位于 gui_region 中。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

现在回到 reloadHashTbl() 函数。该函数将调用 Create_Hashtable() 函数。要到达漏洞位置,我将不得不发送另一个字符串文件表上传请求以重新进入此函数,然后我们的有效负载将从 gui_region 复制到堆栈,从而导致基于堆栈的缓冲区溢出。但在进入漏洞位置之前,我必须满足条件“multiLanguageReadLangTblMTD(v2) == -1”。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

因为Create_Hashtable()函数调用了multiLanguageReadLangTblMTD()函数来检查条件来判断是创建默认的String File Table,还是使用我发送的文件。为了检查条件,mtdn_lang_name 中的内容将与传递给 reloadHashTable() 的语言参数进行比较以检查。NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

调用 Create_Hashtable() 之前的 reloadHashTbl() 函数会先调用 checkStringTblInMTD()。该函数将读取我们文件的内容,并将每种语言的 64 字节内容、版本参数分别复制到 mtd9_lang_name 和 mtd9_lang_version。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

因此,为了满足我想要的条件,我只需要传输超过 64 个字节的任何字符。我终于确定了错误的位置和条件,现在让我们开始利用吧。


写作漏洞

由于以下几个因素,利用此堆栈溢出有点复杂:

+ httpd 的 NX 位已设置。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

+ 设备 ASLR 设置为 1,表示栈和库地址不固定。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

+ 溢出堆栈的副本是字符串副本。因此,如果遇到 NULL 字符,它将停止复制字符。因此,漏洞利用不能包含具有 NULL 字节的小工具。


首先,由于已经设置了 NX 位,我将不得不执行其他漏洞利用技术,例如 ret2libc。但是由于 ASLR 的存在并且没有堆栈地址泄漏,我们将更加难以找到正确的 ROP。Create_Hashtable()函数是一个漏洞函数,所以我会在这个函数刚刚执行完之后得到栈地址作为计算的基础。调试了一会,找到了我们发送文件时保存请求的地址。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

我继续找出是否有一个 ROP 可以帮助我将 sp 寄存器调整到存储请求的内存区域。最初在解析请求期间,直到请求结束的文件内容将被 fwrite() 复制,所以我可以在这里传递任何字节。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

搜索后我会得到地址 0x 009C640 作为 ROP1。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

现在堆栈已经到了我想要的位置。接下来我会想办法利用sp寄存器的地址作为系统的参数。经过一段时间的搜索,我找到了地址0x009FB74,它可以帮助我将sp传递给r0并调用系统,这将是ROP2。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

我无法像往常一样将语言参数与有效负载一起传递。如果内容长于64字节,就会进入错误位置,但是我们的String File Table会被替换为默认文件,导致gui_region包含了默认文件的内容。也就是说,我必须想办法让语言参数既包含有效载荷又满足小于65字节的条件。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

正如我之前提到的,传递给 reloadHashTable() 函数的语言参数将在第一次解包后被解析。在查找语言参数的解析过程中,程序一直读取到文件末尾。所以我可以利用这一点来创建另一个包含 64 字节任意字符的语言参数。此外,对于包含有效负载的语言参数,我将删除字符字节 ' ' ',以便 stristr() 函数忽略包含有效负载的语言参数。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

所以在解析时,会读取包含 64 字节字符的语言参数并将其传递给语言变量,我可以确定 Create_Hashtable() 函数将使用用户文件。但是还有一个问题,有两个这样的语言参数会导致为这两个参数创建两个内存区域。所以我需要查看将返回哪个参数的内容。在查看了 insertMultiLangugeHashTable() 函数后,我发现该函数将创建一个单链表来包含具有相同参数的内容。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

在函数 getMultiLanguageStrByKey() 中,我可以很容易地看到列表的第一个参数将被检索。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

因此,我会将带有有效负载的语言参数放在前面,然后将带有 64 字节字符的参数放在后面。所以我确保你提交的文件会被使用,并且payload仍然被写入gui_region。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

由于会先读取gui_region,然后再写入新的内容,因此只有在发送第一个请求时才会将payload保存到gui_region。为了触发漏洞,我将发送第二个请求,这次读取 gui_region 时,它将包含我们的有效负载,导致基于堆栈的缓冲区溢出。另外因为我必须发送 2 个请求,所以包含请求的内存区域会发生变化,加上导致错误的函数是 strcpy()。所以我会在发送request1时将ROP1放在文件中,而ROP2将放在request2的末尾。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

用户上传的字符串文件表中的ROP1

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

请求 2 中的 ROP2

用request2除了把ROP2放在请求的末尾外,我会留下大于64字节的语言参数的内容才能触发漏洞。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

完成所有步骤后,我现在将继续编写 Python 脚本并运行它。

NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

文章翻译自:

https://blog.viettelcybersecurity.com/netgear-r6700v3-1day-analysis-cve-2021-34982-buffer-overflow-rce-vulnerabiliy-2/

原文始发于微信公众号(Ots安全):NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月15日21:28:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   NETGEAR R6700v3:1 天分析 (CVE-2021-34982) 缓冲区溢出 RCE 漏洞http://cn-sec.com/archives/1235967.html

发表评论

匿名网友 填写信息