Talos Vulnerability Report

TALOS-2017-0418

Circle with Disney Rclient SSL TLD MITM Vulnerability

October 31, 2017
CVE Number

CVE-2017-2911

Summary

An exploitable vulnerability exists in remote control functionality of Circle with Disney running firmware 2.0.1. SSL certificates for specific domain names can cause the rclient daemon to accept a different certificate than intended. An attacker can host an HTTPS server with this certificate to trigger this vulnerability.

Tested Versions

Circle with Disney 2.0.1

Product URLs

https://meetcircle.com/

CVSSv3 Score

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

CWE

CWE-300: Channel Accessible by Non-Endpoint ('Man-in-the-Middle')

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 is no messages of import that occur over the UDP communications (only ping2, ping, and connect).

Unfortunately, there is an issue that lies within the SSL certificate checking of the rclient binary, the disassembly of which is listed below:

.text:004029F4                 lw      $a0, 0x38+arg_0($fp)
.text:004029F8                 jal     SSL_get_peer_certificate #[1]
...
.text:00402A34                 lw      $a0, 0x38+var_20($fp)
.text:00402A38                 jal     X509_get_subject_name #[2]
.text:00402A3C                 nop
.text:00402A40                 move    $a0, $v0
.text:00402A44                 move    $a1, $zero
.text:00402A48                 move    $a2, $zero
.text:00402A4C                 jal     X509_NAME_oneline   #[3]
.text:00402A54                 sw      $v0, 0x38+oneline_buff_malloced($fp)  #[4]

As shown at [1], the rclient grabs the remote server's SSL certificate, and then at [2], the server gets the X509 subject name, which is typical behavior for SSL verification. X509NAMEoneline [3] then grabs a lot of the information from the certificate attributes, joins it all into one line, and then stores it into a buffer on the heap [4]. An example return string might be:

`/C=US/ST=Sad/L=boop/O=<(^_^)>/CN=boopdoop.net`

While the interesting behavior of the X509NAMEoneline can lead to some other vulnerabilities, like including the string 'CN=*.meetcircle.com” inside of another attribute ( For a great writeup of this: [https://langui.sh/2016/01/29/x509-name-oneline/])(https://langui.sh/2016/01/29/x509-name-oneline/) ) , however, due to reasons mentioned a little further down, the binary was not vulnerable to this, as we could not get a certificate signed by the specific CA to be formed as such.

Interestingly due to how they actually check the Common Name attribute of the SSL cert, the binary was left vulnerable to another attack vector:

.text:00402A54                 sw      $v0, 0x38+oneline_buff_malloced($fp) [1]
.text:00402A58                 lw      $a0, 0x38+oneline_buff_malloced($fp)
.text:00402A5C                 lui     $v0, 0x41
.text:00402A60                 addiu   $a1, $v0, (aCn_meetcircle_ - 0x410000)  #                            "CN=*.meetcircle.com" [2]
.text:00402A64                 jal     strstr [3]
.text:00402A68                 nop
.text:00402A6C                 bnez    $v0, loc_402A94
.text:00402A70                 nop
.text:00402A74                 li      $a0, 3
.text:00402A78                 lui     $v0, 0x41
.text:00402A7C                 addiu   $a1, $v0, (aInvalidCertifi - 0x410000)  # "Invalid certificate\n"

As shown above, we continue from immediately after the X509NAMEoneline() function call [1]. The return value of this function is compared is compared against “CN=*.meetcircle.com” [2], with the strstr() function [3], which returns a pointer to the first match of register $a1 in $a0 (and NULL otherwise).

Since this is the only check upon the Common Name attribute, it becomes possible to bypass this check by buying the following domains (as per Wikipedia):

meetcircle.community
meetcircle.company
meetcircle.computer

The resulting call to X509onelinename will look as such:

(gdb) x/1s $v0
0x44f7e0:       "/C=AU/ST=Some-State/O=<(^_^)> LLC/CN=*.meetcircle.computer"
(gdb) x/6i $pc
=> 0x402a5c <_ftext+3324>: lui v0,0x41
0x402a60 <_ftext+3328>: addiu a1,v0,-4248
0x402a64 <_ftext+3332>: jal 0x401700 <[email protected]>

The call to strstr() is made with the following parameters:

Breakpoint 3, 0x00402a64 in _ftext ()
(gdb) x/1s $a0
0x44f7e0:       "/C=AU/ST=Some-State/O=<(^_^)> LLC/CN=*.meetcircle.computer"
(gdb) x/1s $a1
0x40ef68:       "CN=*.meetcircle.com"

And then the return value is as such (indicating success):

0x00402a6c in _ftext ()
(gdb) x/1s $v0
0x44f80f:       "CN=*.meetcircle.computer"

It should be cautioned that certificate presented by the MITM server needs to have its trust chain signed by the Comodo CA. The binary has a barely obfuscated CA cert located inside that is extracted to /tmp/ca.rclient.pem and then utilized to validate the outbound SSL connection. This secondary validation tends to be trivial as the Comodo CA offers a free SSL Certificate trial, the hard part is getting the domain name.

Another note is that the rclient binary also authenticates to the remote server via a barely obfuscated certificate key pair located within the rclient itself. This is also the reason why the rclient name is not vulnerable to the X509NAMEoneline attack previously mentioned, as any certificate generated and signed by the Comodo CA will look as such:

Logging output of the rclient binary upon successful TLS connection:

rclient: Server certificates:
rclient: Subject: /C=AU/ST=Some-State/O=<(^_^)> LLC/CN=*.meetcircle.computer
rclient: Issuer: /C=AU/ST=Some-State/O=<(^_^)> LLC/CN=*.meetcircle.computer
rclient: my AP ===00:00:00:00:00:00===
update_log: stat return 0
rclient: sending register to remote 132 bytes

Interestingly after the SSL connection has been initialized, the Circle sends out the following messages to the server.

[>.>] 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....8CE2DAF23E1
0010   33 2c 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30    3,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
[>.>] Sent X bytes to remote ()
0000   5a 06 00 03 30 02 31                               Z...0.1
[>.>] Sent 7 bytes to remote ()
0000   5a 06 00 5d 31 03 38 43 45 32 44 41 32 30 30 30    Z..]1.8CF2DAFABC
0010   31 33 2d 79 42 37 54 48 4a 46 79 5a 39 75 4b 49    12-yB7abcdeZ9uKI
0020   6e 62 6d 2d 32 30 31 37 30 37 32 31 2e 31 39 32    nbm-20170721.192
0030   33 32 35                                                                    325

Which contains, starting at offset 0x6 of the third message, a comma separated list of the tokens used to authenticate to the API as an administrator, allowing for an immediate escalation of permissions.

Timeline

2017-08-29 - Vendor Disclosure
2017-10-31 - Public Release

Credit

Discovered by Lilith Wyatt and Claudio Bozzato of Cisco Talos.