Lucene search

K
talosTalos IntelligenceTALOS-2021-1428
HistoryJan 26, 2022 - 12:00 a.m.

Reolink RLC-410W "factory" binary firmware update vulnerability

2022-01-2600:00:00
Talos Intelligence
www.talosintelligence.com
29
reolink rlc-410w
firmware update vulnerability
arbitrary firmware update
authentication bypass
debug code
tcp port 2009
cwe-489

CVSS2

5

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

NONE

Integrity Impact

PARTIAL

Availability Impact

NONE

AV:N/AC:L/Au:N/C:N/I:P/A:N

CVSS3

7.5

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

NONE

Integrity Impact

HIGH

Availability Impact

NONE

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

EPSS

0.001

Percentile

51.3%

Summary

A firmware update vulnerability exists in the “factory” binary of reolink RLC-410W v3.0.0.136_20121102. A specially-crafted series of network requests can lead to arbitrary firmware update. An attacker can send a sequence of requests to trigger this vulnerability.

Tested Versions

Reolink RLC-410W v3.0.0.136_20121102

Product URLs

RLC-410W - <https://reolink.com/us/product/rlc-410w/&gt;

CVSSv3 Score

10.0 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-489 - Leftover Debug Code

Details

The Reolink RLC-410W is a WiFi security camera. The camera includes motion detection functionalities and various methods to save the recordings.

The Reolink RLC-410W uses a binary called factory, which is allegedly a leftover debug binary. This binary allows to perform, without authentication, several critical operations. For example, the upload of the firmware and the factory reset of the device.

The wait_for_connection function listens for UDP packets on port 2009:

undefined4 wait_for_connection(void)

{
  [...]
  sockaddr.sin_zero._8_4_ = 1;
  sockaddr_len = 0x10;
  sockaddr.sa_family = 2;
  sockaddr._0_4_ = 0;
  sockaddr.sin_zero._12_4_ = 0;
  sockaddr.sin_addr = 0;
  sockaddr.sin_zero._0_4_ = 0;
  sockaddr.sin_zero._4_4_ = 0;
  sockaddr.sa_data._2_4_ = 0;
  sockaddr.sa_data._6_4_ = 0;
  sockaddr.sa_data._10_4_ = 0;
  sockaddr.sa_data._0_2_ = 55559;
  [...]
      __fd = socket(AF_INET,1,0);
      [...]
        iVar2 = bind(__fd,&sockaddr,0x10);
        [...]
        memset(recv_data,0,0x400);
        sVar3 = recvfrom(__fd,recv_data,0x400,0,(sockaddr *)&sockaddr,&sockaddr_len);
        if (sVar3 &lt; 1) {
            [...]
        }
        else {
          if (recv_data._0_4_ == 0xfafafa) {                                                            [1]
            source_IP = inet_ntoa((in_addr)sockaddr.sin_addr);
            strncpy((char *)&IP_of_brodcaster,source_IP,0x17);
            IP_set = 1;
           [...]
            close(__fd);
            return 0;
          }
          [...]
}

At [1] it is checked if the received UDP packet contains, as first four bytes, the data \xfa\xfa\xfa\x00. If this is the case, the IP of the sender is saved and later used, by the factory binary, for connecting back to the sender on port 9123. With this connection, it is possible to interact with the factory binary and send several commands that the binary will execute.

The messages received by the factory binary, through the previously established connection, are elaborated and queued. Eventually, the received data reach the manage_recv_queue function. This function will iterate through the list of the queued messages and elaborate them.

The manage_recv_queue function:

undefined4 manage_recv_queue(factory *factory)

{
  [...]
  msg_cursor = (factory-&gt;msg_node).node_start;
  do {
    while( true ) {
      if (msg_cursor == (factory_msg_node *)&(factory-&gt;msg_node).node_end) {
        return 0;
      }
      factory_msg = msg_cursor-&gt;data;
      if (factory_msg-&gt;message_handling_status == UNHANDLED) break;
        [...]
    }
    if ((factory-&gt;is_update_preapre_ongoing == 0) || (factory_msg-&gt;message_cmd != 8)) {
      factory_msg-&gt;message_handling_status = HANDLING_WIP;
      [...]
        switch(factory_msg-&gt;message_cmd) {
        case 0:
          ret_code = get_Sp_data(factory,factory_msg);
          break;
        case 1:
          ret_code = sys_time_set(factory,factory_msg);
          break;
        case 2:
          ret_code = set_Sp_uid(factory,factory_msg);
          break;
        default:
          goto switchD_0040ec64_caseD_3;
        case 6:
          ret_code = check_if_filename_is_new_FW(factory,factory_msg);
          break;
        case 7:
          ret_code = check_if_filename_is_new_FW_2(factory,factory_msg);
          break;
        case 8:
          ret_code = update_command(factory,factory_msg);
          break;
        case 9:
          ret_code = maybe_sanity_check_command(factory,factory_msg);
          break;
        case 0xb:
          ret_code = factory_reset(factory,factory_msg);
          break;
        case 0xc:
          ret_code = probably_compare_uid(factory,factory_msg);
          break;
        case 0x11:
          ret_code = get_Sp_info_XML(factory,factory_msg);
          break;
        case 0x12:
          ret_code = speed_test_start(factory,factory_msg);
          break;
        case 0x13:
          factory_msg-&gt;message_handling_status = PROBABLY_COMPLETED;
          goto LAB_0040eec4;
        case 0x14:
          ret_code = speed_test_stop(factory,factory_msg);
          break;
        case 0x15:
          ret_code = speed_test_result_set(factory,factory_msg);
        }
    [...]
    }
    [...]
}

The manage_recv_queue will iterate through the message queue. If a message is UNHANDLED, the manage_recv_queue will execute the functionality specified in the message. The factory binary allows, without authentication, several critical functionalities: firmware update, device factory reset, setting the time and others. The update_command functionality will allow to upload a firmware file. If the uploaded firmware file passes a CRC check, the firmware will be updated.

The factory binary is, allegedly, a leftover debug binary and should not exist in a release version of the firmware.

Timeline

2021-12-13 - Vendor Disclosure
2022-01-19 - Vendor Patched

2022-01-26 - Public Release

CVSS2

5

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

NONE

Integrity Impact

PARTIAL

Availability Impact

NONE

AV:N/AC:L/Au:N/C:N/I:P/A:N

CVSS3

7.5

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

NONE

Integrity Impact

HIGH

Availability Impact

NONE

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

EPSS

0.001

Percentile

51.3%

Related for TALOS-2021-1428