华为HiSilicon硬件视频编码器中的后门

2020-09-18 22:28:06

更新2020-09-17:华为发布声明称,没有任何漏洞是由HiSilicon芯片和SDK封装引入的。随着更多信息的到来,我会更新这篇文章。

本文揭示了基于HiSilicon hi3520d硬件的IPTV/H.264/H.265视频编码器的严重漏洞。这些漏洞存在于这些设备上运行的应用程序软件中。所有漏洞都可远程攻击,并可能导致敏感信息泄露、拒绝服务和远程代码执行,从而完全控制设备。由于有多个供应商受到影响,而且在发布时还没有完全修复,这些编码器应该只在防火墙后的完全受信任的网络上使用。我希望我的详细写作能对物联网世界中更多的安全研究起到指导作用。

在我的研究期间,我接触到了以下供应商的几台设备:URayTech、J-Tech Digital和Pro Video Instruments。我最初在URayTech上进行了研究,然后确认了其他两个供应商的漏洞。

至少有十几家不同的供应商制造和销售非常相似的设备。通过分析产品文档和固件更新包,我有了很高的信心,这些设备也受到了这里列出的大多数(如果不是全部)漏洞的影响。以下是这些附加供应商的[不完整]列表:网络技术公司(NTI)、Oupree、MINE Technology、Blankom、ISEEVY、Orivision、WorldKast/Procode、Digicast。

据我所知,这些设备中的大多数都是在NAT/防火墙之后使用的。然而,我能够利用shodan.io识别公共互联网上的数百个设备,所有这些设备都可能被匿名远程攻击者利用。

硬件视频编码器用于IP网络上的视频流。它们将原始视频信号(如模拟、sdi、hdmi)转换为H.264或H.265流,并将其发送到视频分发网络(Youtube、Twitch、Facebook、…)。或者让用户通过RTSP、HLS等直接观看视频。通常,这些编码器具有允许管理员配置联网、编码参数、流选项等的Web界面。今天市场上的许多这样的设备都是基于hiSilicon(华为品牌)hi3520d arm SoC,运行一种名为hilinux的特殊Linux发行版,上面有一套用户空间实用程序和一个定制的web应用程序。

过去,人们已经对HiSilicon器件进行了安全研究。以下是一些现有出版物:

IP摄像机中的根外壳(俄语),Vladislav Yarmak,2013年。研究发现了允许通过telnet进行root shell访问的root密码。

伊斯特万·托斯(Istvan Toth)的HiSilicon DVR Hack,2017年。这项研究以DVR/NVR设备为目标,发现了一个使用提升的权限访问根外壳、后门密码、通过路径遍历泄露文件以及可利用的缓冲区溢出的漏洞。

全面披露:Vladislav Yarmak在基于小麦的DVR、NVR和IP摄像机的固件中存在0day漏洞(后门)。这项研究发现了一个非常有趣的“敲门”后门,允许远程攻击者启动telnet,然后使用几个已知密码中的一个登录。

虽然流媒体视频编码器可能与上述设备共享相同的硬件架构和底层Linux系统,但我的研究针对的是特定于视频编码器的管理Web应用程序,不会与前人的工作重叠。

这里有几张我有机会测试过的设备的照片。物理端口顶盖关闭。右侧,从上到下依次为:LAN、HDMI输出、重置、HDMI输入、LED、音频输入。让我们插上电源,连接到网络,开始探索吧!

$nmap-p 1-65535编码器...端口状态SERVICE23/tcp open telnet80/tcp open http554/tcp open rtsp1935/tcp open rtmp5150/tcp open atmp8086/tcp open d-s-n8554/tcp open rtsp-alt9588/tcp open未知。

登录提示符建议进行基本的HTTP身份验证,但这实际上是摘要身份验证。应用程序返回以下标头:

(正如我将在下面演示的那样,摘要不是应用程序支持的唯一身份验证方法)。

请注意,供应商自定义了界面,并且您的设备可以显示完全不同的内容,例如:但是,无论UI如何,底层功能(Web API调用)都是相同的。

管理员可以在多个部分执行各种任务,例如设置网络、调整编码器参数、上传图像以覆盖视频、升级固件等。

RTSP代表实时流协议。如果启用,用户可以直接从编码器观看视频流。

