距离上一篇 Blog 更新已经快一个月了,想了想应该给长草的 Blog 除除草了。于是从我的笔记文档里翻了一下, 把这个漏洞翻出来给大家分享分享。具体官方通告可以参考:
众所周知 UPNP相关的程序在路由器上是经常出现漏洞的。这次也不例外, PSV-2020-0437 的漏洞也是出现在 UPNP 的相关处理代码中。我们从刚解压出来的文件系统中提取出 upnpd 程序, 然后我们用 ida pro 打开。
该函数会对输入的数据进行部分解析,例如 M-SEARCH
、ssdp:discover
等关键词, 本次的漏洞是在 sub_22D20
函数中发生的, 我们点进去查看下这个函数。
由于漏洞的根本原因是 strncpy
的缓冲区溢出, 我们知道 strncpy
函数在溢出的时候会存在 \x00
截断。然而程序每次不同链接使用的是同一块内存, 我们可以在第一次 recvfrom
的时候在栈上布局好 rop, 然后通过栈迁移跳转到布局好的 rop 上。
另外最终我期望通过调用 system
函数执行任意命令, 因此我需要在 bss 这样全局的地址上写入命令, 因此我需要找对应可以往任意地址写入值的 gadget 。 在 arm 的汇编中,写入值的汇编指令为 str
1 | $ ropper -f usr/sbin/upnpd --search "str r?" |
对于这样的需求,我从这些 gadget 中选取了 0x0002dd4c: str r6, [r5]; pop {r3, r4, r5, r6, r7, pc};
这条指令, 通过控制 r5、 r6 寄存器,我们可以将任意值从r6 写到 r5 所指向到地址中。然后我通过 for 循环就可以构造出将任意字符串,写到任意地址中的 rop 链
最后呢,在找一条 mov r0, r?, bl system
这样的gadget, 将为可控的 R3
到 R7
寄存器中的一个覆写成刚刚写入了命令的地址,然后将值 mov 到 r0
寄存器上。 因为 arm 到参数传递是由寄存器传递的,通过控制 r0
寄存器, 我们就可以控制 system
执行任意命令。