Protokoll #1136

ID1136
Zeitstempel2025-12-20 18:20:34.053871
Clientroot
IP145.224.96.190
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens2,648 (Input: 22, Output: 2,626)
Dauer75 ms
Request-Zeit2025-12-20 18:20:34.053871
Response-Zeit2025-12-20 18:20:34.129354

Request

{
    "event": "PreToolUse",
    "tool_name": "mcp__mcp-docs__docs_get",
    "tool_input": {
        "id": 40
    }
}

Response

{
    "tool_response": [
        {
            "type": "text",
            "text": "{\n  \"success\": true,\n  \"doc\": {\n    \"id\": 40,\n    \"parent_id\": 36,\n    \"slug\": \"mcp-db-security\",\n    \"path\": \"\/mcp\/mcp-db\/mcp-db-security\",\n    \"title\": \"Sicherheit\",\n    \"description\": \"Vollständige Sicherheitsmaßnahmen und DB-User Hardening.\",\n    \"content\": \"<nav class=\\\"breadcrumb\\\">\\n    <a href=\\\"\/docs\\\">Dokumentation<\/a> &raquo; <a href=\\\"\/docs\/mcp\/mcp-db\\\">MCP-DB<\/a> &raquo; Sicherheit\\n<\/nav>\\n\\n<h1>MCP-DB Sicherheit<\/h1>\\n<p>Vollständige Sicherheitsmaßnahmen und DB-User Hardening.<\/p>\\n\\n<h2>Sicherheitsübersicht<\/h2>\\n<table>\\n    <tr><th>Maßnahme<\/th><th>Implementierung<\/th><th>Verifiziert<\/th><\/tr>\\n    <tr><td>Nur SELECT<\/td><td>QueryValidator.validate_query()<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Prepared Statements<\/td><td>cursor.execute(query, params)<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Keyword Blocklist<\/td><td>15 Keywords mit Word Boundaries<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Database Allowlist<\/td><td>ki_protokoll, ki_system<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Table Allowlist<\/td><td>Konfigurierbar in Config<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Query Timeout<\/td><td>30 Sekunden (MAX_EXECUTION_TIME)<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Row Limit<\/td><td>Max 100<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Query Length<\/td><td>Max 2000 Zeichen<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Separate DB-User<\/td><td>mcp_readonly, mcp_logger<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Logging<\/td><td>Jede Operation in mcp_log<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Credentials<\/td><td>.env (chmod 600)<\/td><td>Ja<\/td><\/tr>\\n    <tr><td>Fail-Safe<\/td><td>Exception bei Logging-Fehler<\/td><td>Ja<\/td><\/tr>\\n<\/table>\\n\\n<h2>DB-User Hardening<\/h2>\\n\\n<h3>mcp_readonly (Query-User)<\/h3>\\n<p>Nur SELECT auf spezifische Tabellen:<\/p>\\n<pre><code>-- User erstellen\\nCREATE USER IF NOT EXISTS 'mcp_readonly'@'localhost'\\nIDENTIFIED BY 'SECURE_PASSWORD_HERE';\\n\\n-- Nur SELECT auf erlaubte Tabellen in ki_protokoll\\nGRANT SELECT ON ki_protokoll.mcp_log TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_eintraege TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_kategorien TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_tags TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_settings TO 'mcp_readonly'@'localhost';\\n\\n-- Schema-Zugriff für db_schema Tool\\nGRANT SELECT ON information_schema.TABLES TO 'mcp_readonly'@'localhost';\\n\\n-- ki_system (nach Bedarf)\\nGRANT SELECT ON ki_system.* TO 'mcp_readonly'@'localhost';\\n\\nFLUSH PRIVILEGES;<\/code><\/pre>\\n\\n<h3>mcp_logger (Logging-User)<\/h3>\\n<p>Nur INSERT auf mcp_log:<\/p>\\n<pre><code>-- User erstellen\\nCREATE USER IF NOT EXISTS 'mcp_logger'@'localhost'\\nIDENTIFIED BY 'DIFFERENT_SECURE_PASSWORD_HERE';\\n\\n-- Nur INSERT auf mcp_log\\nGRANT INSERT ON ki_protokoll.mcp_log TO 'mcp_logger'@'localhost';\\n\\nFLUSH PRIVILEGES;<\/code><\/pre>\\n\\n<h2>Keyword Blocklist<\/h2>\\n<table>\\n    <tr><th>Kategorie<\/th><th>Keywords<\/th><th>Risiko<\/th><\/tr>\\n    <tr><td>DML<\/td><td>DELETE, INSERT, UPDATE<\/td><td>Datenmanipulation<\/td><\/tr>\\n    <tr><td>DDL<\/td><td>DROP, TRUNCATE, ALTER, CREATE, RENAME<\/td><td>Strukturänderung<\/td><\/tr>\\n    <tr><td>DCL<\/td><td>GRANT, REVOKE<\/td><td>Rechteänderung<\/td><\/tr>\\n    <tr><td>File-Ops<\/td><td>LOAD_FILE, INTO OUTFILE, INTO DUMPFILE<\/td><td>Dateizugriff<\/td><\/tr>\\n    <tr><td>DoS<\/td><td>BENCHMARK, SLEEP<\/td><td>Resource Exhaustion<\/td><\/tr>\\n<\/table>\\n\\n<h2>Bekannte Limits<\/h2>\\n<table>\\n    <tr><th>Limit<\/th><th>Beschreibung<\/th><th>Mitigation<\/th><\/tr>\\n    <tr>\\n        <td>SQL-Parsing<\/td>\\n        <td>Regex-basiert, kein Full Parser<\/td>\\n        <td>Konservative Extraktion, Table Allowlist<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Query-Kosten<\/td>\\n        <td>Keine Kostenanalyse vor Ausführung<\/td>\\n        <td>Timeout (30s), Row Limit (100)<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>.env Sicherheit<\/td>\\n        <td>Abhängig von Host-Hardening<\/td>\\n        <td>chmod 600, Owner root<\/td>\\n    <\/tr>\\n<\/table>\\n\\n<h2>Credential-Management<\/h2>\\n\\n<h3>.env Datei<\/h3>\\n<pre><code># Berechtigungen setzen\\nchmod 600 \/opt\/mcp-servers\/mcp-db\/.env\\nchown root:root \/opt\/mcp-servers\/mcp-db\/.env<\/code><\/pre>\\n\\n<h3>Keine Credentials in Claude Config<\/h3>\\n<pre><code># Registrierung OHNE Credentials\\nclaude mcp add mcp-db \\\\\\n  --transport stdio \\\\\\n  -- \/opt\/mcp-servers\/mcp-db\/venv\/bin\/python \\\\\\n     \/opt\/mcp-servers\/mcp-db\/server.py\\n\\n# Credentials werden aus .env geladen, nicht aus dem Befehl<\/code><\/pre>\\n\\n<h2>Testfälle<\/h2>\\n<pre><code># Blockierte Queries (DENIED)\\n\\\"SELECT * FROM mcp_log; DROP TABLE mcp_log\\\"\\n\\\"SELECT LOAD_FILE('\/etc\/passwd')\\\"\\n\\\"SELECT * FROM users\\\"  # Nicht in Allowlist\\n\\\"SELECT SLEEP(10)\\\"\\n\\\"INSERT INTO mcp_log VALUES (...)\\\"\\n\\n# Erlaubte Queries (SUCCESS)\\n\\\"SELECT * FROM mcp_log\\\"\\n\\\"SELECT * FROM mcp_log WHERE status = %s\\\"  # Mit Params\\n\\\"SELECT dropdown FROM ki_tags\\\"  # dropdown != DROP<\/code><\/pre>\\n\\n<h2>Audit-Log<\/h2>\\n<p>Jede Operation wird in mcp_log protokolliert:<\/p>\\n<pre><code>SELECT timestamp, request, status, duration_ms, error_message\\nFROM mcp_log\\nORDER BY timestamp DESC\\nLIMIT 20;<\/code><\/pre>\\n\\n<h2>Migration von direkten DB-Zugriffen<\/h2>\\n\\n<h3>Warum MCP-DB statt direkter mysql-Befehle?<\/h3>\\n<table>\\n    <tr><th>Problem<\/th><th>Legacy (mysql CLI)<\/th><th>Lösung (MCP-DB)<\/th><\/tr>\\n    <tr>\\n        <td>Credentials<\/td>\\n        <td>Passwort in Command-Line oder .my.cnf<\/td>\\n        <td>.env mit chmod 600, kein Passwort in Befehlen<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Shell History<\/td>\\n        <td>Queries mit -p Password in Historie<\/td>\\n        <td>Keine Passwörter in Shell, nur SQL-Queries<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Audit<\/td>\\n        <td>Kein Audit-Log (außer MySQL General Log)<\/td>\\n        <td>Jede Query in mcp_log protokolliert<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Validierung<\/td>\\n        <td>Keine, voller SQL-Zugriff<\/td>\\n        <td>QueryValidator, Keyword-Blocklist, Table-Allowlist<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Rechte<\/td>\\n        <td>Oft zu viel (DML\/DDL)<\/td>\\n        <td>Separate Users (readonly, logger)<\/td>\\n    <\/tr>\\n<\/table>\\n\\n<h3>Migration Schritt-für-Schritt<\/h3>\\n\\n<h4>1. Alte mysql-Befehle identifizieren<\/h4>\\n<pre><code># Suche nach mysql-Befehlen mit Passwörtern\\ngrep -r \\\"mysql.*-p\\\" \/var\/www\/ --include=\\\"*.sh\\\" --include=\\\"*.md\\\" --include=\\\"*.php\\\"\\ngrep -r \\\"mariadb.*-p\\\" \/var\/www\/ --include=\\\"*.sh\\\" --include=\\\"*.md\\\" --include=\\\"*.php\\\"\\n\\n# Suche nach hardcodierten DB-Credentials\\ngrep -r \\\"password.*=\\\" \/var\/www\/tools\/ --include=\\\"*.py\\\" | grep -v \\\"os.environ\\\"<\/code><\/pre>\\n\\n<h4>2. Dokumentation anpassen<\/h4>\\n<pre><code># Alt (unsicher)\\nmysql -u claude_code -p ki_protokoll -e \\\"SELECT * FROM tasks LIMIT 10;\\\"\\n\\n# Neu (sicher via MCP-DB)\\n# In Claude Code: Nutze MCP-DB Tool direkt\\n# Kein Passwort nötig, automatisch authentifiziert<\/code><\/pre>\\n\\n<h4>3. Python-Hooks auf Environment-Variablen umstellen<\/h4>\\n<pre><code># Vorher (unsicher)\\nDB_CONFIG = {\\n    'user': 'claude_code',\\n    'password': 'klartext_passwort'  # UNSICHER\\n}\\n\\n# Nachher (sicher)\\nfrom dotenv import load_dotenv\\nload_dotenv(Path(__file__).parent \/ '.env')\\n\\nDB_CONFIG = {\\n    'user': os.environ.get('CLAUDE_DB_USER', 'claude_code'),\\n    'password': os.environ.get('CLAUDE_DB_PASSWORD', '')\\n}<\/code><\/pre>\\n\\n<h4>4. .env Datei mit korrekten Rechten erstellen<\/h4>\\n<pre><code># .env erstellen\\ncat > \/var\/www\/tools\/ki-protokoll\/claude-hook\/.env << 'EOF'\\nCLAUDE_DB_HOST=localhost\\nCLAUDE_DB_PORT=3306\\nCLAUDE_DB_USER=claude_code\\nCLAUDE_DB_PASSWORD=<SICHERES_PASSWORT>\\nCLAUDE_DB_NAME=ki_protokoll\\nEOF\\n\\n# Rechte setzen (kritisch!)\\nchmod 600 \/var\/www\/tools\/ki-protokoll\/claude-hook\/.env\\nchown root:root \/var\/www\/tools\/ki-protokoll\/claude-hook\/.env<\/code><\/pre>\\n\\n<h4>5. Veraltete Credentials entfernen<\/h4>\\n<pre><code># Aus Claude Settings entfernen\\n# settings.local.json darf KEINE Passwörter enthalten\\n\\n# Prüfen\\ngrep -r \\\"password\\\" \/var\/www\/.claude\/ \/root\/.claude\/\\ngrep -r \\\"\\\\-p[A-Za-z0-9]\\\" \/var\/www\/.claude\/ \/root\/.claude\/\\n\\n# Sollte keine Treffer geben!<\/code><\/pre>\\n\\n<h3>Best Practices<\/h3>\\n<ul>\\n    <li><strong>Nie Passwörter in Code:<\/strong> Immer Umgebungsvariablen oder MCP-DB nutzen<\/li>\\n    <li><strong>.env immer chmod 600:<\/strong> Nur root darf lesen<\/li>\\n    <li><strong>Separate DB-Users:<\/strong> mcp_readonly für Queries, mcp_logger für Logging<\/li>\\n    <li><strong>Audit aktivieren:<\/strong> MCP-DB loggt automatisch alle Queries<\/li>\\n    <li><strong>Legacy-Befehle in Docs:<\/strong> Mit Warnhinweis versehen oder MCP-Beispiele zeigen<\/li>\\n<\/ul>\\n\\n<h2>Incident Response<\/h2>\\n<table>\\n    <tr><th>Event<\/th><th>Indikator<\/th><th>Maßnahme<\/th><\/tr>\\n    <tr>\\n        <td>SQL Injection Versuch<\/td>\\n        <td>status='denied', Keyword in error_message<\/td>\\n        <td>Log analysieren, ggf. Blocklist erweitern<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Unbekannte Tabelle<\/td>\\n        <td>status='denied', \\\"Table not allowed\\\"<\/td>\\n        <td>Allowlist prüfen oder erweitern<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Timeout<\/td>\\n        <td>status='error', Query > 30s<\/td>\\n        <td>Query optimieren oder Timeout erhöhen<\/td>\\n    <\/tr>\\n    <tr>\\n        <td>Credentials in Code gefunden<\/td>\\n        <td>grep findet Passwörter<\/td>\\n        <td>Sofort auf .env migrieren, Passwort rotieren<\/td>\\n    <\/tr>\\n<\/table>\\n\\n<h2>Hook-Enforced Security<\/h2>\\n<p>Zusätzlich zur MCP-DB Validierung können direkte DB-Zugriffe auf System-Ebene blockiert werden.<\/p>\\n\\n<h3>PreToolUse Hook<\/h3>\\n<p>Der Hook <code>\/opt\/scripts\/hooks\/block_direct_db.py<\/code> blockiert Bash-Befehle mit mysql\/mariadb Credentials:<\/p>\\n\\n<pre><code># Blockierte Befehle\\nmysql -u root -pPassword123 -e \\\"SELECT 1\\\"\\nmariadb -u user -p\\nmysql --password=secret123 --execute=\\\"DROP TABLE users\\\"\\n\\n# Stattdessen verwenden\\ndb_select(\\\"SELECT * FROM mcp_log LIMIT 10\\\")\\ndb_schema()\\ndb_stats()<\/code><\/pre>\\n\\n<h3>Hook Installation<\/h3>\\n<p>Der Hook ist bereits installiert unter:<\/p>\\n<pre><c... [TRUNCATED-f0146bb9c71e7def]"
        }
    ]
}
← Vorheriger Zur Liste Nächster →