$curl-i rtsp://编码器:554RTSP/1.0 200 OKCSeq:1服务器:服务器版本9.0.6公共:选项,描述,播放,设置,SET_PARAMETER,GET_PARAMETER,TEARDOWN。

神秘的服务。Netcat连接,但服务器似乎对任何输入都没有反应。

这最初让我感到困惑,但在使用其他供应商的设备时,我注意到一些固件允许控制此端口:

$CURL-I http://encoder:9588HTTP/1.1 200OK服务器:nginx/1.6.0日期:清华,2018年3月22日14:28:13 GMT内容-类型:Text/html内容-长度:612上次修改时间:星期三,2018年12月5日10:58:31 GMT连接:Keep-aliveETag:";5c07af57-264";Accept-Ranges:Bytes<;!DOCTYPE html>;<;html>;<;head>;<;title>;Welcome to nginx!<;/Title>;...。

在Web界面周围单击,我注意到了备份功能:我立即开始备份(即下载)固件和配置。

$file up.rarup.rar:RAR存档数据,v4,os:win32$mkdir up$cd up$unrar../up.rar...

$tree-d.├──Disk├──ko│└──extdrv├──lib├──nginx│├──会议│├──html│├──日志│└──sbin└──Web├──css├──图像├──js└──Player└──图标。

$ls-l总计12756-rw-1根根307JUL 14 08:31 box.ini-rw-1根根6533364 JUL 14 08:31盒.v400_hdmidrwx-2根4096JUL 14 08:31磁盘-RW-1根根2972924 JUL 14 08:31 font.tf-rw。08:31 hostapd.confdrwx-3 root root 4096Jul 14 08:31 kodrwx-2 root root 4096 jul 14 08:31 libdrwx-6 root root 4096 jul 14 08:31 nginx-rw-1 root 1382400 jul 14 08:31 nosig.yuv-rw-1 root 38 jul 14 08:31 passwd-rw-1 root 211248 jul 14 08:31 png2bmp-rw。--1根根19213 JUL 14 08:30 RW-1根根6624JUL 14 08:30 RESET-RW-1根根968JUL 14 08:30 RW-1根根878JUL 14 08:30 udhcpc.script-RW-1根根191JUL 14 08:30 udhcpd.confdrwx-6根根4096JUL 14 08:31 web-RW。39166 7月14 08:31 wpa_cli-rw-1根根264069 7月14 08:31 wpa_requicant。

除了一些通用实用程序(hostapd、png2bmp、reSeries、wpa_cli、wpa_requicant)外,它还包含自定义Web应用程序box.v400_hdmi,它是编译后的二进制文件:

$file box.v400_hdmi box.v400_hdmi:ELF 32位LSB可执行文件,ARM,EABI5版本1(SYSV),动态链接,解释器/lib/ld-uClibc.so.0,已剥离。

这个可执行文件是我研究的主要目标,所有的漏洞都是在其中发现的。

更新2020-09-16:感谢Vladislav Yarmak迅速粗暴地强行执行此散列。原始密码似乎是newsheen。

我最初的想法是用常规的方法破解密码,但仔细考虑后,我有了一个更好的主意。就在主应用程序启动之前,运行脚本将密码文件复制到系统:

$cat-n run...。66 cp/tmp/passwd/etc/67 68 cd/tmp/69./Reset&;70./box.v400_hdmi

据我所知,此运行脚本在设备引导时执行,因此我需要做的全部工作如下:

使用openssl passwd命令可以轻松生成密码散列。让我们将密码设置为“root”:

我在Windows VM上使用WinRAR重新打包固件,以便与报告下级归档版本4和Win32平台的原始固件保持一致。我在WinRAR的参数中指定了RAR 4:

我通过Web界面将“新”固件上传到设备,重新启动,然后瞧:

$telnet编码器正在尝试10.7.7.51...已连接到编码器。转义字符是';^]';。(无)登录:rootPassword:root欢迎使用HiLinux。cmdline中未找到nfsroot。~#。

现在我有了对该设备的完全root访问权限,我可以转储所有类型的内容。

