Lucene search

K
talosTalos IntelligenceTALOS-2023-1763
HistoryOct 11, 2023 - 12:00 a.m.

Yifan YF325 libutils.so nvram_restore stack-based buffer overflow vulnerability

2023-10-1100:00:00
Talos Intelligence
www.talosintelligence.com
12
yifan yf325
libutils.so
nvram_restore
buffer overflow
vulnerability
network request
industrial cellular router
remote management
vpn services
iot applications
stack-based buffer overflow

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS

0.001

Percentile

42.6%

Talos Vulnerability Report

TALOS-2023-1763

Yifan YF325 libutils.so nvram_restore stack-based buffer overflow vulnerability

October 11, 2023
CVE Number

CVE-2023-34365

SUMMARY

A stack-based buffer overflow vulnerability exists in the libutils.so nvram_restore functionality of Yifan YF325 v1.0_20221108. A specially crafted network request can lead to a buffer overflow. 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.

Yifan YF325 v1.0_20221108

PRODUCT URLS

YF325 - <https://yifanwireless.com/entry-level-wifi-router/yf325-series-gprs/3g/4g-wifi-router-with-sim-card-slot.html&gt;

CVSSv3 SCORE

9.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-121 - Stack-based Buffer Overflow

DETAILS

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. The API that manages the nvram.cgi* endpoints uses the httpd’s parse_nvram_file function to manage the incoming data:

void parse_nvram_file(undefined4 param_1,int fd,size_t content_length)
  {
    [...]
    do {
      if ((int)content_length &lt; 1) break;
      read_size = 0x400;
      if (content_length + 1 &lt; 0x401) {
        read_size = content_length + 1;
      }
      read_bytes = wfgets(temp_buf,read_size,fd);
      if (read_bytes == 0) {
        return;
      }
      current_len = strlen(temp_buf);
      content_length = content_length - current_len;
      is_equal = strncasecmp(temp_buf,"Content-Disposition:",0x14);
    } while ((is_equal != 0) || (pcVar3 = strstr(temp_buf,"name=\"file\""), pcVar3 == (char *)0x0));
    while (0 &lt; (int)content_length) {
      read_bytes = wfgets(temp_buf,0x400,fd);
      if (read_bytes == 0) {
        return;
      }
      current_len = strlen(temp_buf);
      content_length = content_length - current_len;
      is_equal = strcmp(temp_buf,"\n");
      if ((is_equal == 0) || (is_equal = strcmp(temp_buf,"\r\n"), is_equal == 0)) break;
    }
    [...]
    restore_fd = fopen("/tmp/restore.bin","wb");
    [... read the request's uploaded file and write it into the "/tmp/restore.bin" file ...]
    res = nvram_restore("/tmp/restore.bin");
    [...]
    return;
  }   The `nvram_restore` function is defined in the `libutils.so` library:
  
undefined4 nvram_restore(char *filepath)

{
  [...]
  restore_fd = fopen(filepath,"rb");
  res = 0xffffffff;
  if (restore_fd != (FILE *)0x0) {
    [... calculate file_size ...]
    is_magic = strcmp(MAGIC,NVRAM_MAGIC);
    if (is_magic == 0) {
      nvram_clear();
      data_size = file_size + -0xc;
      elem_idx = 0;
      nvram_open();
      [... parse the number_of_elements ...]
      local_2c = &key_length;
      nvram_ver = (char *)0x0;
      while ((elem_idx &lt; number_of_elements && (0 &lt; data_size))) {                                              [1]
        key_length = 0;
        fread(&key_length,1,1,restore_fd);                                                                      [2]
        memset(nvram_key,0,0x80);
        fread(nvram_key,(size_t)key_length,1,restore_fd);                                                       [3]
        [...]
        fread(temp_byte,1,1,restore_fd);
        value_len = (uint)temp_byte[0];
        fread(temp_byte,1,1,restore_fd);
        value_len = value_len + (uint)temp_byte[0] * 0x100 & 0xffff;
        value_ptr = (char *)malloc(value_len + 1);                                                              [4]
        fread(value_ptr,value_len,1,restore_fd);                                                                [5]
        value_ptr[value_len] = '\0';
        data_size = data_size - 1 - key_length - 2 - value_len;
        is_nvram_ver = strcmp(nvram_key,"nvram_ver");
        [...]
        elem_idx = elem_idx + 1;
      }
      nvram_close();
      [...]
      nvram_commit();
      fclose(restore_fd);
      res = 0;
    }
    else {
      fclose(restore_fd);
      res = 0xfffffffe;
    }
  }
  return res;
}

The nvram_restore function will open the file specified by the filepath argument, parse the nvram variables defined in the file and commit the new set of nvram variables. The nvram-uploaded file contains several entries, which are parsed in the loop at [1]. Each loop iteration parses one entry. Each entry has the following layout in the file:

|  Key length | Key string (Key length bytes)  |  Value length |  Value string (Value length bytes) |

The entry’s key length is read at [2], this value is then used to read key length bytes into the nvram_key static buffer, at [3]. The read string is the nvram key. The nvram value buffer is dynamically allocated at [4] based on the nvram value’s length read, then at [5] value length bytes are read into the just-allocated buffer to read the nvram value.

Because the buffer used at [2] for the nvram key is a buffer of 128 bytes, but the length can have a value of up to 255, there is a stack-based buffer-overflow through the nvram key parsing. This function is reachable prior to authentication.

TIMELINE

2023-06-28 - Initial Vendor Contact
2023-07-06 - Vendor Disclosure
2023-10-11 - Public Release
2023-10-24 - Vendor Patch Release

Credit

Discovered by Francesco Benvenuto of Cisco Talos.


Vulnerability Reports Next Report

TALOS-2023-1765

Previous Report

TALOS-2023-1762

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS

0.001

Percentile

42.6%