找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 112|回复: 0

某路由器漏洞分析与多种栈溢出利用方法探究

[复制链接]

2万

主题

128

回帖

10万

积分

管理员

积分
105661
发表于 2021-12-30 19:15:45 | 显示全部楼层 |阅读模式 IP:山东省 移动/数据上网公共出口

登录后更精彩...O(∩_∩)O...

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 mind 于 2021-12-30 19:19 编辑

某路由器漏洞分析与多种栈溢出利用方法探究
路由器漏洞分析

问题出现在修改路由器ssid过程中由于对wlanssid 字段传入参数后的处理不严谨,导致溢出,外加/goform/set_wifi页面的未授权访问,从而可以通过远程缓冲区控制程序流程,获取shell

发送大量数据进行测试

可以看到goahead提示segmentation fault,上传gdbserver 进行动态调试测试

在mipsel中 通过./gdbserver 0.0.0.0:1234 /bin/goahead挂起程序,再在ubuntu中通过gdb-multiarch gohead启动goahead程序进行动态调试
再次发送payload测试,可以看到已经成功控制pc寄存器为maab,即填充148个字符即可覆盖pc寄存器

在正式利用之前,这里建议先关闭系统的aslr,以方便后续的调试


方式1:控制程序执行shellcode

既然已经明确了我们所能控制的寄存器,就要确定我们的目标是什么,比如要实现某个功能,需要控制哪些寄存器,之后构造需要确定下一步的跳转寄存器

1.寻找gadget1执行sleep函数

由于在MIPS架构下,叶子函数的返回地址是直接放在 ra 寄存器中,而非叶子函数需要调用另外的函数,这里的差异就造成了我们在利用叶子函数溢出时,且需要把当前的返回地址暂时存放在栈上,而利用方式便是先通过控制sleep(nS)来更新codecache,之后才能正确执行栈上的代码。
因此先控制a0=1,然后跳转执行sleep,控制a0可以通过mipsrop来寻找gadget,这里用0x005512c

第一步构造如下,此时s2为下一次跳转的地址,同时控制t9与$pc指向“dasy”

(这里省略了通过pwndbg中的vmmap来确定libc的基地址过程…)


2.寻找gadget2,控制$ra寄存器 提前设置返回地址

但此时如果控制s2为sleep函数的话,当然可以执行sleep,但执行完后程序也就结束了,因此上面的gadget并不能直接用,我们需要另外寻找一个gadget,能够在执行sleep之前设置函数的返回地址,然后再执行sleep函数,结束后返回到我们之前设置的返回地址上面,进而进行下一次的利用
可以通过mipsrop.tails()来查找,这里使用s1控制t9来设置下一次跳转的地址,并同时设置s0、s1、s2、ra等几个寄存器

payload构造结构如下

即先控制程序跳转到gadget1处,并同时设置s1\s2为sleep函数与gadget2的地址,在执行完gadget1设置a0=1后,
在跳转到gadget2处,通过其中代码段控制ra寄存器为“dddd”后执行sleep函数,当sleep函数执行完后,跳转到“dddd”处即ra寄存器中

3.寻找gadget3,提前设置下下次跳转的地址,与gadget4配合

这一步起着承上启下的作用主要与gadget4配合,以确保我们的shellcode可以放到最后面同时设置gadget4要跳转到的地址,即a1通过 mipsrop.stackfinder() 搜索gadget3,将上一步中的ra中换为gadget3

4.寻找gadget4

然后通过mipsrop.find(“move t9,t9,a1”) 来寻找我们需要的gadget4,放到第二步中$s0的位置。

5.放shellcode

最后我们放上shellcode测试,可以看到程序确实可以跳到shellcode上面,但pc的值为0x2806ffff,显然是需要我们来提供一个指针地址

因此将shellcode向后移,可以看到是成功执行完了shellcode的,但不清楚为什么没有一点反馈信息,直到最后的程序崩溃….