~#dmesg在物理CPU 0x0上启动linux初始化cgroup子系统cpuLinux版本3.18.20(root@ubuntu1604x32)(GCC版本4.9.4 20150629(预发行)(HiSilicon_V500_20180120))#4SMP Tue Jan 8 15:43:51 cst 2019CPU:ARMv7处理器[410fc075]修订版5(Armv7),cr=10c5387dCPU:pipt/vipt非混叠数据缓存,vipt混叠指令缓存机器型号:hiSilicon HI3520DV400演示板...。

HiSilicon(华为品牌)是一家专门为IP摄像机、NVR、IP视频和其他设备生产视频硬件的中国制造商。他们的hi3520d是一款受欢迎的SoC,适用于不同类型的此类设备。他们运行一个专门的Linux发行版,名为HiLinux。

~#psPID用户时间命令1根0:01初始化...。一堆内核内容...53 root 0:00{rcs}/bin/sh/etc/init.d/rcs 66 root 0:00udevd--daemon101 root 0:00{load}/bin/sh./load113 root 0:00 telnetd116 root 0:00{run}/bin/sh./run212 root 0:00udevd--daemon213 root 0:00udevd--daemon227 root 0:00{nginx}nginx:master process/tmp/nginx/sbin/ginx-p/tmp/ginx/228 root 0:00。/set229 root 3:59{main}./box.v400_hdmi230 root 0:09 nginx:worker process 245 root 0:12[rtw_CMD_THREAD]252 root 0:28./wpa_requicant-dwext-iwlan0-c/tmp/wpa_Supplicant.conf-d-B261 root 0:00。/em Serial-p 5150-s 9600 raw/dev/ttyAMA1。

查看此列表,您可以重新构建主Web应用程序的加载顺序:rcs→Load→Run→box.v400_hdmi。

通过操作这些脚本,我可以更改引导流,这在稍后的反向工程和调试过程中非常方便。我修改了/box/load,在我的子网上设置了一个静态IP地址,并注释掉了run脚本的执行。这样,我可以在重启后拥有一个干净的shell,在那里我可以按照我想要的方式启动可执行文件。

~#netstat-tulnp Active Internet Connections(仅服务器)Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program Name tcp 0 0 0.0.0.0:8554 0.0.0.0:*listen 229/box.v400_hdmitcp 0 0 0.0.0.0:554 0.0.0.0:*listen 229/box.v400_hdmitcp 0 0 0.0.0.0:1935 0.0.0.0:*listen 227/tcp 0 0.0.0.0:80 0。.0.0.0:*侦听229/box.v400_hdmitcp 0 0 0.0.0.0:9588 0.0.0.0:*侦听227/tcp 0 0.0.0.0:8086 0.0.0.0:*侦听229/box.v400_hdmitcp 0 0 0.0.0.0:5150 0.0.0.0:*侦听261/reemy altcp 0 0::23:*侦听113/telnetdudp 0 0 0.0.0.0:52579 0.0。.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:20080 0.0.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:20081 0.0.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:20082 0.0.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:20083 0.0.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:20083 0.0.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:20083 0.0.0.0:*229/box.v400_hdmiudp 0。Hdmiudp 0 0 0.0.0.0:3702 0.0.0.0:*229/box.v400_hdmiudp 0 0 0.0.0.0:34462 0.0.0.0:*229/box.v400_hdmi。

以下是关于谁在端口5150上监听的答案-它是重新串行的。再次处理信息:

RemSerial桥接本地串行端口和网络端口,允许网络上的实体与串行端口通信,前提是它们在机器上是本地的。HM…。这听起来不酷。我再次查看了dmesg,发现了以下内容:

串行:AMBA PL011 UART驱动程序12080000.uart:MMIO 0x12080000(irq=38,base_baud=0)的ttyAMA0是启用的PL011 rev2控制台[ttyAMA0]12090000.uart:MMIO 0x12090000(irq=39,base_baud=0)的ttyAMA1是PL011 rev2120a0000.uart:MMIO 0x120a0000(irq=40,base_baud=0)的ttyAMA2是PL011 Rev2。

我必须承认我不是硬件专家,但是我明白/dev/ttyama?是设备的UART的接口。我搜索了这个主板的UART规格,找到了这个PDF,我认为可能会有帮助,但我没有太多的时间来研究,所以我仍然不知道这个端口暴露是否可以被利用,以及如何利用。如果有人想黑这个,请就这么做!(发现什么请告诉我)

