Bewährte Methoden für sicherheit für mssql-django

In diesem Artikel werden Sicherheitspraktiken für Django-Anwendungen behandelt, die über das mssql-django Back-End eine Verbindung mit SQL Server herstellen. Diese Methoden ergänzen die integrierten Sicherheitsfeatures von Django und das Sicherheitsmodell SQL Server.

Verwenden Microsoft Entra Authentifizierung anstelle von Kennwörtern

Microsoft Entra Authentifizierung beseitigt gespeicherte Datenbankwörter. Verwenden Sie sie für alle Azure SQL Verbindungen.

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryMsi",
        },
    },
}

Die vollständige Liste der Authentifizierungsmethoden, aktuelle Einschränkungen und TOKEN Beispiele mit DefaultAzureCredential und ManagedIdentityCredentialfinden Sie unter Microsoft Entra Authentifizierung mit mssql-django.

Sicheres Verwalten von Anmeldeinformationen

Wenn Sie die SQL-Authentifizierung benötigen, behalten Sie Anmeldeinformationen außerhalb des Quellcodes bei.

Umgebungsvariablen

import os

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": os.environ["DB_NAME"],
        "USER": os.environ["DB_USER"],
        "PASSWORD": os.environ["DB_PASSWORD"],
        "HOST": os.environ["DB_HOST"],
        "PORT": os.environ.get("DB_PORT", "1433"),
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

Azure Key Vault (ein Dienst zur sicheren Verwaltung kryptografischer Schlüssel)

Rufen Sie für Produktionsbereitstellungen geheime Schlüssel aus Azure Key Vault ab:

from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient

credential = DefaultAzureCredential()
client = SecretClient(vault_url="https://<your-vault>.vault.azure.net/", credential=credential)

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": client.get_secret("db-name").value,
        "USER": client.get_secret("db-user").value,
        "PASSWORD": client.get_secret("db-password").value,
        "HOST": client.get_secret("db-host").value,
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

Vorsicht

Committen Sie Anmeldeinformationen niemals an die Quellcodeverwaltung. Hinzufügen von .env Dateien zu .gitignore. Verwenden Sie git-secrets oder Pre-Commit-Hooks, um auf versehentlich committete Zugangsdaten zu prüfen.

TLS-Verschlüsselung erzwingen

SQL Server Verbindungen sollten immer verschlüsselt werden. Der ODBC-Treiber verschlüsselt Verbindungen standardmäßig ab ODBC-Treiber 18:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            # Encryption is on by default with Driver 18
        },
    },
}

Wenn Sie ODBC-Treiber 17 verwenden, aktivieren Sie die Verschlüsselung explizit:

"extra_params": "Encrypt=yes"

Vorsicht

Verwenden Sie TrustServerCertificate=yes nur für die lokale Entwicklung mit selbstsignierten Zertifikaten. Verwenden Sie sie nicht in der Produktion. Sie deaktiviert die Validierung der Zertifikatskette und erhöht das Risiko eines Man-in-the-Middle-Angriffs. Installieren Sie ein vertrauenswürdiges Zertifikat auf dem Server, und stellen Sie eine Verbindung mit TrustServerCertificate=no.

Anwenden des Prinzips der geringsten Rechte

Erstellen Sie dedizierte SQL Server Anmeldungen mit nur den Berechtigungen, die Ihre Anwendung benötigt:

-- Create a login and user for the application
CREATE LOGIN [django_app]
WITH PASSWORD = '<strong-password>';

USE [<your-database>];

CREATE USER [django_app] FOR LOGIN [django_app];

-- Grant minimum required permissions
-- Read and write data
ALTER ROLE db_datareader ADD MEMBER [django_app];
ALTER ROLE db_datawriter ADD MEMBER [django_app];

-- Allow Django to create and alter tables during migrations
GRANT ALTER ON SCHEMA::dbo TO [django_app];
GRANT CREATE TABLE TO [django_app];
GRANT REFERENCES ON SCHEMA::dbo TO [django_app];

Für Anwendungen, die keine Migrationen in der Produktion ausführen, lassen Sie die Berechtigungen ALTER und CREATE TABLE aus:

-- Production application user (read/write only)
ALTER ROLE db_datareader ADD MEMBER [django_app];
ALTER ROLE db_datawriter ADD MEMBER [django_app];

GRANT EXECUTE ON SCHEMA::dbo TO [django_app]; -- If using stored procedures

Führen Sie Migrationen aus einem separaten, privilegierteren Bereitstellungsschritt aus:

-- Migration user (used only during deployments)
ALTER ROLE db_ddladmin ADD MEMBER [django_migrations];

Auswählen der richtigen Rolle

Die festen SQL Server-Datenbankrollen sind von den am wenigsten privilegierten bis zu den am meisten privilegierten geordnet. Wählen Sie die Rolle mit den geringsten Rechten aus, die Ihre Workload abdeckt, und eskalieren Sie nur bei Bedarf:

Role Grants Wann verwenden?
db_datareader SELECT in allen Benutzertabellen und -ansichten Benutzer mit schreibgeschütztem Zugriff auf Berichte
db_datawriter INSERT, UPDATEDELETE auf allen Benutzertabellen Laufzeitanwendungsbenutzer (mit db_datareader kombinieren)
db_ddladmin Erstellen, Ändern und Ablegen von Schemaobjekten Nur Migrations- oder Bereitstellungsbenutzer
db_owner Alle Datenbankberechtigungen, einschließlich Sicherheit Für Anwendungen vermeiden; DBAs vorbehalten

