EMUX仿真RV130的栈溢出整型利用 admin 102205文章 87评论 2023年3月7日08:54:56评论67 views字数 2976阅读9分55秒阅读模式 背景介绍 在本篇文章中将介绍如何使用EMUX固件仿真框架来为其手动添加设备模拟Cisco RV130路由器,并对设备中存在的固件漏洞进行相关利用复现,以实现远程未授权接管设备。 Cisco RV130 路由器是一款经济实惠且易于使用的设备,它可以为多个分支机构和远程员工提供高性能的网络连接,并且提供基本的企业级功能。这些功能包括千兆以太网、服务质量、IPv6支持和高级安全,被广泛应用于小型企业网络的构建。 EMUX 固件仿真框架是一组脚本、内核和文件系统,可与QEMU一起用于仿真 ARM 和 MIPS Linux IoT 设备。EMUX 旨在通过尽可能多地虚拟化物理设备来促进物联网研究。这是我们可以得到的最接近实际物联网虚拟机的方法。 固件分析 提取文件系统 通过binwalk解包后,得到squashfs文件系统,并确定其架构、端序等信息。 emux仿真固件 git clone --depth 1 --single-branch https://github.com/therealsaumil/emux.git clone完后直接修改配置文件,在官方文件中简明了新建设备时所需的一些文件配置。 到emux/files/emux目录中复制一份模板目录,其中放入刚解包好的rv130文件系统 kernel文件中保留对应系统架构的内核文件。 在编写config文件如下: 最后在/emux/files/emux/devices中追加一行。 RV130,qemu-system-arm-7.0.0,vexpress-a9,,,256M,zImage-2.6.39.4-vexpress,VEXPRESS2,Cisco RV130 Router 然后执行以下命令就可以部署emux的docker了。 ❯ ./build-emux-volume ❯ ./build-emux-docker 部署完成后 ./run-emux-docker启动docker 可以看到一些端口映射的信息。 输入launcher选择新加的固件后,提示登录时输入root后,选择 “start cisco-rv130”。 启动后看到80端口已经开放。 对照emux启动时的端口映射,访问127.0.0.1:20080即可。 但此时是无法登陆成功的,因为我们直接启动httpd服务的原因,绕过了系统本身的启动脚本preinit,导致确实了很多nvram关键值,而直接启动preinit初始化则又会导致直接down掉,具体原因即分析过程可参考链接中的文章。 https://www.ics-cert.org.cn/portal/page/121/8b078dd28bcf42dfaf894e585d880cea.html 因此我们需要emux固件中的config文件里添加相应的nvram值。 language=EN language_list=EN boot_hw_model=RV130 sysinfo_pid=RV130-E-K9-CN http_user0=rw,enc=0fa58742e186c8e5ce52ba133f8714cb,cisco http_user1=r,enc=3ff83912fdb4176a21cd5c93e2094554,guest admin_timeout=30 guest_timeout=30 http_user_count=2 至此才算模拟成功。 漏洞分析 产生原因 根据网上公布的事例来看漏洞是产生在管理界面登录时的password字段溢出所导致。 https://dl.packetstormsecurity.net/1906-exploits/ciscorv130w10344-overflow.txt 通过python构造request请求,可以看到在python脚本执行完后,80端口的服务便已经down掉。 而问题是出现在httpd服务上,因此通过ida进行分析发现在其中的sub_2C614()便是处理用户认证的相关函数。 接着可以跟踪到pwd字段的内容被保存到了 v37变量并传入到了 sub_2c4b0中里。 v16 = sub_1D170("pwd"); -> v37 = (char *)v16; -> v21 = sub_2C4B0(v36, v37, v20); 而在sub_2c4b0中 v37变量传参给了v14,追踪v14,到了sub_2bf64 v4 = sub_2BF64(v15, v14, &s, v13); 进而在sub_2bf64中又传参给了v5,而问题就出现在了后面,在strcpy函数中由于v26变量的空间不足以保存v5的内容,从而导致了溢出。 EMUX中GDB调试 接下来我们就要通过动态调试来进一步的跟进程序,判断程序的溢出点。 而在emux中使用gdbserver调试的话,则需要运行./emux-docker-shell 通过userspace 进入到用户空间,此时便可以查看用户进程,内存映射包括启动gdbserver等。 这里在emux中使用 gdbserver :9999 --attach $(pidof httpd) 附加到httpd进程上。 通过gdb-multiarch远程连接上去设置相应的参数。 官方介绍也可以通过 set sysroot target:/emux/RV130/squashfs-root 找到用于解析符号链接的二进制文件(尝试失败)。 且由于在过程中会存在多线程的情况,要通过 parent跟进父进程,不要进子进程。 pwndbg> set architecture arm pwndbg> set follow-fork-mode parent pwndbg> set solib-search-path /emux/RV130/squashfs-root/lib/ pwndbg> target remote 192.168.10.2:9999 在设置好调试环境后通过cyclic生成大量有序字符串进行测试: 断到了aema处,即446个字符即可产生溢出控制$pc寄存器。 EXP编写 由于程序之开启了nx保护,因此我们可以直接通过构造rop来进行漏洞利用。 而构造rop,首先就是需要找到libc加载基地址,在通过其基地址与libc库中的地址相加得到真实的地址,但无奈不清楚什么原因导致libc库中的地址和httpd加载后的地址对不上,导致ret2libc的方案失败。 而想要通过直接的ret2text将参数放到某个post字段里,则需要我们可控的参数地址在不能存在00字节的情况下也不能是栈空间内的地址、不能指向指针。 因此在本程序中只能换种法式迂回一下,参考某师傅的方案,通过整型溢出+ret2text的方式构造ROP。 通过找一个 add r0,x,x的代码段,让某两个寄存器相加,从而整数溢出得到一个包含00字节的地址后在传给r0寄存器。 其次就是要确定我们要执行的命令放在哪里,由于为了方便在执行较长命令的同时尽量避免影响其它参数的传递,这里选择了 change_action,记下地址后简单算一下得到我们要用来相加的地址。 即通过控制r4、r5寄存器为 0xeee85ac1和0x11223344即可得到其溢出的结果,也就是我们的目的地址0xa8e05。 至此完成利用,其exp构造如下: 原文始发于微信公众号(山石网科安全技术研究院):EMUX仿真RV130的栈溢出整型利用 点赞 http://cn-sec.com/archives/1247842.html 复制链接 复制链接 左青龙 微信扫一扫 右白虎 微信扫一扫
评论