Talos Vulnerability Report

TALOS-2017-0436

Circle with Disney Rclient SSH Persistent Remote Access Vulnerability

October 31, 2017
CVE Number

CVE-2017-12084

Summary

A backdoor vulnerability exists in remote control functionality of Circle with Disney running firmware 2.0.1. A specific set of network packets can remotely start an SSH server on the device, resulting in a persistent backdoor. An attacker send an API call to enable the SSH server.

Tested Versions

Circle with Disney 2.0.1

Product URLs

https://meetcircle.com/

CVSSv3 Score

8.0 - CVSS:3.0/AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-489: Leftover Debug Code

Details

Circle with Disney is a network device used to monitor and restrict internet use of children on a given network. When connected to a given network and configured, it immediately begins arp poisoning all filtered devices on the network, such that it can validate and restrict all traffic as is seen fit by the parent/administrator of the device.

The rclient binary provide a way for the admin of the device to control the device, even if the admin is not present, essentially providing a “cloud” functionality. Rclient talks with the F0.meetcircle.co domain, which in turn talks with the administrator's phone. In order to provide this persistent and remote administrative capability, the rclient binary will consistently send a 'ping2' message via udp:8988 to F0.meetcircle.co, to which the server will reply with 'pong'. This allows the server to reach the Circle device whenever necessary, since firewalls will typically allow return UDP traffic of this nature. A sample of this follows:

[*.*] Listening on 192.168.11.2:8988
[$.$] local:udp|remote:udp
0000 70 69 6e 67 32 20 38 43 45 32 44 41 46 31 41 42 ping2 8CE2DAF1EC
0010 31 36 20 69 64 3d 34 30 39 64 65 31 39 37 31 38 16 id=409de33718
0020 35 39 34 62 34 39 62 38 34 31 37 66 63 62 34 31 594c3a813fcb21
0030 66 65 36 63 66 62 63 62 35 38 20 74 61 67 3d 65 fe6cfbcb58 tag=e
0040 61 38 32 64 33 63 36 65 64 39 61 30 34 31 32 62 a82d3c3ed9a0402b
0050 35 33 34 35 3e 61 6d 38 33 33 36 61 31 35 65 38 53456abcd6a15e8
0060 62 38 64 38 36 37 31 63 66 35 66 34 63 33 30      b8d8671cf5f4c
[o.o] Sent 111 bytes to remote (45.79.169.242:8988)

0000 70 6f 6e 67 20 38 43 45 32 41 41 4a 39 45 42 30 pong 8CE2DAE1EB0
0010 36 6
[o.o] Sent 17 bytes to local (192.168.11.2:8988)

When the admin needs to perfrom any task remotely, the server will send a 'connect' message over this UDP tunnel, to which the rclient will initiate an SSL connection on port 4567 to the F0.meetcircle.co domain. Through this SSL connection, the actual management occurs, there are no messages of import that occur over the UDP communications (only ping2, ping, and connect).

Upon utilizing an SSL mitm to sniff the management traffic, the following behavior was observed when a phone connected to it's corresponding Circle device:

[>.>] Received Connection from ('192.168.2.104', 33392)
0000   5a 02 00 80 01 38 43 45 32 44 41 46 32 30 30 30    Z....8CE2DAF2123
0010   33 2c 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30    4,00:00:00:00:00
0020   3a 30 30 20 69 64 3d 33 35 63 61 63 36 63 63 63    :00 id=<removed>
…....                             tag=<removed>
00X0   20 76 3d 32                                                   v=2
[o.o] Sent 132 bytes to remote ()

0000 5a 01 00 f8 10 47 45 54 20 2f 61 70 69 2f 51 55 Z....GET /api/QU
0010 45 52 59 2f 6f 76 65 72 61 6c 6c 3f 61 70 69 3d ERY/overall?api=
0020 31 2e 30 26 74 6f 6b 65 6e 3d 38 43 45 32 44 41 1.0&token=<removed>
….
0050                                    20 48 54 54 50 2f 31 2e 31        HTTP/1.1
0060 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 44 61  ..User-Agent: Da
0070 6c 76 69 6b 2f 32 2e 31 2e 30 20 28 4c 69 6e 75   lvik/2.1.0 <removed>
                                   ..Host: <removed>
