La sécurité dans Django¶
Ce document est un aperçu des fonctionnalités de sécurité dans Django. Il contient des conseils sur la sécurisation des sites basés sur Django.
Real-world security
Django’s web security implementations have been designed with security for real-world applications in mind. Django is a general-purpose web application framework, and its defaults reflect this - they will not be the best solution for every particular case. Special cases deserve special attention to their needs.
Web security requires a multi-layered approach. Securing only a single vector does not make a site secure overall, nor does a single apparent weakness necessarily compromise the entire site. This should be borne in mind particularly when assessing individual points in security audits.
Toujours nettoyer les contenus en provenance des utilisateurs¶
La règle d’or en matière de sécurité des applications web est de ne jamais faire confiance aux contenus contrôlés par les utilisateurs. C’est pourquoi toute donnée en provenance d’utilisateurs doit être nettoyée avant d’être utilisée dans l’application. Consultez la documentation sur les formulaires pour plus de détails sur la validation des saisies des utilisateurs dans Django.
Cross-site scripting (XSS) protection¶
In a cross-site scripting attack, malicious code in the form of a client-side script is injected into another user’s web browser, where it will be executed.
This is typically done by:
storing the malicious script in the database where it will be retrieved and presented to other users in their browsers, or
getting users to click a link which will cause the attacker’s JavaScript to be executed by the user’s browser.
Cross-site scripting attacks can originate from any untrusted source of data, including cookies or web services, if the data are not adequately sanitized before being published in a page.
Django templates provide protection against the majority of cross-site scripting attacks by automatically escaping characters that represent a risk (that is, HTML characters that could be interpreted by the browser to malicious effect are instead safely displayed).
However, the extent of this protection and its limitations should be understood.
Ambiguity between the developer’s intention and how the browser interprets HTML can expose the client to unintended code execution. Suppose that a developer creates:
<style class={{ var }}>...</style>
where var is expected to contain something like 'class1'. If var
were set to 'class1 onmouseover=javascript:func()' though, this could
result in unauthorized JavaScript execution due to differences in how browsers
will interpret this imperfect HTML.
Explicit template design, in which the quotes are not left to the variable to provide:
<style class="{{ var }}">...</style>
would eliminate this possibility.
It is also important to be particularly careful when using the is_safe
attribute with custom template tags, the safe template tag,
mark_safe, and when autoescape is turned off.
Django’s built-in escaping is intended to protect HTML output. If you are using the template system to output something other than HTML, the characters and strings that require escaping might be entirely different.
Additionally, be very careful when storing HTML in the database, especially when that HTML is retrieved and displayed. Unless the HTML is guaranteed to come from a trusted source - user input is not a trusted source - stored HTML should be checked and sanitized, preferably on input as well as output.
Cross-site request forgery (CSRF) protection¶
Les attaques CSRF permettent à une personne malveillante d’exécuter des actions en utilisant les données d’authentification d’un autre utilisateur sans que ce dernier ne s’en rende compte.
Django offre une protection intégrée contre la plupart des types d’attaques CSRF, pour autant que vous l’ayez activée et que vous l’utilisiez de manière appropriée. Toutefois, comme pour toute technique de protection, elle est limitée. Par exemple, il est possible de désactiver le module CSRF de manière globale ou pour certaines vues. Vous ne devriez le faire que si vous savez ce que vous faites. Il existe d’autres limites si votre site contient des sous-domaines qui ne sont pas sous votre contrôle.
La protection CSRF fonctionne en contrôlant un jeton dans chaque requête POST. Cela garantit qu’un utilisateur malveillant ne peut « rejouer » un envoi de formulaire POST sur votre site Web tout en faisant soumettre ce formulaire de manière involontaire par un autre utilisateur connecté. L’utilisateur malveillant devrait connaître le jeton secret qui est spécifique à l’utilisateur (en utilisant un cookie).
Lorsqu’il est déployé avec HTTPS, CsrfViewMiddleware vérifie que l’en-tête « HTTP referer » contient une URL de même origine (y compris le sous-domaine et le port). Comme HTTPS offre une sécurité supplémentaire, il est impératif de s’assurer que les connexions utilisent HTTPS quand c’est possible en redirigeant les requêtes de connexion non sécurisées et en utilisant HSTS pour les navigateurs qui le prennent en charge.
Soyez très prudent lorsque vous adaptez des vues avec le décorateur csrf_exempt et ne le faites qu’en cas d’absolue nécessité.
Protection contre l’injection SQL¶
L’injection SQL est un type d’attaque où un utilisateur malveillant est capable d’exécuter du code SQL arbitraire sur une base de données. Il peut en résulter des suppressions d’enregistrements ou des divulgations de données.
Les jeux de requête de Django sont prémunies contre les injections SQL car leurs requêtes sont construites à l’aide de la paramétrisation des requêtes. Le code SQL d’une requête est défini séparément de ses paramètres. Comme ceux-ci peuvent provenir de l’utilisateur et donc non sécurisés, leur échappement est assuré par le pilote de base de données sous-jacent.
Django permet aussi aux développeurs d’écrire des requêtes brutes ou d’exécuter du code SQL personnalisé. Ces possibilités devraient être exploitées de manière parcimonieuse et il faut toujours prendre la précaution d’échapper proprement tout paramètre pouvant être contrôlé par l’utilisateur. De plus, il faut être prudent en utilisant extra() et RawSQL.
Protection contre le détournement de clic (« clickjacking »)¶
Le détournement de clic est un type d’attaque où un site malveillant intègre un autre site dans un cadre. Cette attaque peut amener un utilisateur à cliquer de manière non désirée pour effectuer des actions non volontaires sur le site ciblé.
Django intègre une protection contre le détournement de clic sous la forme de l'intergiciel X-Frame-Options qui, dans un navigateur qui le prend en charge, peut empêcher un site d’être affiché à l’intérieur d’un cadre. Il est possible de désactiver cette protection par vue ou de configurer la valeur exacte de l’en-tête envoyé.
Cet intergiciel est fortement recommandé pour tout site qui n’a pas besoin de voir ses pages affichées dans un cadre par des sites tiers ou qui n’en a besoin que pour une section limitée du site.
SSL/HTTPS¶
Le déploiement de votre site en HTTPS est toujours mieux pour la sécurité. Sans cela, il est possible que des utilisateurs malveillants du réseau interceptent des données d’authentification ou toute autre information transférée entre le client et le serveur et, dans certains cas, pour des attaquants réseau actifs, que des données soient modifiées au passage, dans l’une ou l’autre direction.
Si vous souhaitez profiter de la protection ajoutée par HTTPS et l’activer sur votre serveur, il peut être nécessaire de procéder à quelques étapes supplémentaires :
Si nécessaire, définissez
SECURE_PROXY_SSL_HEADER, en prenant soin de bien comprendre les avertissements correspondants. Sinon, cela pourrait provoquer des vulnérabilités CSRF, et son application incorrecte peut aussi être dangereuse !Définissez
SECURE_SSL_REDIRECTàTrue, pour que les requêtes HTTP soient redirigées vers HTTPS.Prenez bonne note des mises en garde de
SECURE_PROXY_SSL_HEADER. Dans le cas d’un serveur mandataire inverse, il peut être plus simple ou plus sûr de configurer le serveur web principal pour qu’il fasse lui-même la redirection vers HTTPS.Utilisez des cookies « sécurisés ».
Si un navigateur se connecte initialement en HTTP, ce qui est le comportement par défaut de la plupart des navigateurs, il est possible que des cookies existants soient divulgués. Pour cette raison, vous devriez définir les réglages
SESSION_COOKIE_SECUREetCSRF_COOKIE_SECUREàTrue. Cela indique au navigateur qu’il ne doit envoyer les cookies que par des connexions HTTPS. Notez que cela signifie que les sessions ne fonctionneront pas en HTTP et que la protection CSRF empêchera l’acceptation de données POST par HTTP (ce qui ne pose pas de problème si vous redirigez tout le trafic HTTP vers HTTPS).Utilisez Sécurité de transport HTTP stricte (HSTS) (HSTS)
HSTS est un en-tête HTTP informant le navigateur que toute connexion future à un site particulier devra toujours utiliser HTTPS. Combiné avec la redirection des requêtes HTTP vers HTTPS, cela garantit que les connexions profiteront toujours de la sécurité ajoutée par SSL à partir du moment où une connexion réussie a eu lieu. HSTS peut être configuré soit avec
SECURE_HSTS_SECONDS,SECURE_HSTS_INCLUDE_SUBDOMAINSetSECURE_HSTS_PRELOAD, soit directement au niveau du serveur web.
Validation de l’en-tête Host¶
Django uses the Host header provided by the client to construct URLs in
certain cases. While these values are sanitized to prevent cross-site scripting
attacks, a fake Host value can be used for cross-site request forgery,
cache poisoning attacks, and poisoning links in emails.
Comme même des configurations de serveur Web apparemment sûres sont susceptibles d’accepter des en-têtes Host contrefaits, Django valide les en-têtes Host en les comparant avec le réglage ALLOWED_HOSTS dans la méthode django.http.HttpRequest.get_host().
Cette validation ne s’applique qu’avec get_host() ; si votre code accède directement à l’en-tête Host dans request.META, vous outrepassez cette protection de sécurité.
Pour plus de détails, consultez la documentation complète de ALLOWED_HOSTS.
Avertissement
Des versions précédentes de ce document recommandaient de configurer le serveur Web pour s’assurer qu’il valide les en-têtes HTTP Host entrants. Même si c’est toujours recommandé, bien des configurations de serveurs Web bien connus paraissant valider l’en-tête Host ne le font pas toujours en réalité. Par exemple, même si Apache est configuré pour que votre site Django soit servi depuis un hôte virtuel autre que celui par défaut ayant défini ServerName, il est encore possible qu’une requête HTTP corresponde à cet hôte tout en fournissant un en-tête Host contrefait. C’est pourquoi Django demande dorénavant que ALLOWED_HOSTS soit défini explicitement plutôt que de se fier à la configuration du serveur Web.
En plus, Django exige que vous activiez explicitement la prise en charge de l’en-tête X-Forwarded-Host (via le réglage USE_X_FORWARDED_HOST) si votre configuration l’exige.
Politique de référencement¶
Les navigateurs utilisent l’en-tête Referer comme moyen d’envoyer l’information de provenance de l’utilisateur à un site. En définissant une politique de référencement (Referrer Policy), vous pouvez aider à protéger la confidentialité de vos utilisateurs, en limitant les cas de figure où l’en-tête Referer est défini. Consultez la section sur la politique de référencement de l’intergiciel de sécurité pour plus de détails.
Politique d’ouverture d’origine croisée¶
L’en-tête cross-origin opener policy (COOP, politique d’ouverture d’origine croisée) permet aux navigateurs d’isoler une fenêtre de premier niveau à partir d’autres documents en les plaçant dans une groupe de contexte différent afin qu’ils ne puissent pas interagir directement avec la fenêtre de premier niveau. Si un document protégé par COOP ouvre une fenêtre pop-up, la propriété window.opener de celle-ci sera null. COOP protège contre les attaques d’origine croisée. Lisez la section sur la politique d’ouverture d’origine croisée de la référence de l’intergiciel de sécurité pour plus de détails.
Sécurité des sessions¶
Tout comme les limites de CSRF exigeant qu’un site soit déployé de manière à ce que des utilisateurs non fiables n’aient pas accès à d’éventuels sous-domaines, django.contrib.sessions présente également certaines limites. Consultez la section sur la sécurité du guide thématique des sessions pour plus de détails.
Contenu envoyé par les utilisateurs¶
Note
Considérez le service des fichiers statiques par un service en nuage ou un CDN pour éviter certains de ces problèmes.
Si votre site accepte les téléversements de fichiers, il est fortement conseillé de limiter ces téléversements dans la configuration de votre serveur web à une taille raisonnable afin d’empêcher les attaques par déni de service (DOS). Dans Apache, cela peut être facilement défini en utilisant la directive LimitRequestBody. Vous ne devriez pas uniquement compter sur
DATA_UPLOAD_MAX_MEMORY_SIZEetFILE_UPLOAD_MAX_MEMORY_SIZE.Si vous servez vous-même les fichiers statiques, soyez sûr que les gestionnaires comme
mod_phpd’Apache qui pourraient exécuter des fichiers statiques comme du code sont désactivés. Il n’est manifestement pas souhaitable que des utilisateurs puissent exécuter du code arbitraire en téléversant puis en accédant à un fichier spécialement prévu à cet effet.La gestion des envois de fichiers par Django présente certaines vulnérabilités lorsque ces fichiers sont ensuite servis selon des pratiques non sécurisées. Plus particulièrement, un fichier HTML peut être téléversé comme image si le fichier contient un en-tête PNG valide suivi de code HTML malicieux. Ce fichier passera avec succès les vérifications effectuées par la bibliothèque de traitement d’image utilisée par Django (Pillow) pour les champs
ImageField. Au moment où le fichier est ensuite affiché pour un utilisateur, il se peut qu’il soit affiché comme un fichier HTML en fonction du type et de la configuration du serveur Web.Il n’existe actuellement pas de solution technique à toute épreuve dans l’infrastructure Django pour valider de manière sûre tous les contenus de fichiers envoyés par les utilisateurs. Cependant, il existe un certain nombre de mesures à prendre pour diminuer les risques de telles attaques :
Une catégorie d’attaques peut être évitée en servant toujours les contenus envoyés par les utilisateurs à partir d’un autre nom de domaine de premier ou de deuxième niveau. Cela évite les attaques bloquées par les protections same-origin policy telles que les scripts inter-sites. Par exemple, si votre site est servi par
example.com, il serait imaginable de servir les contenus téléversés (cf. réglageMEDIA_URL) à partir d’un site nommécontenuutilisateur-example.com. Il n’est pas suffisant de servir le contenu à partir d’un sous-domaine tel quecontenuutilisateur.example.com.En plus de cette mesure, les applications peuvent choisir de définir une liste des extensions de fichiers autorisées pour les fichiers téléversés par les utilisateurs et configurer le serveur Web pour qu’il n’accepte de servir que ces fichiers.
Envoi de formulaire¶
Les envois de formulaires qui contiennent des fichiers ne sont pas limités par
DATA_UPLOAD_MAX_MEMORY_SIZE. Avec ASGI, la requête entière peut être stockée provisoirement sur disque avant qu’une validation de taille de fichier ait lieu. Il est fortement recommandé de limiter la taille maximale du corps des requêtes dans votre configuration de serveur web pour empêcher des attaques de type DOS (déni de service).
Politique de sécurité de contenu (CSP)¶
La politique de sécurité de contenu (Content Security Policy - CSP) est un mécanisme de sécurité des navigateurs qui aide a protéger les applications web contre les attaques telles que les scripts intersites (XSS) et d’autres attaques d’injection de contenu.
CSP permet aux applications web de définir quelles sources de contenu sont fiables, instruisant le navigateur de charger, exécuter ou produire des ressources uniquement à partir de ces sources. Cela crée en réalité une liste autorisée d’origines de contenu, réduisant ainsi le risque d’exécution de code malveillant.
Principaux bénéfices de l’activation de CSP :
Limitation des attaques XSS en bloquant les scripts dans les pages et en limitant le chargement de scripts externes.
Contrôle sur les ressources externes (par ex. images, polices, feuilles de style) autorisées à être chargées.
Prévention de l’intégration non désirée de votre site dans d’autres sites pour protéger contre le détournement de clics.
Signalement des violations vers un point de référence défini, activant la surveillance et le débogage.
Pour des instructions de configuration, consultez la documentation sur l”Utilisation de CSP, et référez-vous à l”Aperçu de CSP pour d’autres détails sur les directives et les réglages.
Limites et considérations¶
Bien que CSP soit un mécanisme de sécurité puissant, il est important de comprendre ses limites et ses implications, particulièrement lorsqu’il est utilisé dans Django :
Risques de politique d’exclusion : évitez d’exclure des chemins ou des réponses spécifiques de la protection CSP. En raison de la politique de même origine des navigateurs, une vulnérabilité sur une page non protégée (par ex. permettant l’injection arbitraire d’un script) pourrait être exploitée pour attaquer des pages protégées. L’exclusion d”une seule route peut affaiblir significativement la protection CSP générale sur un site.
Pénalité de performance : même si c’est généralement négligeable, la protection CSP ajoute un peu de calcul supplémentaire. La génération de nonce implique de la génération aléatoire sécurisée pour chaque requête concernée. Pour des applications à fort trafic, ou des environnements limités en ressources, mesurez l’impact en terme de performance selon la situation.
Prise en charge dans les navigateurs : alors que les niveaux 1 et 2 de CSP sont largement pris en charge, les directives plus récentes (niveau CSP 3+) ou les comportements de politique complexes peuvent varier d’un navigateur à l’autre. Testez votre politique parmi les différents environnements que vous avez l’intention de supporter.
Malgré ces limites, CSP reste une couche de sécurité importante et recommandée pour les applications web. La compréhension de ses contraintes vous aidera à concevoir un déploiement plus efficace et fiable.
Thèmes de sécurité supplémentaires¶
Même si Django offre nativement de bonnes protections de sécurité, il est toujours important de déployer proprement les applications et de profiter des protections de sécurité du serveur web, du système d’exploitation et d’autres composants.
Prenez soin de placer votre code Python en dehors de la racine du serveur web. Ceci pour garantir que le code Python ne puisse pas être accidentellement servi en texte pur (ou exécuté accidentellement).
Prenez garde aux fichiers envoyés par les utilisateurs.
Django ne limite pas les requêtes d’authentification des utilisateurs. Pour se protéger des attaques en force brute contre le système d’authentification, il faut envisager le déploiement d’un complément Django ou d’un module du serveur web pour limiter ces requêtes.
Assurez-vous de conserver secret votre réglage
SECRET_KEY, ainsi queSECRET_KEY_FALLBACKS, si vous l’utilisez.C’est une bonne pratique que de limiter l’accès au système de cache et à la base de données par un pare-feu.
Jetez un œil à la liste Top 10 du projet Open Web Application Security (OWASP) qui identifie quelques vulnérabilités fréquentes dans les applications Web. Bien que Django possède des outils pour affronter certains de ces problèmes, d’autres doivent être pris en compte durant la conception de votre projet.
Mozilla parle de différents sujets concernant la sécurité Web. Leurs pages contiennent également des principes de sécurité qui s’appliquent à tout système.