关于错误

CVE-2022-24355 允许网络相邻攻击者在受影响的 TP-Link TL-WR940N 路由器安装上执行任意代码。利用此漏洞不需要身份验证。该特定缺陷存在于文件扩展名的解析中。该问题是由于在将用户提供的数据复制到固定长度的基于堆栈的缓冲区之前缺乏对长度的正确验证。攻击者可以利用此漏洞在 root 上下文中执行代码。( www.zerodayinitiative.com )




阅读描述后,我认为该错误类似于常见的缓冲区溢出,它是通过发送对具有很长文件扩展名的文件的请求(例如,index.aaaa ..........aaaa)触发的。但是,这种情况是不同的。
 
 

重新创建错误

从名为httpd()的 init 函数中,要使程序调用httpRpmFs()函数,请求 url 必须包含“/fs/”或“/loginFs/”。





此外,请求中的referer ip 必须等于host ip 才能通过httpDispatcher()函数中的安全检查。





现在,关于易受攻击的函数,httpRpmFs()用于读取和响应请求文件的内容,如果它存在于 /tmp/ 或 /web/ 文件夹中。





起初,我认为缺陷是strcat(v2, v3)但是,v2和v3都是分配的并且仅在堆上使用。因此,我尝试将此httpRpmFs()与固定的进行比较。它们基本相同,只是如果您想读取 /tmp/ 文件夹中的文件,则需要进行新的安全检查。





根据该线索,我提出了几个读取 /tmp/ 中每个文件的请求,最后,当我尝试读取名为passwd的文件时,它崩溃了。查看调试器,请求的一部分被写入堆栈并导致溢出。




让我们回到代码,看看这是怎么发生的。在htttpRpmFs()函数中,成功读取文件后,程序将做出包含该文件内容的响应。

调用函数sub_5299E0()以检测与文件扩展名匹配的响应的 Content-Type。这是溢出开始的地方





函数sub_5299E0()通过创建指向文件路径末尾的指针来查找文件扩展名。之后,该点将向后移动,直到与“。”相遇。特点。最后,sub_5299E0()将复制 '.' 之后的所有字符。字符一个接一个,直到它遇到空字节。复制的字符将更改为上键并保存到堆栈中。在我们的例子中,passwd 没有文件扩展名,指针向后移动,传递文件路径,到达保存的请求头区域,只有在遇到最后一个'.'时才停止。在Referer部分的IP地址中。结果,将其复制到堆栈并覆盖保存的寄存器值之后的所有内容。在sub_5299E0()之后完成后,这些值被弹出回寄存器并导致程序崩溃。



 
 

编写漏洞

我没有实际的路由器,所以我使用固件分析工具包来模拟固件。经过一番研究,我发现路由器的 ASLR 默认是禁用的,所以我也在我的模拟器上禁用了 ASLR。由于程序没有保护,我将使用溢出错误将shellcode存储到堆栈中并运行它。



从上面的调试中,我创建了一个存储在请求的 cookie 部分中的有效负载。有效载荷包含 16 字节缓冲区、指向 shellcode 的堆栈指针和 shellcode。





一切看起来都很完美,我认为这很容易,但是该请求只会使程序在没有任何外壳或连接的情况下崩溃。我回去调试,发现问题出在toupper()函数上。shellcode 包含 0x61 到 0x7a 范围内的一些字节(ascii 中的“a”到“z”)。当通过toupper()函数(减去 0x20)时,这些字节将被更改,这会导致 shellcode 无法工作。



所以,我找到了一个绕过toupper()的解决方案,它在发送到路由器之前对 shellcode 进行编码。幸运的是,pwntool 库针对这种情况有一个 XORencode 函数。但是,经过编码后,shellcode 仍然有一个字节 0x70。




我试图反汇编 0x01c07027 并收到一条指令“ nor $t6, $t6, $zero ”。为了终止坏字节,我稍微更改了编码的 shellcode。由于 $t1 寄存器与 $t6 具有相同的用途,并且它没有在 shellcode 和编码中使用,因此我将 $t6 寄存器替换为 $t1 并且坏字节消失了。





此外,我了解到 MIPS 路由器具有缓存一致性,可通过异步读取和写入主内存来提高内存访问速度。在堆栈缓冲区溢出用 shellcode 地址覆盖存储的返回地址后,处理器将执行定向到正确的位置,因为返回地址是数据。但是,它执行的是仍然占用指令缓存的旧指令,而不是最近写入数据缓存的指令。为了使 shellcode 工作,我必须通过调用sleep()函数来刷新数据和指令缓存。我从旧的漏洞利用代码 ( www.exploit-db.com/exploits/46678 )中借用了一个 ROPchain,并对其进行了一些修改以适应我的情况。





该请求还需要编辑以匹配新的有效负载。




最后,漏洞利用完成并准备好运行。