本篇文章主要是对使用了HiSilicon hi3520d和片上系统(SoC)构建的DVR / NVR设备的漏洞的分析,利用此漏洞会导致在Web界面未授权的远程代码执行(RCE),可以使被攻击设备被完全接管。
海思半导体是全球领先的多媒体ARM SoC解决方案供应商之一,该公司的SoC广泛应用于DVR,网络摄像机,NVR,智能手机等产品。Ambarella,海思,德州仪器是当今全球高清电视多媒体行业的三大先锋。HiSilicon DVR是海思公司生产的一种数字视频录像机。
首先应该学习一下官方的用户使用手册,然后进行深入分析,或者尝试提取固件,进行固件提取后分析会可能发现一些漏洞。
用于测试的DVR设备被称作“Seculink”
物理接口:
2个USB端口(用于控制GUI控制台的鼠标)
用于连接外接显示器的HDMI端口(VGA)(用于GUI和摄像头视图)
用于模拟闭路电视摄像机的4个BNC连接器
内部的SATA端口用于连接存储器来记录视频
用于网络访问的以太网端口
用户界面:
使用HDMI(或VGA)作为输出可以直接访问
通过HTTP进行网络访问来查看,控制摄像机
可直接访问Web界面,默认用户为“admin”,默认密码为空
在设置强密码之后,用户可能会觉得很安全了,其他人无法访问设备,但是人们经常将DVR设备的Web端口(tcp / 80)从安全的LAN(局域网)转发到WAN,以便从公网访问DVR(通过Shodan可以搜索到)。
提取固件有很多方法:
通过一些漏洞从设备获取
通过JTAG,串口控制从设备中获取
从网上查找固件包下载
虽然从官网下载固件包很简单,但我们选择最难的路,第一种方式提供了有关设备的其他信息
在DVR上进行全端口扫描,请注意,如果是root用户运行,默认情况下SYN扫描会非常慢
分析一下:
23 / tcp是telnet登录界面,需要用户名+密码验证
80 / tcp是Web登录界面
554 / tcp是rtsp服务;,它可以通过rtsp url打开:
打开rtsp界面也需要用户凭据验证
9527 / tcp似乎是一个保密的服务端口,具有一些非常有趣的功能
34567 / tcp和34599 / tcp是与DVR应用程序相关的一些数据端口
SDR设备应该是基于Linux系统的,连接到9527 / tcp(通过raw netcat)显示应用程序控制台的日志消息和登录提示,使用任何已定义的应用程序凭据登录都可以登陆,发现它为设备提供了root shell。
请注意,这显然是一个严重的安全问题,因为任何(低权限)应用用户都不应自动获取设备上的root shell。
在root shell中执行命令dmesg,可以看出DVR运行的是Linux内核(版本3.0.8),它有一个ARMv7 CPU,SoC模型是hi3520d。
从正在运行的进程列表中(ps)可以清楚地看到DVR应用程序正在监听34568 / udp,34569 / udp以及nmap()检测到的上述tcp端口。
从已装入的磁盘列表(命令)中可以清楚地看到固件映像在设备中(其中X = 0,1,2,3,4,5)。
固件文件非常小,因此如果我们想要将文件复制到设备或从设备复制文件,需要想点办法,幸运的是固件支持NFS,因此在主机上设置NFS服务器并从DVR安装固件就可以解决此问题:
获取固件:
要通过telnet接口(端口23 / tcp)访问设备,我们需要登录口令,查看可以拿到root用户的密码哈希:
假设密码是一串六个字符的小写字母,hashcat可以很快破解上面的DES hash:
因此,通过端口23 / tcp上的telnet接口登录用户root和密码xc3511是完全有可能的,在unclosable telnet界面上可访问的这个硬编码root帐户显然就是一个后门。
分析固件发现文件/var/Sofia是实现所有接口的主要应用程序,除了视频处理之外,所以这个二进制文件对我们来说似乎是最重要的。
但是加了混淆,这使得静态分析变得非常难:
因此,除静态分析(使用radare2或IDA)外,必须使用动态分析
进行动态分析,将GNU Project调试器(GDB)附加到远程 应用程序上,方法是将在远程设备上运行,并用从本地计算机上连接它。
当然,需要针对适当的ARM体系结构进行编译,为了编译它,我们可以使用 μClibc,它是嵌入式系统的C库(比如这里的DVR)。
有一个很好的编译环境叫做 Buildroot,它使编译非常简单,选择所需的应用程序(例如gdb) ,选择静态库,然后运行 。
现在固件已准备好然后开始逆向分析, 远程连接现在正在运行的进程上:
本地机器连接:
静态分析的推荐工具是Hex-Ray的 IDA Pro。
自动分析后有15.000多个函数,使用Python脚本找到auth函数。下面的 IDAPython 代码段可以找到“Users” 和 “Password” 相关的所有函数:
找到了一个函数:,对此函数快速分析后证实这就是验证函数
对硬编码字符串进行初步检查,发现一个后门密码,通用密码是:。
使用此密码,我们可以以任何用户(例如管理员)访问应用程序中的任何内容。例如,获取视频流:
或者在应用程序控制台(9527 / tcp)上获得root shell:
对auth函数深入分析发现:密码hash函数是sub_3DD5E4。它是一串MD5,有一些奇怪的转换,用Python逆向算法:
使用上面的哈希算法,可以设置任意密码
Sofia文件可以处理80 / tcp端口上的HTTP请求,可以对其进行fuzz测试。可以使用gdb附加调试,先杀死Sofia进程,然后使用gdbserver重新启动进程:
本地连接:
GET请求:
正常响应:
使用looong请求测试是否可以溢出:
响应是200,带有“404 File Not Found”消息,但我们可以在gdb中看到进程崩溃了
分析一下崩溃原因,远程进程Sofia得到了SIGSEGV(分段错误),堆栈中填充了输入的“a”字符,$ pc(程序计数器)寄存器中出现了输入的值(“aaaa” - 1) ,这是典型的堆栈溢出,这意味着我们有机会控制程序流程
测试:
这也可以导致SIGSEGV,并且$ pc寄存器是 ,我们的payload在$ sp + 0x14(堆栈基址+ 0x14)上开始执行
利用这种溢出的最方式是通过将一些shellcode注入到堆栈,然后将程序流重定向到shellcode,这样我们就可以在目标机器上远程任意代码执行。由于设备操作系统上没有权限分离,这意味着完全控制设备(root shell)。
设备上也有可能启用了一些漏洞利用缓解技术,这会使漏洞利用变得更难。
防止栈溢出的shellcode的最基本方法是No-eXecute(NX)技术,这可以防止在特定的内存页面上执行代码(通常是具有写入权限的页面,如堆栈)。
但是这个设备有些地方没有NX位设置(查看STACK,rwx):
或者在gdb gef中使用checksec。gef输出发现也没有其他的缓解措施,例如堆栈canary(因为如果存在堆栈canary,我们无法控制带有堆栈溢出的$ pc)。
在进行RCE之前,我们唯一应该知道的是堆栈地址。我们应该在paylaod的适当位置(上面的“wxyz”)写入地址$ sp + 0x14,以便将程序流重定向到shellcode。
还有一种缓解技术也可以使漏洞利用变得更难:地址空间布局随机化(ASLR),ASLR随机化存储段的基址(例如,堆栈的基址)。
发现确实启用了ASLR(“2”表示完全随机化,“0”禁用):
让我们首先尝试利用溢出来关闭ASLR。
按照上面的过程,我们得到SIGSEGV崩溃时堆栈地址($ sp)是0x5a26f3d8
所以payload应该是:
shellcode应该是我们想要执行的东西,最好是一个connectback shellcode。注意,必须避免一些“badchars”,:0x00,0x0d('\ n'),0x20(''),0x26('&'),0x3f('?'),此外,还有299字节的大小限制。
这里的shellcode使用socket,connect,dup2和execve系统调用写出了一个连接shell
发送payload进行漏洞利用,就可以拿到shell
首先要启动一个监听器:
然后发送shellcode:
使用 netcat 监听发送RCE命令
现在可以在远程系统上以root身份执行任意命令
但是还不能稳定漏洞利用,因为ASLR没有关闭,因此我们不知道shellcode起始地址
关闭ASLR并非易事,通常有两种方法可以做到:
在随机发生器中发现一些信息通过泄漏/覆盖来攻击它
泄漏远程二进制文件的随机内存地址。
经过一段时间的研究,发现无法泄漏,但后来想到了一个办法,Web服务器中存在一个漏洞:目录遍历漏洞。
目录遍历漏洞可以拿到root用户的hash密码:
此漏洞非常严重,因为攻击者可以读取任何文件,包括录制的视频(如果设备有一些HDD存储)。
此外,该漏洞可以帮助我们关闭ASLR。
该/proc文件系统包含了很多正在运行的进程信息,也就是/proc/[pid]目录。/proc可以获得列表GET ../../proc,这样我们就可以得到所有的PID。如果 /proc/[pid]/cmdline是/var/Sofia,就可以找到应用程序的PID。
关闭ASLR最重要的信息是 /proc/[pid]/smaps。此文件包含内存页统计信息,包含页面地址和其他信息(例如rss)。
例如:
这只是其中一页,该列表包含约150页。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!