CVE-2023-39367
An OS command injection vulnerability exists in the web interface mac2name functionality of Peplink Smart Reader v1.2.0 (in QEMU). A specially crafted HTTP request can lead to arbitrary command execution. An attacker can make an authenticated HTTP request to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Peplink Smart Reader v1.2.0 (in QEMU)
Smart Reader - https://www.peplinkworks.com/Smart-Reader.asp
9.1 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
CWE-78 - Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)
The Peplink Smart Reader is the access-control hardware associated with the PepXIM Time-Logging and Security System. It is used to manage access to buildings, workstations and public transit, as well as for employee time management.
The Peplink Smart Reader exposes a web server on ports 80 and 443 intended for local configuration and control of the card reader. One of the endpoints accessible on this web interface is /cgi-bin/api.cgi
, backed by the binary located at /web/cgi-bin/api.cgi
. A vulnerability exists in the function responsible for handling mac2name
requests which allows an authenticated attacker to execute arbitrary commands on the device.
Requests destined for api.cgi
are initially passed to a function located at offset 0x437ab0
which we refer to as api_handler
. This function extracts four common parameters (option, type, poll_by and mode
) from the POST body and further dispatches the request based on the contents of option
, type
and mode
. The vulnerable function is reached when the request is successfully authenticated, the mode
parameter is set to info
, type
is set to json
, option
is set to xws
and func
is set to mac2name
. With those preconditions, the request will be handled by a function located at 0x438930
which we refer to as xws_handler
. This function queries a Peplink API endpoint for the name associated with a particular MAC address. The way this is done is vulnerable to an OS Command injection of the mac
parameter. An annotated decompilation of this function is included here for reference.
00438930 int32_t xws_handler(int32_t* arg1)
00438930 {
00438930 // [1] Compare the value of the `func` parameter to "mac2name"
00438988 if (strcmp(SafecgiGetValue("func", ""), "mac2name") == 0)
00438988 {
004389d8 char template_filename[0x19];
004389d8 __builtin_strncpy(&template_filename, "/tmp/_xws_doc_tmp.XXXXXX", 0x19);
00438a04 char url[0x80] = {0};
00438a20 char command[0x100] = {0};
00438a20
00438a60 // [2] Construct a URL (and subsequent OS command) using the attacker-controlled `mac` parameter
00438a60 snprintf(&url, 0x80, "%s?option=mac2name\&mode=text\&m…", "http://ws.peplink.com/api1/", SafecgiGetValue("mac", ""));
00438a98 snprintf(&command, 0x100, "(%s %s -T %d -O %s) > /dev/null", "/bin/wget_https", &url, 10, &template_filename);
00438a98
00438aa8 // [3] Execute the constructed command with root privileges
00438aa8 system(&command);
00438aa8
00438ac0 // [4] Finalize API response to user
00438ac0 int32_t $v0_4 = load_taglist_ex(&var_38, 1, 0);
00438ad4 unlink(&var_38);
00438adc if ($v0_4 != 0)
00438adc {
00438aec int32_t i = 0;
00438ae8 if (*(uint32_t*)$v0_4 > 0)
00438ae8 {
00438b44 do
00438b44 {
00438b00 int32_t* $v1_2 = *(uint32_t*)(*(uint32_t*)($v0_4 + 0xc) + (i << 2));
00438b04 i = (i + 1);
00438b34 json_object_set_new_nocheck(arg1, *(uint32_t*)$v1_2, json_string(escape_html_character($v1_2[1])));
00438b08 } while (i < *(uint32_t*)$v0_4);
00438b3c }
00438b50 free_taglist($v0_4);
00438b70 return 1;
00438b70 }
00438aec }
004389a8 return 1;
004389a8 }
At [1]
we see the final precondition being enforced, which is that the func
parameter must match mac2name
. If that is the case, then a URL is constructed (at [2]
) which contains the attacker-controlled POST parameter, mac
. It is expected that this parameter will be an appropriately formatted MAC address, but no such checks are conducted. The constructed URL is passed to a system command (at [3]
) intended to query the http://ws.peplink.com/api1/
endpoint, but since no validation occurs, it is possible for the value in mac
to escape from the expected command and execute arbitrary OS commands with root privileges.
An authenticated attacker can leverage this vulnerability to execute arbitrary commands on the device with root privileges and elevate their access to the vulnerable system.
The vendor links to new firmware versions at the end of their advisory: https://forum.peplink.com/t/peplink-security-advisory-smart-reader-firmware-1-2-0-cve-2023-43491-cve-2023-45209-cve-2023-39367-cve-2023-45744-cve-2023-40146/47256
2023-11-30 - Vendor Disclosure
2024-04-17 - Vendor Patch Release
2024-04-17 - Public Release
Discovered by Matt Wiseman of Cisco Talos.