Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo aborda as práticas de segurança para aplicativos Django que se conectam a SQL Server por meio do mssql-django back-end. Essas práticas complementam os recursos de segurança internos do Django e o modelo de segurança do SQL Server.
Use a autenticação do Microsoft Entra em vez de senhas
A autenticação do Microsoft Entra elimina senhas armazenadas de bancos de dados. Use-o para todas as conexões SQL do Azure.
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",
},
},
}
Para obter a lista completa de métodos de autenticação, ressalvas atuais e exemplos com TOKEN, DefaultAzureCredential e ManagedIdentityCredential, consulte autenticação do Microsoft Entra com mssql-django.
Gerenciar credenciais com segurança
Quando precisar de autenticação SQL, mantenha as credenciais fora do código-fonte.
Variáveis de ambiente
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
Para implantações de produção, recupere segredos do Azure Key Vault:
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",
},
},
}
Cuidado
Nunca confirme credenciais no controle do código-fonte. Adicionar .env arquivos a .gitignore. Use git-secrets ou pré-confirmar ganchos para verificar se há confirmações de credenciais acidentais.
Exigir criptografia TLS
SQL Server conexões devem ser sempre criptografadas. O driver ODBC criptografa conexões por padrão, começando com o Driver ODBC 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
},
},
}
Se você usar o ODBC Driver 17, habilite a criptografia explicitamente:
"extra_params": "Encrypt=yes"
Cuidado
Use TrustServerCertificate=yes somente para desenvolvimento local com certificados autoassinados. Não o use em produção. Desabilita a validação da cadeia de certificados e aumenta o risco de ataque de intermediário. Instale um certificado confiável no servidor e conecte-se com TrustServerCertificate=no.
Aplicar o princípio de privilégios mínimos
Crie logons SQL Server dedicados apenas com as permissões necessárias para seu aplicativo:
-- 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];
Para aplicações que não executam migrações em produção, omita as permissões ALTER e CREATE TABLE:
-- 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
Execute as migrações a partir de uma etapa de implantação separada, com mais privilégios:
-- Migration user (used only during deployments)
ALTER ROLE db_ddladmin ADD MEMBER [django_migrations];
Escolha a função certa
As funções de banco de dados fixas do SQL Server são ordenadas da menos privilegiada para a mais privilegiada. Escolha a função menos privilegiada que abrange sua carga de trabalho e só escalone quando necessário:
| Função | Grants | Quando usar |
|---|---|---|
| db_datareader |
SELECT em todas as tabelas e exibições do usuário |
Usuários com acesso somente leitura a relatórios |
| db_datawriter |
INSERT, UPDATE, DELETE em todas as tabelas de usuários |
Usuário de aplicativo de runtime (combinar com db_datareader) |
| db_ddladmin | Criar, alterar e soltar objetos de esquema | Somente usuário de migração ou implantação |
| db_owner | Todas as permissões de banco de dados, incluindo segurança | Evite aplicativos; reserva para DBAs |
Para um controle mais refinado do que as funções fixas permitem, crie uma função de banco de dados personalizada e GRANT apenas as permissões específicas no esquema específico que seu aplicativo usa. Manter todos os objetos do aplicativo em um esquema dedicado (por exemplo, app) permite restringir as concessões de permissões com GRANT ... ON SCHEMA::app, em vez de depender das funções db_datareader e db_datawriter aplicáveis a todo o banco de dados.
Note
Não use a conta sa nem a função fixa de banco de dados db_owner para conexões de aplicativos. Se o aplicativo estiver comprometido, um invasor obterá controle de banco de dados completo.
Impedir a injeção de SQL
O ORM do Django parametriza todas as consultas automaticamente. A injeção de SQL é apenas um risco quando você usa SQL bruto:
Consultas ORM seguras
# Django parameterizes these automatically
users = User.objects.filter(email=user_input)
products = Product.objects.filter(price__lte=max_price)
Seguro: SQL bruto parametrizado
from django.db import connection
with connection.cursor() as cursor:
cursor.execute(
"SELECT * FROM products WHERE category = %s AND price < %s",
[category, max_price],
)
Não seguro: formatação de cadeia de caracteres no SQL bruto
# 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 e RawSQL
O Django extra() e RawSQL() aceitam fragmentos brutos de SQL. Sempre use parâmetros:
# 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])
)
Importante
Nunca use extra() ou RawSQL() com formatação de cadeia de caracteres. Elas ignoram a parametrização automática do ORM.
Configurar o middleware de segurança do Django
Habilite o middleware de segurança interno do Django para proteger a camada da Web. Embora elas não sejam específicas do banco de dados, elas protegem o aplicativo que se conecta ao banco de dados:
# 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
Auditar o acesso ao banco de dados
Habilite SQL Server auditoria para acompanhar as operações de banco de dados do aplicativo Django:
-- 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);
Para Banco de Dados SQL do Azure, habilite a auditoria por meio do portal Azure ou CLI do Azure:
az sql db audit-policy update --resource-group <rg> --server <server> \
--name <database> --state Enabled \
--storage-account <storage-account>
Proteger colunas confidenciais com o Always Encrypted
Para criptografia em nível de coluna de dados confidenciais, como SSNs, números de cartão de crédito ou dados de salário, use Always Encrypted. O driver ODBC lida com criptografia e descriptografia de forma transparente:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": "ColumnEncryption=Enabled",
},
},
}
Para obter uma configuração detalhada, incluindo o gerenciamento de chaves com Azure Key Vault, consulte Always Encrypted com mssql-django.
Lista de verificação de segurança
| Categoria | Prática | Prioridade |
|---|---|---|
| Authentication | Use a autenticação do Microsoft Entra para o SQL do Azure. | Alto |
| Credentials | Armazene segredos em variáveis de ambiente ou Azure Key Vault. | Alto |
| Encryption | Use o ODBC Driver 18 (criptografia ativada por padrão) ou Encrypt=yes. |
Alto |
| Injeção | Use consultas de ORM ou SQL puro parametrizado. Nunca formate SQL como string. | Alto |
| Privilégios mínimos | Crie logons dedicados com permissões mínimas necessárias. | Alto |
| TLS | Não use TrustServerCertificate=yes em produção. |
Alto |
| Django | Ativar SECURE_SSL_REDIRECT, cookies seguros, HSTS. |
Medium |
| Auditing | Habilite a auditoria do SQL Server ou a Auditoria do SQL do Azure. | Medium |
| Criptografia de coluna | Use Always Encrypted para colunas altamente sensíveis. | Baixo |
| Conexão | Defina CONN_MAX_AGE e CONN_HEALTH_CHECKS para impedir conexões obsoletas. |
Baixo |