因此此路可能行不同,所以果断换路!
(这里非常迷惑,起初怀疑是shellcode的问题,也试过许多shellcode,包括pwntools中的shellcraft也不尽人意,希望有大师傅看到并了解的话,可以给我讲解一二)

方式2:利用libc中的函数构造rop

1.寻找命令执行函数

对于传统的pwn手来说,当然是首选libc中的system函数,但这里并没有….

之后尝试寻找exec系列函数或popen函数来利用
2.exec系列函数利用



这里先以execl为例演示,可以看到其函数所需有三个参数,对应寄存器也就是a0,a1,a2
而我们需要自由控制的参数也就只需要前两个就可以了
因此大概寻找gadgets的思路便是,控制a0、a1为栈上的地址,之后可以控制某值为0的寄存器mov到a2寄存器上
由于未保存之前的调试信息,且懒,所以直接放上最终的payload截图,针对其中的需要会对其11讲解

(1)首先就是寻找控制a0寄存器的gadgets1,同时我们要能确定赋完值后能跳到下一个gadgets中,这里选择0x34fcc


即本次gadget的下一跳地址位置为payload中第53行,且设置的$a0参数为第55行,其中的值0x7fff63e0便是paylaod最后的“ls -l\x00”的地址

(2)接下来找控制$a1寄存器的gadgets2,并且能保证我们传给a1的值是在上一步中可以直接控制的

那么最合适的便是0xc7a8,而此次跳转所需要修改的参数则是第52行,将其修改为任意值即可,其次本次的下一跳地址,也就是也就是程序中的第51行,其实$ra寄存器的值可以是随便位置(根据gadgets的不同,只要自己能确定可控就可以)


(3)最后来寻找gadget3,控制程序调转到execl函数中,但是需要注意这条指令尽量选择通过t9寄存器进行跳转到execl函数而不是ra寄存器,否则大概率错误会如下,蹦到错误的地址上去。而本次跳转后所需要修改的也就只有payload中的第54行即s2寄存器的值,也就是我们的execl函数。其次第60行的$ra寄存器改不改无所谓。



2.popen函数利用



由于只用修改两个参数的原因,所以大体上与execl函数的利用方法一致只需要主要r字符串的寻找,结尾处为\x00即可

3.结果
最后的最后不言而喻,都以命令执行失败而告终,但理论上是没问题的,失败原因同样令我费解
因为从gdb上来看,都是已经将execl或popen函数执行完了的,而且参数a0\a1\a2都没有任何问题,但就是咩有任何反馈信息….
另附上一张利用同等构造执行puts函数成功时的一个截图

方式3:终极方法,利用程序中的system…

在前两种方法都失败后 我突然意识到,既然可以将字符串放到payload的最后面从而避免\x00的截断。
那我将elf中的函数地址放到最后面岂不是同样可以正常执行,而需要执行的字符串,我只要通过其他方式存放到程序中,那不就可以正常执行调用了?

说干就干,既然利用程序中的system的话,我只需要能控制一个寄存器a0就可以了,其次对gadgets的要求便是最后返回到的地址必须要处于payload的末尾处 因此我找了一个这么长的gadgets,即最后跳转到的是 0x58+var_4(sp) 处,再次放上system函数的地址便可以了


接下来就是system参数的构造,也就是我们要执行命令的地址,字符串该写到哪里,经观察后发现才传过去的post请求中,cookie的值正好合适,且”user=admin“后便是空字符,所以我们只用在后面跟上命令,便可以轻易的在程序中去定其所在位置

最后开始构造payload,通过系统自带的ftpget下载完整的busybox,再通过完整版的busybox中的nc命令来连接在本地开启的8808端口,最最后成功反弹shell



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|IOTsec-Zone|在线工具|CTF WiKi|CTF平台汇总|CTF show|ctfhub|棱角安全|rutracker|攻防世界|php手册|peiqi文库|CyberChef|猫捉鱼铃|手机版|小黑屋|cn-sec|分享屋 ( 鲁ICP备2021028754号 )

GMT+8, 2024-5-3 14:20

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表