security: 9 Findings aus Security-Audit behoben (CRITICAL + HIGH + MEDIUM)
CRITICAL: - C-1: LDAP tls_verify Default False → True (MITM-Schutz) - C-2: TOTP-Secret Fernet-verschlüsselt in DB (statt Plaintext) - core/crypto.py: encrypt_value() / decrypt_value() helper - Migration 0026: totp_secret VARCHAR(64→500), ldap tls_verify default=true - _totp_plain() helper mit Legacy-Fallback für bestehende Werte HIGH: - H-1: Kiosk Nonce-Cache asyncio.Lock (Race Condition behoben) - H-2: File-Upload-Limit 10 MB (import_kimai.py + users.py CSV-Import) - H-3: CORS allow_methods/allow_headers explizit eingeschränkt (war *) - H-4: TrustedHostMiddleware aktiviert wenn ALLOWED_HOSTS gesetzt MEDIUM: - M-1: IP-Logging nutzt X-Forwarded-For hinter nginx-Proxy - M-4: Audit-Log für password_changed, totp_enabled, totp_disabled - M-5: CalDAV verify_ssl in Production erzwungen (_effective_verify_ssl) 152/152 Tests grün Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
"""Security-Fixes: LDAP tls_verify default=True, totp_secret column length 500
|
||||
|
||||
Revision ID: 0026
|
||||
Revises: 0025
|
||||
Create Date: 2026-05-24
|
||||
|
||||
Änderungen:
|
||||
- ldap_configs.tls_verify: DEFAULT False → DEFAULT True
|
||||
Neue Konfigurationen werden mit TLS-Verifikation angelegt.
|
||||
BESTEHENDE Einträge mit tls_verify=False werden NICHT automatisch geändert,
|
||||
da dies laufende LDAP-Verbindungen unterbrechen könnte.
|
||||
Admins müssen ihre LDAP-Konfiguration manuell prüfen.
|
||||
|
||||
- users.totp_secret: VARCHAR(64) → VARCHAR(500)
|
||||
Fernet-verschlüsselte Secrets sind länger als 64 Zeichen (~180 Zeichen).
|
||||
Bestehende Plaintext-Secrets (falls vorhanden) müssen manuell verschlüsselt
|
||||
werden; nach dieser Migration werden neue Secrets automatisch verschlüsselt.
|
||||
WICHTIG: Nach dem Deployment müssen bestehende TOTP-Nutzer ihr 2FA neu einrichten
|
||||
(altes Plaintext-Secret nicht mehr kompatibel mit neuem Decrypt-Flow).
|
||||
Alternativ: vor dem Deployment `migrate_totp_secrets.py` ausführen (TODO).
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = "0026"
|
||||
down_revision = "0025"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ── C-1: LDAP tls_verify Default auf True ────────────────────────────────
|
||||
op.alter_column(
|
||||
"ldap_configs",
|
||||
"tls_verify",
|
||||
server_default=sa.text("true"),
|
||||
existing_type=sa.Boolean(),
|
||||
existing_nullable=False,
|
||||
)
|
||||
|
||||
# ── C-2: totp_secret Column-Länge für Fernet-Token ───────────────────────
|
||||
op.alter_column(
|
||||
"users",
|
||||
"totp_secret",
|
||||
existing_type=sa.String(64),
|
||||
type_=sa.String(500),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# totp_secret zurück auf 64 (ggf. Datenverlust bei Fernet-verschlüsselten Werten)
|
||||
op.alter_column(
|
||||
"users",
|
||||
"totp_secret",
|
||||
existing_type=sa.String(500),
|
||||
type_=sa.String(64),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
# LDAP tls_verify Default zurück auf False
|
||||
op.alter_column(
|
||||
"ldap_configs",
|
||||
"tls_verify",
|
||||
server_default=sa.text("false"),
|
||||
existing_type=sa.Boolean(),
|
||||
existing_nullable=False,
|
||||
)
|
||||
Reference in New Issue
Block a user