CVE-2020-36876
Unauthenticated disclosure of sensitive info in ReQuest F3 Server debug log.
- CVSS 8.7
- CWE-532
- Information Leakage
- Remote
ReQuest Serious Play F3 Media Server versions 7.0.3.4968 (Pro), 7.0.2.4954, 6.5.2.4954, 6.4.2.4681, 6.3.2.4203, and 2.0.1.823 allows unauthenticated attackers to disclose the webserver's Python debug log file containing system information, credentials, paths, processes and command arguments running on the device. Attackers can access sensitive information by visiting the message_log page.
- CWE
- CWE-532
- CVSS base score
- 8.7
- Published
- 2025-12-05
- OWASP
- A05 Security Misconfiguration
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Information Leakage
- Subcategory
- Information Disclosure
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- ReQuest Seri
Solution
No patch is available. Restrict network access to the device's web interface, particularly the `/message_log` page.
Vulnerable code sample
from flask import Flask, Response
import os
import datetime
# This code is for educational and demonstration purposes only.
# It simulates the vulnerability CVE-2020-36876 and should not be used in production.
app = Flask(__name__)
LOG_FILE = "debug_log.txt"
def setup_sensitive_logs():
"""
Simulates the server application writing sensitive data to a debug log file.
In a real system, this would happen organically during operation.
"""
log_content = f"""
[DEBUG] {datetime.datetime.now()}: System Initializing...
[DEBUG] {datetime.datetime.now()}: Reading configuration from /etc/f3_server/config.ini
[INFO] {datetime.datetime.now()}: Connecting to database 'mediadb' on 127.0.0.1:5432 with user 'postgres' and password 'P@ssw0rd_1s_n0t_S@f3'.
[INFO] {datetime.datetime.now()}: Database connection successful.
[DEBUG] {datetime.datetime.now()}: System Paths:
- Media Root: /data/media/
- Transcode Temp: /tmp/transcode/
- App Root: /opt/request/f3
[INFO] {datetime.datetime.now()}: New media file detected. Starting transcode process.
[DEBUG] {datetime.datetime.now()}: Executing command: /usr/bin/ffmpeg -i /data/media/movies/new_arrival.mkv -c:v libx264 -preset fast /data/media/movies/new_arrival.mp4
[DEBUG] {datetime.datetime.now()}: Process spawned with PID 8872.
[INFO] {datetime.datetime.now()}: API Key for metadata service: 987def654cba3210fed098cb765a4321
"""
with open(LOG_FILE, "w") as f:
f.write(log_content)
@app.route('/message_log')
def show_message_log():
"""
VULNERABLE ENDPOINT: This route directly exposes the contents of the debug
log file without any authentication or authorization checks.
"""
try:
with open(LOG_FILE, 'r') as f:
content = f.read()
return Response(content, mimetype='text/plain')
except FileNotFoundError:
return "Log file not found.", 404
except Exception as e:
return f"An internal error occurred: {e}", 500
@app.route('/')
def index():
return "ReQuest Serious Play F3 Media Server is running. <br> The vulnerable endpoint is at /message_log"
if __name__ == "__main__":
# Create the simulated sensitive log file on startup for the demonstration.
setup_sensitive_logs()
# Run the web server.
# In a real vulnerable environment, this would be running as a service.
# The debug=True parameter is used here to represent a flawed development/production configuration.
app.run(host='0.0.0.0', port=8080, debug=True)Patched code sample
import os
from functools import wraps
from flask import Flask, session, Response, redirect, url_for
# --- Configuration and Setup ---
# In a real application, this would come from a secure configuration file.
SECRET_KEY = os.urandom(24)
LOG_FILE_PATH = "/tmp/sensitive_debug.log"
app = Flask(__name__)
app.secret_key = SECRET_KEY
# --- The Vulnerability Fix ---
def admin_required(f):
"""
A decorator to ensure a user is logged in as an admin.
This is the core of the fix, preventing unauthenticated access.
"""
@wraps(f)
def decorated_function(*args, **kwargs):
# FIX: Check if a user is authenticated and authorized.
# Here, we check for a specific flag in the user's session.
if not session.get('is_admin'):
# If the check fails, deny access.
return "Forbidden: You do not have permission to access this resource.", 403
# If the check passes, proceed to the original function.
return f(*args, **kwargs)
return decorated_function
# --- Route Definitions ---
@app.route('/message_log')
@admin_required # <-- APPLYING THE FIX: This route is now protected.
def show_message_log():
"""
Displays the content of the sensitive debug log file.
Access is now restricted to authenticated admin users by the @admin_required
decorator, which fixes the original vulnerability.
"""
try:
# This part of the code is now only reachable by authenticated admins.
with open(LOG_FILE_PATH, 'r') as log_file:
log_content = log_file.read()
# Display the log content in a preformatted block for readability.
return Response(f"<pre>{log_content}</pre>", mimetype='text/html')
except FileNotFoundError:
return "Log file not found.", 404
except Exception as e:
# Avoid leaking detailed exception info in a production environment.
return "An internal error occurred.", 500
# --- Helper Routes for Demonstration ---
@app.route('/')
def index():
"""Provides instructions for demonstrating the fix."""
instructions = """
<h1>Demonstration of CVE-2020-36876 Fix</h1>
<p>1. <a href="/message_log">Try to access the message_log (will be denied)</a></p>
<p>2. <a href="/login_as_admin">Log in as an admin</a></p>
<p>3. <a href="/message_log">Try to access the message_log again (will be allowed)</a></p>
<p>4. <a href="/logout">Log out</a></p>
"""
return instructions
@app.route('/login_as_admin')
def login_as_admin():
"""Simulates a user logging in and gaining admin privileges."""
session['is_admin'] = True
return 'You are now logged in as an administrator. <a href="/message_log">Access the log</a>.'
@app.route('/logout')
def logout():
"""Simulates a user logging out."""
session.pop('is_admin', None)
return 'You have been logged out. <a href="/">Back to home</a>.'
# --- Main Execution Block for Demonstration ---
if __name__ == '__main__':
# Create a dummy sensitive log file for the demonstration.
try:
with open(LOG_FILE_PATH, 'w') as f:
f.write("--- ReQuest F3 Media Server Python Debug Log ---\n")
f.write("INFO: System boot process initiated.\n")
f.write("DEBUG: DB_USER='admin'\n")
f.write("DEBUG: DB_PASSWORD='HardcodedPassword123!'\n")
f.write("DEBUG: Filesystem Path: /usr/local/app/media_server\n")
f.write("INFO: Process started with args: ['--daemon', '--port', '80']\n")
f.write("ERROR: Unauthenticated access attempt from IP 192.168.1.100\n")
print(f"Dummy log file created at {LOG_FILE_PATH}")
except IOError as e:
print(f"Error: Could not create dummy log file. Please check permissions for {LOG_FILE_PATH}.")
print(f"Details: {e}")
print("\nStarting Flask server to demonstrate the fix...")
print("Open http://127.0.0.1:5000 in your browser.")
# Note: debug=True is for demonstration purposes only.
# It should be False in a production environment.
app.run(host='127.0.0.1', port=5000, debug=True)Cite this entry
@misc{vaitp:cve202036876,
title = {{Unauthenticated disclosure of sensitive info in ReQuest F3 Server debug log.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2020-36876},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2020-36876/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
