MCP-DB Sicherheit

Vollständige Sicherheitsmaßnahmen für 10 MCP-DB Tools.

Sicherheitsübersicht

MaßnahmeImplementierungBetrifft
Prepared Statementscursor.execute(query, params)Alle Tools
Identifier-ValidierungRegex ^[a-zA-Z0-9_]+$INSERT, UPDATE, DELETE
Mandatory WHEREwhere dict PflichtUPDATE, DELETE
Default LIMIT 100Automatisch bei DELETEDELETE
DDL Statement-ValidierungExecuteValidatordb_execute
Keyword Blocklist (15)Word Boundariesdb_select
Database Allowlistki_dev, ki_contentAlle Tools
Query Timeout30 Sekundendb_select
Row LimitMax 100db_select
Query LengthMax 2000 Zeichendb_select
LoggingJede Operation in mcp_logAlle Tools
Blocking-HookPreToolUse für Bashmysql/mariadb CLI

Schreib-Operationen Sicherheit

db_insert

SchutzImplementierung
Identifier-ValidierungTabellen- und Spaltennamen: ^[a-zA-Z0-9_]+$
Prepared StatementsWerte als Parameter, nie String-Konkatenation
DB-WhitelistNur ki_dev, ki_content erlaubt
# Sicher: Prepared Statement
INSERT INTO `tasks` (`title`, `status`) VALUES (%s, %s)
# Mit values: ("Mein Task", "pending")

db_update

UPDATE ohne WHERE ist verboten!
SchutzImplementierung
Mandatory WHERELeeres where dict → status: "denied"
Identifier-ValidierungAlle Spalten in data und where
Prepared StatementsSET und WHERE Werte als Parameter
# Erlaubt:
db_update(table="tasks", data={"status": "done"}, where={"id": 42})

# Blockiert (kein WHERE):
db_update(table="tasks", data={"status": "done"}, where={})
# → {"status": "denied", "error": "WHERE clause is required..."}

db_delete

DELETE ohne WHERE ist verboten! Default LIMIT: 100
SchutzImplementierung
Mandatory WHERELeeres where dict → status: "denied"
Default LIMITAutomatisch LIMIT 100 wenn nicht angegeben
Identifier-ValidierungSpaltennamen in where
# Erlaubt:
db_delete(table="mcp_log", where={"status": "error"}, limit=50)

# Blockiert (kein WHERE):
db_delete(table="mcp_log", where={})
# → {"status": "denied", "error": "WHERE clause is required..."}

db_execute (DDL)

SchutzImplementierung
Statement-WhitelistALTER, CREATE, DROP, TRUNCATE
ExecuteValidatorPrüft erstes Keyword
LoggingStatement-Typ in mcp_log
# Erlaubt:
db_execute("ALTER TABLE tasks ADD COLUMN priority INT")
db_execute("CREATE INDEX idx_status ON tasks(status)")
db_execute("DROP TABLE temp_data")
db_execute("TRUNCATE TABLE cache")

# Blockiert:
db_execute("SELECT * FROM tasks")  # Kein DDL
db_execute("INSERT INTO tasks...")  # Kein DDL

Identifier-Validierung

Verhindert SQL-Injection über Tabellen-/Spaltennamen:

def _validate_identifier(name: str) -> bool:
    """Validiert Tabellen-/Spaltennamen gegen SQL-Injection."""
    return bool(re.match(r"^[a-zA-Z0-9_]+$", name))
EingabeValideGrund
tasksJaAlphanumerisch
chat_sessionsJaMit Underscore
tasks; DROP TABLE--NeinSonderzeichen
tasks`NeinBacktick

Blocking-Hook (PreToolUse)

KRITISCH: Direkte mysql/mariadb-Befehle werden auf System-Ebene blockiert!

Blockierte Muster

# Blockierte Befehle (Beispiele)
mysql -u root -pPassword123 -e "SELECT 1"
mariadb -u user -pSecret
mysql --password=geheim --execute="DROP TABLE users"
mysqldump ki_protokoll > backup.sql
sudo mysql -u root -pPass

# Stattdessen MCP-DB verwenden:
db_select      - SELECT-Abfragen
db_insert      - Datensätze einfügen
db_update      - Datensätze ändern
db_delete      - Datensätze löschen
db_execute     - DDL (ALTER/CREATE/DROP)
db_describe    - Tabellenstruktur
db_databases   - Datenbanken auflisten
db_tables      - Tabellen auflisten
db_schema      - Tabellen-Metadaten
db_stats       - MCP-Log Statistiken

Hook-Konfiguration

Pfad: /var/www/.claude/settings.local.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/var/www/tools/ki-protokoll/claude-hook/block_direct_db.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

Sicherheitsschichten (Defense in Depth)

SchichtMechanismusSchutz vor
1. Claude Code Hook block_direct_db.py (Exit Code 2) Direkte Bash-Befehle mit mysql/mariadb
2. Identifier-Validierung Regex ^[a-zA-Z0-9_]+$ SQL-Injection über Namen
3. Mandatory WHERE where dict Pflicht Versehentliches UPDATE/DELETE aller Zeilen
4. Default LIMIT LIMIT 100 bei DELETE Massenlöschung
5. DDL-Whitelist ExecuteValidator Unerlaubte DDL-Statements
6. Prepared Statements cursor.execute(sql, params) SQL-Injection über Werte
7. DB-Whitelist Config.ALLOWED_DATABASES Zugriff auf andere Datenbanken
8. Audit-Log mcp_log Tabelle Nachvollziehbarkeit, Incident Response

Keyword Blocklist (db_select)

KategorieKeywordsRisiko
DMLDELETE, INSERT, UPDATEDatenmanipulation
DDLDROP, TRUNCATE, ALTER, CREATE, RENAMEStrukturänderung
DCLGRANT, REVOKERechteänderung
File-OpsLOAD_FILE, INTO OUTFILE, INTO DUMPFILEDateizugriff
DoSBENCHMARK, SLEEPResource Exhaustion

Incident Response

EventIndikatorMaßnahme
Hook blockiert Befehl PreToolUse:Bash hook error: BLOCKIERT MCP-DB Tools verwenden
WHERE fehlt status='denied', "WHERE clause is required" where Parameter hinzufügen
Ungültiger Identifier status='denied', "Invalid column name" Spaltenname prüfen
Unerlaubtes DDL status='denied', "Statement not allowed" Nur ALTER/CREATE/DROP/TRUNCATE
SQL Injection Versuch status='denied', Keyword in error_message Log analysieren

Credential-Management

.env Datei

# Berechtigungen setzen
chmod 600 /opt/mcp-servers/mcp-db/.env
chown root:root /opt/mcp-servers/mcp-db/.env

Keine Credentials in Claude Config

# Registrierung OHNE Credentials
claude mcp add mcp-db \
  --transport stdio \
  -- /opt/mcp-servers/mcp-db/venv/bin/python \
     /opt/mcp-servers/mcp-db/server.py

# Credentials werden aus .env geladen

Verwandte Kapitel