Headline
CVE-2023-24497: TALOS-2023-1704 || Cisco Talos Intelligence Group
Cross-site scripting (xss) vulnerabilities exist in the requestHandlers.js detail_device functionality of Milesight VPN v2.0.2. A specially-crafted HTTP request can lead to arbitrary Javascript code injection. An attacker can send an HTTP request to trigger these vulnerabilities.This XSS is exploited through the remote_subnet field of the database
SUMMARY
Cross-site scripting (xss) vulnerabilities exist in the requestHandlers.js detail_device functionality of Milesight VPN v2.0.2. A specially-crafted HTTP request can lead to arbitrary Javascript code injection. An attacker can send an HTTP request to trigger these vulnerabilities.
CONFIRMED VULNERABLE VERSIONS
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Milesight VPN v2.0.2
PRODUCT URLS
MilesightVPN - https://www.milesight-iot.com/milesightvpn/
CVSSv3 SCORE
8.3 - CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H 9.6 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H - chain: TALOS-2023-1702
##### CWE
CWE-80 - Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
DETAILS
The MilesightVPN is a software that make easier the setup of VPN tunnel for the Milesight products and allow to monitor the connection status with a web server interface.
The MilesightVPN exposes the /Device_Auth API used to authenticate to the server and to get the an OpenVPN configuration file. This API is for the various Milesight devices, the API requires as data the serial number, the authentication code, the device name and the subnet of the device. Essentially the API expects four entries in the POST payload:
- authcode: is a secret generated by the MilesightVPN
- subnet: the subnet mask of the main network used by the device
- device_name: the identifier of the device that is connecting to the MilesightVPN server
- sn: is the serial number of the device that is connecting to the MilesightVPN server
After been registered, the device will appear in the Device table showing the provided information. This Device table is in the landing page after the login.
Following the relevant portion of the Embedded JavaScript template related to the device table:
<table class="table table-no-bordered" data-striped="true" data-height="100%" id="tbl_content" data-toggle="table" data-url="/detail_device" data-target="/detail_device" data-id-field="sn" data-pagination="true" data-sort-stable="true" data-sort-name="connect_time" data-sort-order="asc" data-toolbar="#deviceToolbar" data-search="true" data-search-on-enter-key="true" data-cache="false">
<thead>
<tr>
<th data-field="name" data-width="15%" data-sortable="true" data-formatter="name_formatter"><%=lang.detail.device.name%></th>
<th data-field="status" data-width="10%" data-sortable="true" data-formatter="status_formatter"><%=lang.detail.device.status%></th>
<th data-field="sn" data-width="10%" data-sortable="true"><%=lang.detail.device.sn%></th>
<th data-field="virtual_ip" data-width="15%" data-sortable="true"><%=lang.detail.device.virtualip%></th>
<th data-field="real_ip" data-width="15%" data-sortable="true"><%=lang.detail.device.realip%></th>
<th data-field="remote_subnet" data-width="15%" data-sortable="true" data-formatter="subnet_formatter"><%=lang.detail.device.subnet%></th>
<th data-field="connect_time" data-width="15%" data-sortable="true" data-formatter="time_formatter"><%=lang.detail.device.time%></th>
<th data-field="history" data-width="10%" data-formatter="history_formatter"><%=lang.detail.device.history%></th>
</tr>
</thead>
The data of this table is filled using the requestHandlers.js’s detail_device function:
function detail_device(res,postdata,connection){
var $sql="select * from device";
$sql+=' left join ';
$sql+=' (select count(*) as total,remote_subnet from device group by remote_subnet) repeatsubnet on repeatsubnet.remote_subnet=device.remote_subnet';
var result={};
connection.query($sql).then(function(data){
if(data['error'])
{
res.write(JSON.stringify(result));
res.end();
}
else
{
if(data['result'].length>0)
{
result=JSON.stringify(data['result']);
res.writeHead(200,{'Content-Type':'application/json','Content-length':Buffer.byteLength(result, 'utf8')});
res.write(result);
res.end();
}
else
{
res.write(JSON.stringify([]));
res.end();
}
}
});
}
The device table has the following schema:
+---------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| name | varchar(255) | YES | | NULL | |
| sn | varchar(12) | NO | PRI | NULL | |
| virtual_ip | varchar(15) | YES | | NULL | |
| real_ip | varchar(32) | YES | | NULL | |
| remote_subnet | varchar(32) | YES | | NULL | |
| connect_time | int | YES | | NULL | |
| status | int | YES | | NULL | |
+---------------+--------------+------+-----+---------+-------+ The `device` table is populated through the registered devices, so through the `/Device_Auth` API.
From when a Milesight device is registered, using the /Device_Auth API, until showing its data in the web interface, no checks about the data are performed, this can lead an XSS vulnerability. An attacker can upload malicious Javascript code through the /Device_Auth API, registering a device. An admin of the server would execute this malicious javascript whenever they viewed the details page due to the stored XSS. An attacker would need to know the Authorization Code of the server to actually use the /Device_Auth API. But because TALOS-2023-1702 this information can be easily retrieved by an attacker.
CVE-2023-24496 - XSS in the name field
An attacker can upload malicious Javascript code through the /Device_Auth’s device_name parameter. The device_name value will be stored in the device database as the name field.
CVE-2023-24497 - XSS in the remote_subnet field
An attacker can upload malicious Javascript code through the /Device_Auth’s subnet parameter. The subnet value will be stored in the device database as the remote_subnet field.
VENDOR RESPONSE
Since the maintainer of this software did not release a patch during the 90 day window specified in our policy, we have now decided to release the information regarding this vulnerability, to make users of the software aware of this problem. See Cisco’s Coordinated Vulnerability Disclosure Policy for more information: https://tools.cisco.com/security/center/resources/vendor_vulnerability_policy.html
TIMELINE
2023-02-14 - Initial Vendor Contact
2023-02-21 - Vendor Disclosure
2023-07-06 - Public Release
Discovered by Francesco Benvenuto of Cisco Talos.
Related news
Given the privileged position these devices occupy on the networks they serve, they are prime targets for attackers, so their security posture is of paramount importance.
In all, Cisco Talos is releasing 22 security advisories today, nine of which have a CVSS score greater than 8, associated with 69 CVEs.
In all, Cisco Talos is releasing 22 security advisories today, nine of which have a CVSS score greater than 8, associated with 69 CVEs.