Für eine feinere Steuerung als mit den festen Rollen möglich, erstellen Sie eine benutzerdefinierte Datenbankrolle und GRANT nur die erforderlichen Berechtigungen für genau das Schema, das Ihre App verwendet. Wenn Sie alle Anwendungsobjekte in einem dedizierten Schema (z. B. app) beibehalten, können Sie Berechtigungen mit GRANT ... ON SCHEMA::app gezielt darauf beschränken, anstatt sich auf die datenbankweiten Rollen db_datareader und db_datawriter zu verlassen.

Note

Verwenden Sie für Anwendungsverbindungen weder das Konto sa noch die feste Datenbankrolle db_owner. Wenn die Anwendung kompromittiert wird, erhält ein Angreifer die vollständige Datenbankkontrolle.

Verhindern der SQL-Einfügung

Djangos ORM parametrisiert alle Abfragen automatisch. DIE SQL-Einfügung ist nur ein Risiko, wenn Sie rohes SQL verwenden:

Sicher: ORM-Abfragen

# Django parameterizes these automatically
users = User.objects.filter(email=user_input)
products = Product.objects.filter(price__lte=max_price)

Sicher: Parametrisiertes rohes SQL

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute(
        "SELECT * FROM products WHERE category = %s AND price < %s",
        [category, max_price],
    )

Unsicher: Zeichenfolgenformatierung in rohem SQL

# NEVER do this - vulnerable to SQL injection
cursor.execute(f"SELECT * FROM products WHERE category = '{category}'")
cursor.execute("SELECT * FROM products WHERE category = '%s'" % category)

Extra und RawSQL

Djangos extra() und RawSQL() akzeptieren rohe SQL-Fragmente. Parameter immer verwenden:

# Safe - parameterized
Product.objects.extra(where=["category = %s"], params=[category])

from django.db.models.expressions import RawSQL
Product.objects.annotate(
    discount=RawSQL("price * %s", [discount_rate])
)

Important

Nie verwenden extra() oder RawSQL() mit Zeichenfolgenformatierung. Diese umgehen die automatische Parametrisierung des ORM.

Konfigurieren von Django-Sicherheits-Middleware

Aktivieren Sie djangos integrierte Sicherheits-Middleware, um die Webebene zu schützen. Obwohl diese nicht datenbankspezifisch sind, schützen sie die Anwendung, die eine Verbindung mit Ihrer Datenbank herstellt:

# settings.py

# HTTPS enforcement
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000  # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Cookie security
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True

# Content security
SECURE_CONTENT_TYPE_NOSNIFF = True

Überwachen des Datenbankzugriffs

Aktivieren Sie SQL Server Überwachung, um Datenbankvorgänge aus Ihrer Django-Anwendung nachzuverfolgen:

-- Create a server audit (Azure SQL uses Azure SQL Auditing instead)
CREATE SERVER AUDIT [DjangoAudit]
TO FILE (FILEPATH = 'C:\Audits\')
WITH (ON_FAILURE = CONTINUE);

ALTER SERVER AUDIT [DjangoAudit] WITH (STATE = ON);

-- Create a database audit specification
USE [<your-database>];

CREATE DATABASE AUDIT SPECIFICATION [DjangoDbAudit]
FOR SERVER AUDIT [DjangoAudit]
ADD (SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo BY [django_app])
WITH (STATE = ON);

Aktivieren Sie für Azure SQL-Datenbank die Überwachung über das Azure Portal oder Azure CLI:

az sql db audit-policy update --resource-group <rg> --server <server> \
    --name <database> --state Enabled \
    --storage-account <storage-account>

Schützen vertraulicher Spalten mit Always Encrypted

Verwenden Sie für die Verschlüsselung auf Spaltenebene vertraulicher Daten wie SSNs, Kreditkartennummern oder Gehaltsdaten Always Encrypted. Der ODBC-Treiber verarbeitet Verschlüsselung und Entschlüsselung transparent:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "ColumnEncryption=Enabled",
        },
    },
}

Ausführliche Einrichtung einschließlich der Schlüsselverwaltung mit Azure Key Vault finden Sie unter "Always Encrypted with mssql-django".

Sicherheitscheckliste

Kategorie Praxis Priorität
Authentifizierung Verwenden Sie Microsoft Entra Authentifizierung für Azure SQL. Hoch
Credentials Speichern Sie geheime Schlüssel in Umgebungsvariablen oder Azure Key Vault. Hoch
Encryption Verwenden Sie ODBC-Treiber 18 (Verschlüsselung standardmäßig aktiviert) oder Encrypt=yes. Hoch
Injektion Verwenden Sie ORM-Abfragen oder parametrisierte rohe SQL-Daten. Sql wird nie im Zeichenfolgenformat formatiert. Hoch
Prinzip der geringsten Rechte Erstellen Sie dedizierte Anmeldungen mit mindestens erforderlichen Berechtigungen. Hoch
TLS Verwenden Sie nicht TrustServerCertificate=yes in der Produktion. Hoch
Django Aktivieren Sie SECURE_SSL_REDIRECT, sichere Cookies und HSTS. Medium
Überwachung Aktivieren Sie SQL Server Überwachung oder Azure SQL Überwachung. Medium
Spaltenverschlüsselung Verwenden Sie "Always Encrypted" für streng vertrauliche Spalten. Niedrig
Verbindung Legen Sie CONN_MAX_AGE und CONN_HEALTH_CHECKS fest, um veraltete Verbindungen zu verhindern. Niedrig