当sftp和rsync不可用时,我喜欢使用Netcat从远程系统拉取文件。幸运的是,设备上有NC。

首先,我启动一个tar存档进程,并将其输出通过管道传输到端口1337上的NC侦听器:

~#cd//#tar cf-bin引导盒等home lib mnt nfsroot opt root sbin share tmp usr|NC-LP 1337。

如上所述,主应用程序是此特定设备上名为box.v400_hdmi的可执行文件。其他设备可能会使用其他名称。这个应用程序是一个真正的主力-它监听多个端口,服务于web用户界面,并在幕后执行一系列低级任务。

~#PS-T|grep v400_hdmi 229 root 1:56{main}./box.v400_hdmi 233 root 0:25{disk.write}./box.v400_hdmi 234 root 0:00{tty_read}./box.v400_hdmi 235 root 0:01{main}./box.v400_hdmi 236 root 0:00{main}./box.v400_hdmi 253 root 0:00{route_check}./box.v400_hdmi 254 root 0:00{cept0_check}./box.v400_hdmi 253 root 0:00{route_check}./box.v400_hdmi 234 root 0:00{tty_read}./box.v400_hdmi 234 root 0:00{tty_read}。80}./box.v400_hdmi 255 root 0:00{cept1_8086}./box.v400_hdmi 256 root 0:26{mt2st_80}./box.v400_hdmi 257 root 0:00{cept0_554}./box.v400_hdmi 258 root 0:00{cept1_8554}./box.v400_hdmi 259 root 0:25{mt2st_554}./box.v400_hdmi 262 root 0:00{Discovery}./box.v400_hdmi 263 root 0:25{mt2st_554}。00{广播}./box.v400_hdmi 264 root 0:01{Timer}./box.v400_hdmi 265 root 0:00{srt:gc}./box.v400_hdmi1620 root 0:00{rtmp0}./box.v400_hdmi1621 root 0:00{hi_Aenc_get}./box.v400_hdmi1622 root 0:00{hi_Aenc_get}./box.v400_hdmi1622 root 0:00{hi_Aenc_get}./box.v400_hdmi1622 root 0:00{hi_Aenc_get}./box.v400_HDMI。

Tty_read是一个立即看起来可疑的线程。这是通过REMERSIAL处理ttyAMA1的那家吗?让我们看看哪些进程使用tty设备:

啊…。不,此线程似乎处理未通过重新串行…公开的ttyama2。好的,我们继续吧。

我不一定希望目标应用程序在调试期间设备引导时自动启动。我们可以通过修改/box/load脚本禁用自动启动来更改这一点:

...cd/tmp/ifconfig eth0 10.7.7.51网络掩码255.255.255.0#add:静态IP地址route add default gw 10.7.7.1 dev eth0#add:default gatewaychmod 777./run#./run#注释掉。

重新启动、telnet,然后看到一个干净的HiLinux。现在,让我们手动运行Web应用程序:

