CVE-2023-35965,CVE-2023-35966
Two heap-based buffer overflow vulnerabilities exist in the httpd manage_post functionality of Yifan YF325 v1.0_20221108. A specially crafted network request can lead to a heap buffer overflow. An attacker can send a network request to trigger these vulnerabilities.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Yifan YF325 v1.0_20221108
9.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE-190 - Integer Overflow or Wraparound
The Yifan YF325 is an industrial cellular router. This device is designed for M2M and IOT applications, allowing remote management, offering several VPN services and many other features.
The YF325 router provides a series of APIs. Many of those APIs, which expect to receive a POST request, use the manage_post
function to manage the received POST data:
void manage_post(undefined4 param_1,FILE **fd,int content_length)
{
[...]
if (post == 1) {
if (POST_DATA == (char *)0x0) {
POST_DATA = (char *)malloc(content_length + 1U); [1]
}
else {
POST_DATA = (char *)realloc(POST_DATA,content_length + 1U); [2]
}
if ((POST_DATA != (char *)0x0) &&
(data_end = wfread(POST_DATA,1,content_length,fd), [...])) { [3]
[...]
}
}
[...]
}
The first thing checked, after confirming that the request is actually a POST, is if the POST_DATA
global variable has already been initialized. Based on the answer, a malloc
or a realloc
is called to accommodate the actual request’s Content-Length
.
The Content-Length
is parsed in the manage_request
function:
void manage_request(void)
{
[... receive and parse the request until the start of the headers ...]
[... peforms some checks and parse on the received data ... ]
while( true ) {
[... tmp_buff is a buffer just after current_header buffer ...]
read_len = wfgets(current_header,(int)tmp_buff - (int)current_header,(char *)CLIENT_REQUEST_FD);
if (((is_equal == 0) || (is_equal = strcmp(current_header,"\n"), is_equal == 0)) ||
(is_equal = strcmp(current_header,"\r\n"), is_equal == 0)) break;
is_equal = strncasecmp(current_header,"Authorization:",0xe);
if (is_equal == 0) {
[...]
}
else {
is_equal = strncasecmp(current_header,"Referer:",8);
if (is_equal == 0) {
[...]
}
else {
is_equal = strncasecmp(current_header,"Host:",5);
if (is_equal == 0) {
[...]
}
else {
is_equal = strncasecmp(current_header,"Content-Length:",0xf); [4]
if (is_equal == 0) {
content_length_value_ptr = current_header + 0xf;
[...]
content_length_empty_space = strspn(content_length_value_ptr," \t");
content_length = content_length_value_ptr + content_length_empty_space;
CONTENT_LENGTH = strtoul(content_length,(char **)0x0,0);
[...]
while( true ) { [5]
URL_path_pattern = (code *)API_entry_cursor->URL_path_pattern;
[... find the correct API entry based on the URL path pattern ...]
}
[...]
post = 0;
is_equal = strcasecmp(request_method,"post");
if (is_equal == 0) {
post = 1;
}
if ((code *)API_entry_cursor->manage_request_data != (code *)0x0) {
(*(code *)API_entry_cursor->manage_request_data)
(request_URL+1,CLIENT_REQUEST_FD,CONTENT_LENGTH,boundary); [6]
}
[...]
}
The function will eventually parse, at [4]
, the Content-Length
. Then, at [5]
, based on the URL path, the correct API entry struct to use is located. At [6]
, the manage_request_data
function of the located API entry, if not null, is called. The manage_request_data
struct field, for several APIs, corresponds to the manage_post
function.
Many API URL paths will eventually call the manage_post
function. At [1]
for the malloc
function the requested size is content_length + 1
. The + 1
is used to ensure there is enough space for the null terminator. Because the content_length
value is never checked, it could correspond to the max unsigned integer, so, an integer overflow vulnerability exists at [1]
that can lead to a heap buffer overflow at [3]
.
Many API URL paths will eventually call the manage_post
function. At [2]
for the realloc
function the requested size is content_length + 1
. The + 1
is used to ensure there is enough space for the null terminator. Because the content_length
value is never checked, it could correspond to the max unsigned integer, so, an integer overflow vulnerability exists at [2]
that can lead to a heap buffer overflow at [3]
.
2023-06-28 - Initial Vendor Contact
2023-07-06 - Vendor Disclosure
2023-10-11 - Public Release
2023-10-24 - Vendor Patch Release
Discovered by Francesco Benvenuto of Cisco Talos.