# Talos Vulnerability Report
### TALOS-2023-1695
## Milesight UR32L luci2-io file-export mib directory traversal vulnerability
##### July 6, 2023
##### CVE Number
CVE-2023-23547
##### SUMMARY
A directory traversal vulnerability exists in the luci2-io file-export mib functionality of Milesight UR32L v32.3.0.5. A specially crafted network request can lead to arbitrary file read. An attacker can send a network request to trigger this vulnerability.
##### 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 UR32L v32.3.0.5
##### PRODUCT URLS
UR32L –
##### CVSSv3 SCORE
6.5 – CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
##### CWE
CWE-22 – Improper Limitation of a Pathname to a Restricted Directory (âPath Traversalâ)
##### DETAILS
The Milesight UR32L is an industrial cellular router. The router features include support for multiple VPNs, a router console shell, firewall and many others.
The router offers many CGI endpoints, one of which is `cgi-bin/file-export`. This CGI endpoint allows for the various configuration files to be exported, based on parameters provided. This API is managed by the `luci2-io`âs `file-export` function. The `file-export` function parses the parameters provided, checks if the session provided is valid and then returns, if the parameters are valid, the content of the requested configuration file. Following the `file-export` function:
void file-export(void)
{
[… variable declaration …]
[…]
key_value_array[0].key = “sessionid”;
key_value_array[0].value = (char *)0x0;
key_value_array[1].key = “type”;
key_value_array[1].value = (char *)0x0;
key_value_array[2].key = “file”;
key_value_array[2].value = (char *)0x0;
[…]
is_ok = parse_data_and_url_decode(key_value_array,3); [1]
if ((is_ok == 0) ||
(is_ok = check_permission(key_value_array[0].value,”export”,”read”),
file_variable = key_value_array[2].value, type_variable = key_value_array[1].value,
is_ok == 0)) {
type_variable = “Export permission denied”;
}
else {
cgi_struct_cur = cgi_helper_structure;
struct_idx = 0;
do {
iVar2 = strcmp(type_variable,cgi_struct_cur->type);
if (iVar2 == 0) {
if (cgi_struct_cur->file == (char *)0x0) {
snprintf(EXPORT_FILEPATH,0x80,”%s%s”,cgi_helper_structure[struct_idx].filepath/dirpath,
file_variable); [2]
cgi_helper_structure[struct_idx].filepath/dirpath = EXPORT_FILEPATH; [3]
}
else {
[…]
}
iVar2 = ::pipe((int *)pipe_obj);
if (iVar2 == 0) {
__pid = fork();
if (__pid != -1) {
if (__pid == 0) {
iVar2 = -1;
close((int)pipe_obj[0]);
cgi_helper_structure[struct_idx].pipe_write_side = pipe_obj[1];
(*(code *)cgi_helper_structure[struct_idx].read_file_func)
(cgi_helper_structure + struct_idx); [4]
close((int)pipe_obj[1]);
}
[…]
}
[…]
}
[…]
}
struct_idx = struct_idx + 1;
cgi_struct_cur = cgi_struct_cur + 1;
} while (struct_idx != 0x61);
type_variable = “Export : incorrect file type”;
}
[…]
}
The function uses a static array with the different configuration info. Following the relevant portion of an element of this array:
char * type = “mib”
char * file = 0
char * filepath/dirpath = “/usr/share/snmp/mibs”
char * filename = “mib.txt”
char * respone_content_type = “text/plain”
code * read_file_func = read_file # function at 0x13a30
[…]
The relevant requestâs parameters are: `type` and `file`. The function will iterate over all the elements of the static array and will perform an action when the `type` field of the considered element is equal to the `type` parameter provided. Above it is shown the `mib` element.
The function parses, at `[1]`, the parameters provided. The function then iterates over all the elements in the static array as soon as the `type` matches the provided one. If the `file` field is not empty in the considered element, the `file` parameter is used at `[2]` to compose the pathname of the desired file using the `filepath/dirpath` field of the specified element. For instance, using the element shown above, at `[2]`, the composed string will have the following form: `/usr/share/snmp/mibs/`. Then the field `filepath/dirpath` is modified to be equal to the just-composed string.
In the case of the `mib` type, at `[4]`, the `read_file` function will be called, and the string composed at `[2]` will be used as pathname. Because the composed string at `[2]` is not sanitized, a directory traversal vulnerability exists in the `file-export` function, which can lead to arbitrary file read.
##### 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
##### Credit
Discovered by Francesco Benvenuto of Cisco Talos.
* * *
Vulnerability Reports Next Report
TALOS-2023-1710
Previous Report
TALOS-2023-1697Read More
References
Back to Main