Journal DJT-CSP : Django et sécurisation côté client

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
21
28
jan.
2021

Sommaire

Django et sécurisation côté client

Petit moment de pub : pour me faciliter la vie, j'ai développé récemment une extension pour Django-Debug-Toolbar
pour évaluer pendant le développement la valeur d'en-têtes HTTP liés à la sécurité en HTML : djt-csp.

Screenshot

Vous aurez sur chaque page la colonne de droite caractéristique de Django-Debug-Toolbar, avec les détails qui s'affichent en cliquant sur security score.

Il fonctionne sans connexion internet et évite d'utiliser l'outil en ligne de Mozilla.
Avec djt-csp, vous aurez ainsi le score sur chaque page. Il devrait être identique à celui fourni par Mozilla,
sachant que je fais comme si c'était du HTTPS pour certains calculs, même si ce n'est pas le cas, afin d'avoir quelque chose de représentatif du site définitif.

Comme il n'y a rien de plus à dire, j'en profite pour faire un petit rappel sur certains aspects de sécurité sur le web.

En-têtes HTTP pour la sécurité

Quand on souhaite sécuriser son site web, on commence souvent à présenter les attaques du client vers le serveur, et on protège donc le serveur contre le client.
Cependant, se limiter à ces attaques serait ignorer que votre site peut servir de vecteur à l'encontre du client (par exemple en présentant involontairement au client du code javascript malveillant), ou qu'il est possible
que votre client réalise à son insu des actions a priori légitimes (le faire poster des messages, par exemple).
Ces attaques peuvent se faire en intégrant votre page dans une autre ou orientant le client vers une page de votre site avec des données choisies par l'attaquant (via les paramètres de l'URL).

Heureusement, il est possible de limiter ces possibilités en indiquant ce que le navigateur web est censé pouvoir faire avec la page web que vous lui envoyez.
Bien sûr, cela signifie que votre navigateur coopère pleinement en prenant en compte les limitations indiquées par votre page.
Quelques exemples rapides :

  • indiquer que votre page devra toujours être accédée en HTTPS,
  • préciser l'empreinte des ressources externes (Javascript, notamment) pour éviter leur corruption, notamment si elles sont conservées par un tiers (on pense immédiatement aux CDN),
  • empêcher un fichier quelconque d'être confondu avec un fichier JavaScript,
  • empêcher votre site d'être intégré dans un site tiers,
  • empêcher votre site d'intégrer, à son insu, des éléments tiers,
  • empêcher l'envoi de formulaires depuis votre site vers un tiers.

Ces limitations peuvent être imposées via l'envoi de en-têtes HTTP (dans le plus pur respect de la séparation des couches réseau…) ou l'ajout d'attributs dans le HTML (pour les empreintes des ressources externes).
Voici les principaux en-têtes utilisés pour ce faire :

  • Strict-Transport-Security, pour indiquer que votre site doit toujours être accédé en HTTPS,
  • X-Content-Type-Options, empêchant le navigateur de confondre un fichier quelconque avec un script,
  • X-XSS-Protection pour bloquer les attaques par injection de JavaScript dans votre HTML,
  • X-Frame-Options encadrant le comportement des iframe,
  • Content-Security-Policy pour limiter les ressources qui peuvent être chargées ou utilisées,
  • Referrer-Policy afin de ne pas trop donner d'information quand clique sur des liens extérieurs,
  • Permissions-Policy servant à limiter l'accès aux périphériques locaux (caméra, micro, localisation), encore très récent et qui reprend le rôle de l'en-tête Feature-Policy.

Les cookies doivent également être protégés. Le serveur peut ainsi les rendre inaccessibles au trafic en clair (Secure), au JavaScript (HttpOnly) et aux autres sites (SameSite).

Enfin, les attaques CSRF (vous validez depuis un site malveillant B un formulaire qui est envoyé vers un site victime A) peuvent êtres contrées
avec une valeur aléatoire envoyée avec le formulaire et qui ne peut provenir que de A : ainsi, A est certain que le client a bien vu le formulaire depuis son propre site.

Intégration dans Django

Le framework Django est bien connu des développeurs web Python.
Je ne m'étendrais donc pas sur le sujet, mais sachez simplement que c'est un framework «tout-en-un», avec les connecteurs base de données, moteurs de rendu, etc.
De très nombreuses extensions sont disponibles étant donnée sa popularité.

De base, un certain nombre de ces en-têtes sont prévus par Django et sont réglables par les fameux settings:
- Strict-Transport-Security (SECURE_HSTS_INCLUDE_SUBDOMAINS, SECURE_HSTS_PRELOAD, SECURE_HSTS_SECONDS),
- X-Content-Type-Options (SECURE_CONTENT_TYPE_NOSNIFF),
- X-XSS-Protection (SECURE_BROWSER_XSS_FILTER),
- X-Frame-Options (X_FRAME_OPTIONS),
- Referrer-Policy (SECURE_REFERRER_POLICY).

D'autres réglages permettent également de déterminer le comportement des cookies utilisés par Django.
Il manque cependant un en-tête, Content-Security-Policy, qui est souvent plus dur à paramétrer et pourra être différent d'une page à l'autre.
Si de base, Django ne permet pas de le configurer, il existe tout de même un projet pour le faire : Django-CSP.

Vous pouvez ainsi désactiver le JavaScript intégré au HTML sur la plupart de vos pages en ne l'activant que sur celles qui le réclament absolument.
Comme il est délicat d'utiliser CSP sur un site existant, il est souvent conseillé de commencer avec des options minimales puis de renforcer progressivement les protections.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.