00c0                              0d 0a 43 6f 6e 6e 65                   ..Conne
00d0 63 74 69 6f 6e 3a 20 4b 65 65 70 2d 41 6c 69 76    ction: Keep-Aliv
00e0 65 0d 0a 41 63 63 65 70 74 2d 45 6e 63 6f 64 69   e..Accept-Encodi
00f0 6e 67 3a 20 67 7a 69 70 0d 0a 0d 0a ng: gzip....
[o.o] Sent 252 bytes to local (192.168.2.2:8988)

Aside from the redactions, it quickly became apparent that there was plain HTTP api requests flowing through the SSL tunnel. But there was still the question of the the wrapping protocol:

 0000 5a 01 00 f8 10 47 45 54 20 2f 61 70 69 2f 51 55 Z....GET /api/QU

An approximation of the wrapping backdoor protocol is as follows:

            _____________________________________________________________
Byte Offset |_0______1_______3________5_________5|7_____+MsgSize__________|
           ||  [Header] |[Opcode]|[MsgSize]|[OpSubtype]|[Message....]|[Size]|[Message]|
           ||       'Z'      |\x01\x00 | \x80\x01 |   (optional)  | GET /api... |  (If big msg) |

For extremely big messages and streams, the protocol maintained a max size, such that the messages were broken up into chunks. When observing other actions during the course of device usage, sometimes the Circle will also reach outbound by itself, using the same protocol. In order for the device to send its PIN over SMS for configuration of a new admin, the following occurs:

[>.>] Received Connection from ('192.168.2.104', 43629)
('ECDHE-RSA-AES128-GCM-SHA256', 'TLSv1/SSLv3', 128)
<address:port redacted>
0000   5a 02 00 80 01 38 43 45 32 44 41 46 32 30 30 30    Z....8CE2DAF2123
0010   33 2c 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30     4,00:00:00:00:00
0020   3a 30 30 20 69 64 3d 33 35 63 61 63 36 63 63 63    :00 id=<removed>
…....                             tag=<removed>
00X0   20 76 3d 32 5a 06 00 06 71 06 31 34 39 32              v=2Z...q.1492

[o.o] Sent 142 bytes to remote <address:port redacted>

Upon discovering this, it became apparent that this SSL tunnel actually has a lot more functionality than just redirecting for HTTP, so further exploration of the binary was needed. The function responsible for handling HTTPS traffic over the SSL tunnel was soon found in the Apid binary at 0x404d94. The function reads in 4 bytes at first, and verifies that it has the 'Z' header, an opcode, and a size, and then reads in bytes corresponding to the given size.

The opcode and subtype (if any) is then thrown against two different jump tables. Ignoring the main jumptable for now to get an idea of some of the capabilities, the subtype jumptable looks as such:

loc_4050C0:              # jumptable 004050B8 case 2
[...]
li      $a0, 6
lui     $v1, 0x41
addiu   $a1, $v1, (aSubtypeD - 0x410000)  # "subtype=%d\n"
move    $a2, $v0
jal     syslog
nop
lb      $v0, 0xB0+subtype($fp)
nop
sltiu   $v1, $v0, 7      # switch 7 cases
[...]
sll     $v1, $v0, 2      # .word aRegister          # "register"
                     # .word aDisconnect        # "disconnect"
                     # .word aPing_0            # "ping"
                     # .word aReboot            # "reboot"
                     # .word aTelnet_disconn    # "telnet_disconnect"
                     # .word aMac_change        # "mac_change"
                     #  .word aDisconnect_all    # "disconnect_all"
la      $v0, jpt_40511C
addu    $v0, $v1, $v0
lw      $v0, 0($v0)
nop
jr      $v0              # switch jump

Since there's the 'telnetdisconnect' and 'disconnectall' options, there's logically got to be telnet and something else located within the code base. The rest is found in the normal opcode jumptable, summarized below:

Case 1: Send data to the local Apid HTTP server at 127.0.0.1:4444. 
Case 2: Jump to subtype table.
Case 3/5: Connect to TCP port 127.0.0.1:22 or 127.0.0.1:23 
Case 4: <Unused>
Case 6: Regenerate the device's /mnt/shares/usr/bin/passcode

Now thankfully, there's no Telnet server running on the device, but there does exist an instance of Dropbear SSH, and if we check in the authorized_keys file, we can plainly see:

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuIaD23ac41XZp5AcSSOunHXHYN38dF2YX+rmb0QT4zxKFnccl6BpzoxGb604rPc4eQ477glWyM4D/jTIyaKqmA7P1iVMym8v5nSXH6haSc/
KrzV5EizmalXd4+eoK8ddSgpoci0P9oul3yiWtvccwN5WQ5H/DZhyYvdM73kKnYh3JUllx8JnGi1Qa0nhNGfrhIqaApTc/AyIAFR9I8wtp5KR98xRH5u/hEm1IMB5lo7yS6yJUcupIctnW/
C2qUOD7WtWzZvJtgAmmhh+A1XLU42PruPtTfQ2EAHUmNJ+xVssUl3N2cIhvCt1sm5o8DymttOS4xot6Ni06UZ/LK/iKw== [email protected]

As of firmware version 2.0.1, Dropbear SSH is not enabled by default however, but with one of the more recent 'Circle Home' app updates, a button was added to the settings:

(Manage->Support Remote Access->Remote Access)
“Enabling 'Remote Access' will allow Circle's support team to securely access your Circle remotely to perform system diagnostic commands”

So while it's great that they publicly diclose that there is a “Remote Access” feature, this was not public until recently (August 10th 2017), but the SSH capabilities were there the whole time. Also, there's the fact about what the 'Remote Access' switch inside the app actually does. It sends an API call to the Circle device Apid server: /api/DEBUG/enable, which causes configure.xml to be changed to

 <debugEnabled>false</debugEnabled> → <debugEnabled>true</debugEnabled>

Which then causes the configd daemon running on the device to switch on Dropbear:

loc_41059C:
lui     $a1, 0x43
move    $a0, $s0
jal     sub_41D3EC
la      $a1, (aOverallDebugen+8)  # "debugEnabled"
beqz    $v0, loc_4105E0
nop

loc_410FD4:
lui     $a0, 0x43
jal     system
la      $a0, aEtcInit_dDro_0  # "/etc/init.d/dropbear start"
j       loc_4105E0
nop

It should be noted that this API call does require a valid token for authentication, however when viewing the /api/DEBUG/enable call through an SSL MITM, we can see that the device actually discloses all of its tokens to the MeetCircle servers:

[>.>] Received Connection from ('192.168.2.104', 43810)
('ECDHE-RSA-AES128-GCM-SHA256', 'TLSv1/SSLv3', 128)
<removed ip:port>
0000   5a 02 00 80 01 38 43 45 32 44 41 46 32 30 30 30    Z....8CE2DAF2123
0010   33 2c 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30     4,00:00:00:00:00
0020   3a 30 30 20 69 64 3d 33 35 63 61 63 36 63 63 63    :00 id=<removed>
…....                             tag=<removed>
00X0                                    Z...v.<tokens redacted>
0090 46 32 33 45 31 33 2d 79 42 37 54 48 4a 46 79 5a    [{"ID":"A_de
0120 62 75 67 5f 65 6e 61 62 6c 65 64 22 2c 22 4c 6f    bug_enabled","Lo
0130 63 61 6c 65 22 3a 22 65 6e 5f 55 53 22 2c 22 56    cale":"en_US","V
0140 61 72 73 22 3a 7b 7d 7d 5d                 ars":{}}]
[o.o] Sent 329 bytes to remote (F0.meetcircle.co:8988)

Which essentially renders the 'Enable Remote Access' option useless, since the SSH access can be enabled by anyone with a token (which includes Circle Media Inc.)

Timeline

2017-09-12 - Vendor Disclosure
2017-10-31 - Public Release

Credit

Discovered by Lilith Wyatt, Claudio Bozzato of Cisco Talos.