/tmp#./runchmod:lib/*:没有这样的文件或目录yid is index 0 mmz_start:0x90000000,mmz_size:256M*板卡工具:ver0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x120F00D0:0x00000001-->;0x00000000[结束]*板卡工具:ver0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x121A0400:0x00000000-->;0x00000008[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x121A0020:0x00000008-->;0x00000000[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x121A0020:0x00000000-->;0x00000008[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x12210400:0x00000000-->;0x00000007[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x12210010:0x00000004-->;0x00000000[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x12210008:0x00000002-->;0x00000002[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x12210004:0x00000000-->;0x00000001[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x120f00f8:0x00000000-->;0x00000001[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x120f00fc:0x00000000-->;0x00000001[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x120f0100:0x00000000-->;0x00000001[结束]*板卡工具:版本0.0.1_20121120*[调试]:{source/utils/cmdshell.c:167}cmdstr:himm0x120f0104:0x00000000-->;0x00000001[end]width_Height_Same_as_input(0):1 1920 1080venc_fps:30 vi_fps:30width_Height_Same_as_input(1):0 1280 720venc_fps:30 vi_fps:30width_Height_Same_as_input(2):0 640 360 venc_fps:30 width_Height_Same_as_input(3):0 640 360 venc_fps:30 vi_fps:30date-s 2018.03.22-22:22:22Thu Mar 22:22:22:22 ABC 2018ifconfig eth0 10.7.7.51网络掩码255.255.255.0route del default gw 0.0.0.0 dev eth0route:SIOCDELRT:no此类process route add default gw 10.7.7.1 dev eth0name erver 8.8.8.8 name erver 8.8.4.4初始化接口';驱动程序';文本;ctrl_interface';N/A';网桥配置文件';/tmp/wpa_requicant.conf';/tmp/wpa_requicant.conf';-&>读取配置文件';/tmp/wpa_supplicant.conf';ctrl_interface=';;/tmp/wpa_Supplicant.conf';/tmp/wpa_Supplicant.conf&39;读取配置文件WPA';/tmp/wpa_Supplicant.conf&39;读取配置文件WPA';/tmp/wpa_Supplicant.conf';读取配置文件WPA';/tmp/wpa_Supplicant.conf&39;读取配置文件。/var/run/wpa_requicant';优先级组0 id=0 ssid=';88888888';正在初始化接口(2)';wlan0';SIOCGIWRANGE:WE(编译)=22 WE(源)=16 enc_capa=0xf功能:key_mgmt 0xf enc 0xf标志0x0ioctl[SIOCSIWAP]:不允许操作WEXT:Operate State:LinkMode=1,OPERSTATE=5Own MAC地址:7c:a7:b0:40:95:48wpa_driver_wext_set_wpawpa_driver_wext_set_key:ALG=0 KEY_IDX=0 SET_TX=0 SEQ_LEN=0 KEY_LEN=0wPA_DRIVER_WEXT_SET_KEY:ALG=0 KEY_IDX=1 SET_TX=0 SEQ_LEN=0 SEQ_LEN=0 KEY_LEN=0wPA_Driver_WEXT_SET_KEY:ALG=0 KEY_IDX=2 SET_TX=0 SEQ_LEN=0 KEY_LEN=0wPA_Driver_WEXT_SET_KEY:ALG=0 KEY_IDX=0 SEQ_LEN=0 key_len=0wpa_driver_wext_set_countermeasureswpa_。DRIVER_WEXT_SET_DROP_UNENCRYTEDRSN:刷新驱动程序中的PMKID列表设置扫描请求:0秒100000使用EAPOL:SUPP_PAE进入状态DISCONNECTEDEAPOL:KEY_RX进入状态NO_KEY_RECEIVEEAPOL:SUPP_BE进入状态INITIALIZEEAP:EAP进入状态DISABLED使用现有控制接口目录。CTRL_IFACE BIND(PF_UNIX)FAILED:已在使用中的地址ectrl_iface,但不允许连接-假设它是强制程序终止的剩余部分成功替换了剩余的ctrl_iface套接字';/var/run/wpa_requicant/wlan0';新增接口wlan0Daemonize..http:80rtsp_udp_bind_port:20080http:554width_height_same_as_input(0):1 19201080venc_fps:30vi_fps:30width_Height_Same_as_Input(1):01280 720venc_fps:30 vi_fps:30width_Height_Same_as_Input(2):0640 360 venc_fps:30 vi_fps:30width_Height_Same_as_Input(3):0640 360 venc_fps:30 vi_fps:30HI_AACENC_VERSION=HiBVT_AACENC_INPUT(3):0640 360 venc_fps:30 vi_fps:30HI_AACENC_VERSION=HiBVT_AACENC。_V2.0.0.0HI_AACENC_VERSION=HiBVT_AACENC_V2.0.0.0BlkTotalSize:107Mbytepool ID:1,PhyAddr:96d3c000,virAddr:ae3c7000[HI35XXX_COMM_VPSS_Start]-128:HI_MPI_VPSS_CreateGrp失败,错误为0xFFFFFFFFF![StartVi]-272:启动VPSS失败![SetVpssMode]-102:获取VPSS Chn模式失败!vi:30->;Venc:30,码率:2800[SetRcParam]-431:HI_MPI_venc_GetRcParam err 0xffffffff。

应用程序将大量信息打印到控制台。我相信这在逆向工程和调试过程中会非常方便!

运行脚本在启动box.v400_hdmi之前做一些准备工作。让我们看看是否可以单独运行该应用程序。再次重新启动,然后

.