mssql-django için en iyi güvenlik uygulamaları

Bu makale, arka uç üzerinden SQL Server bağlanan Django uygulamalarına yönelik mssql-django güvenlik uygulamalarını kapsar. Bu uygulamalar Django'nun yerleşik güvenlik özelliklerini ve SQL Server güvenlik modelini tamamlar.

Parolalar yerine Microsoft Entra kimlik doğrulaması kullanma

Microsoft Entra kimlik doğrulaması depolanan veritabanı parolalarını ortadan kaldırır. Tüm Azure SQL bağlantıları için kullanın.

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",
        },
    },
}

Kimlik doğrulama yöntemlerinin tam listesi, mevcut sınırlamalar ve DefaultAzureCredential ile ManagedIdentityCredential içeren TOKEN örnekler için bkz. mssql-django ile Microsoft Entra kimlik doğrulaması.

Kimlik bilgilerini güvenli bir şekilde yönetme

SQL kimlik doğrulamasına ihtiyacınız olduğunda kimlik bilgilerini kaynak kodun dışında tutun.

Ortam değişkenleri

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

Üretim dağıtımları için gizli anahtarları Azure Key Vault'tan alın:

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",
        },
    },
}

Caution

Kimlik bilgilerini hiçbir zaman kaynak denetimine işlemeyin. .env dosyalarını .gitignore öğesine ekleyin. Kimlik bilgilerinin yanlışlıkla commit edilmesini taramak için git-secrets veya pre-commit kancalarını kullanın.

TLS şifrelemesini zorunlu kıl

SQL Server bağlantıları her zaman şifrelenmelidir. ODBC sürücüsü, ODBC Sürücüsü 18'den başlayarak bağlantıları varsayılan olarak şifreler:

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
        },
    },
}

ODBC Sürücüsü 17 kullanıyorsanız şifrelemeyi açıkça etkinleştirin:

"extra_params": "Encrypt=yes"

Caution

TrustServerCertificate=yes yalnızca kendinden imzalı sertifikalarla yerel geliştirme için kullanın. Üretimde kullanmayın. Sertifika zinciri doğrulamasını devre dışı bırakır ve ortadaki saldırgan riski artırır. Sunucuya güvenilir bir sertifika yükleyin ve ile TrustServerCertificate=nobağlanın.

En az ayrıcalık ilkesini uygulama

Yalnızca uygulamanızın ihtiyaç duyduğu izinlerle ayrılmış SQL Server oturum açma bilgileri oluşturun:

-- 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];

Üretimde geçişleri çalıştırmayan uygulamalar için ALTER ve CREATE TABLE izinlerini atlayın:

-- 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

Geçişleri ayrı, daha ayrıcalıklı bir dağıtım adımından çalıştırın:

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

Doğru rolü seçme

SQL Server sabit veritabanı rolleri en azdan en ayrıcalıklıya sıralanır. İş yükünüzü kapsayan en az ayrıcalıklı rolü seçin ve yalnızca gerektiğinde yükseltin:

Rolü Grants Ne zaman kullanılır?
db_datareader SELECT tüm kullanıcı tablolarında ve görünümlerinde Salt okunur raporlama kullanıcıları
db_datawriter INSERT, UPDATE, DELETE tüm kullanıcı tablolarında Çalışma zamanı uygulama kullanıcısı (db_datareader ile birleştirilmiş)
db_ddladmin Şema nesneleri oluşturma, değiştirme ve bırakma Yalnızca geçiş veya dağıtım kullanıcısı
db_owner Güvenlik de dahil olmak üzere tüm veritabanı izinleri Uygulamalar için kullanmaktan kaçının; veritabanı yöneticilerine ayırın

Sabit rollerin izin verdiğinden daha ayrıntılı denetim için özel bir veritabanı rolü ve GRANT yalnızca uygulamanızın kullandığı belirli şemada belirli izinleri oluşturun. Tüm uygulama nesnelerini özel bir şemada tutmak (örneğin, app), veritabanı genelindeki db_datareader ve db_datawriter rollerine güvenmek yerine izinleri GRANT ... ON SCHEMA::app ile sınırlandırmanıza olanak tanır.

Note

Uygulama bağlantıları için sa hesabını veya db_owner sabit veritabanı rolünü kullanmayın. Uygulamanın güvenliği aşılırsa, saldırgan tam veritabanı denetimine sahip olur.

SQL enjeksiyonunu önleme

Django'nun ORM'i tüm sorguları otomatik olarak parametreleştirir. SQL ekleme yalnızca ham SQL kullandığınızda bir risktir:

Güvenli: ORM sorguları

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

Güvenli: Parametreli ham 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],
    )

Güvenli değil: Ham SQL'de dize biçimlendirmesi

# 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 ve RawSQL

Django'nun extra() ve RawSQL() ham SQL parçacıklarını kabul eder. Her zaman parametreleri kullanın:

# 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

Dize biçimlendirmede asla extra() ya da RawSQL() kullanmayın. Bunlar ORM'nin otomatik parametreleştirmesini atlar.

Django güvenlik ara yazılımını yapılandırma

Web katmanını korumak için Django'nun yerleşik güvenlik ara yazılımını etkinleştirin. Bunlar veritabanına özgü olmasa da, veritabanınıza bağlanan uygulamayı korur:

# 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

Veritabanı erişimini denetleme

Django uygulamanızdan veritabanı işlemlerini izlemek için SQL Server denetimini etkinleştirin:

-- 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);

Azure SQL Veritabanı için Azure portalı veya Azure CLI aracılığıyla denetimi etkinleştirin:

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

Always Encrypted ile hassas sütunların güvenliğini sağlama

SSN'ler, kredi kartı numaraları veya maaş verileri gibi hassas verilerin sütun düzeyinde şifrelemesi için Always Encrypted kullanın. ODBC sürücüsü şifreleme ve şifre çözme işlemlerini saydam bir şekilde işler:

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

Azure Key Vault ile anahtar yönetimi dahil ayrıntılı kurulum için bkz. mssql-django ile Always Encrypted.

Güvenlik denetim listesi

Kategori Practice Priority
Authentication Azure SQL için Microsoft Entra kimlik doğrulamasını kullanın. Yüksek
Credentials Gizli anahtarları ortam değişkenlerinde veya Azure Key Vault'ta depolayın. Yüksek
Encryption ODBC Sürücüsü 18'i (varsayılan olarak şifreleme açık) veya Encrypt=yeskullanın. Yüksek
Enjeksiyon ORM sorgularını veya parametreli ham SQL'i kullanın. SQL'i asla dize biçimlendirmeyle oluşturmayın. Yüksek
En az ayrıcalık Gerekli en düşük izinlere sahip ayrılmış oturum açma bilgileri oluşturun. Yüksek
TLS Üretimde kullanmayın TrustServerCertificate=yes . Yüksek
Django SECURE_SSL_REDIRECT güvenli tanımlama bilgilerini ve HSTS'yi etkinleştirin. Orta
Auditing SQL Server denetimini veya Azure SQL Denetimi’ni etkinleştirin. Orta
Sütun şifreleme Çok hassas sütunlar için Always Encrypted kullanın. Low
Bağlantı Eski bağlantıları önlemek için CONN_MAX_AGE ve CONN_HEALTH_CHECKS ayarlayın. Low