Question:
Vous essayez de faire en sorte qu'un site basé sur Django utilise uniquement HTTPS, vous ne savez pas s'il est sécurisé?
John C
2011-11-17 02:46:25 UTC
view on stackexchange narkive permalink

L'EFF recommande d'utiliser HTTPS partout sur votre site, et je suis sûr que ce site serait d'accord. Quand j'ai posé une question sur l'utilisation de Django pour implémenter HTTPS sur ma page de connexion, c'était certainement la réponse que j'ai eue :)

J'essaie donc de faire exactement cela. J'ai une configuration Django / nginx que j'essaie de configurer uniquement pour HTTPS - cela fonctionne en quelque sorte, mais il y a des problèmes. Plus important encore, je suis sûr que c'est vraiment sécurisé , malgré le préfixe https .

J'ai configuré nginx pour rediriger toutes les pages http vers https , et cette partie fonctionne. Cependant ... Disons que j'ai une page, https://monsite.com/search/ , avec un formulaire / bouton de recherche dessus. Je clique sur le bouton, Django traite le formulaire et effectue une redirection vers une page résultats , qui est http://monsite.com/search/results?term="foo".

Cette URL est envoyée au navigateur, qui la renvoie retour au serveur nginx, qui effectue une redirection permanente vers un https - version préfixée de la page. (Au moins, je pense que c'est ce qui se passe - certainement IE me prévient que je vais sur une page non sécurisée, puis je reviens directement à une page sécurisée :)

Mais c'est est-ce vraiment sécurisé? Ou, au moins autant de sécurité qu'un site standard uniquement HTTPS aurait? Le fait que Django transmette une URL de préfixe http est-il une compromission de la sécurité? Oui, pour autant que je sache, seules les pages qui ont un préfixe https reçoivent une réponse, mais cela ne semble pas juste :) La sécurité est funky, comme ce site peut en témoigner, et J'ai peur qu'il me manque quelque chose.

Comment définissez-vous l'attribut d'action du formulaire? Si vous le forcez à l'URL https complète, cela résout-il le problème?
@mikeazo, la syntaxe HTML que j'utilise est `
ne diffusez aucune page sur HTTP à l'exception d'une page qui redirige vers votre site sécurisé ou affiche un message avec un lien vers votre site sécurisé. Et seul HTTPS n'est pas égal à un site sécurisé, HTTPS assure uniquement que votre trafic est crypté entre votre navigateur et votre serveur rien de plus. Alors n'ignorez pas d'autres choses et intégrez la sécurité dans votre application
@JohnC a corrigé une faute de frappe (njinx) pour nginx.
Sept réponses:
dr jimbob
2011-11-17 05:06:21 UTC
view on stackexchange narkive permalink

Sécurisez vos cookies

Dans settings.py mettez les lignes

  SESSION_COOKIE_SECURE = TrueCSRF_COOKIE_SECURE = True  

et les cookies ne seront envoyés que via des connexions HTTPS. De plus, vous voulez probablement aussi SESSION_EXPIRE_AT_BROWSER_CLOSE = True . Notez que si vous utilisez des versions plus anciennes de django (inférieures à 1.4), il n'y a pas de paramètre pour les cookies CSRF sécurisés. En guise de solution rapide, vous pouvez simplement sécuriser le cookie CSRF lorsque le cookie de session est sécurisé ( SESSION_COOKIE_SECURE = True ), en éditant django / middleware / csrf.py :

  classe CsrfViewMiddleware (objet): ... def process_response (self, request, response): ... response.set_cookie (settings.CSRF_COOKIE_NAME, request.META ["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52, domain = settings.CSRF_COOKIE_DOMAIN, secure = settings.SESSION_COOKIE_SECURE ou None)  

Diriger les requêtes HTTP vers HTTPS dans le serveur Web

Ensuite, vous voulez une règle de réécriture qui redirige les requêtes http vers https, par exemple dans nginx

  server {listen 80; réécrire ^ (. *) https: // $ host $ 1 permanent;}  

La fonction reverse de Django et les balises de modèle d'url ne renvoient que des liens relatifs; donc si vous êtes sur une page https, vos liens vous garderont sur le site https.

Définissez la variable d'environnement HTTPS du système d'exploitation sur on

Enfin, (et ma réponse d'origine excluait cela), vous devez activer la variable d'environnement OS HTTPS sur 'on' afin que django ajoute https aux liens entièrement générés (par exemple, comme avec HttpRedirectRequest s ). Si vous utilisez mod_wsgi, vous pouvez ajouter la ligne:

  os.environ ['HTTPS'] = "on"  

à votre script wsgi. Si vous utilisez uwsgi, vous pouvez ajouter une variable d'environnement par le commutateur de ligne de commande --env HTTPS = on ou en ajoutant la ligne env = HTTPS = on à votre uwsgi Fichier .ini . En dernier recours, si rien d'autre ne fonctionne, vous pouvez modifier votre fichier de paramètres pour avoir les lignes import os et os.environ ['HTTPS'] = "on" , qui devrait également fonctionner.

Si vous utilisez wsgi, vous pouvez également définir la variable d'environnement wsgi.url_scheme sur 'https' en ajoutant ceci à votre settings.py :

  os.environ ['wsgi.url_scheme'] = 'https'  

Le wsgi conseil grâce au commentaire de Vijayendra Bapte.

Vous pouvez voir la nécessité de cette variable d'environnement en lisant django / http / __ init__.py :

  def build_absolute_uri (self, location = None): "" "Construit un URI absolu à partir de l'emplacement et des variables disponibles dans cette requête. Si aucun emplacement n'est spécifié, l'URI absolu est construit sur` `request .get_full_path () ``. "" "sinon location: location = self.get_full_path () sinon absolu_http_url_re.match (location): current_uri = ' % s: //% s% s '% (self.is_secure () et' https 'ou' http ', self.get_host (), self.path) location = urljoin (current_uri, location) return iri_to_uri (location) def is_secure (self): return os.environ.get ("HTTPS") == "on"  

Autres éléments du serveur Web:

Prenez celui de ce type conseil et activez les en-têtes HSTS sur votre serveur Web en ajoutant une ligne à nginx:

  add_header Strict-Transport-Security max-age = 31536000;  

Cela indique à votre navigateur Web que votre site Web pour les 10 prochaines années utilisera uniquement HTTPS. S'il y a une attaque Man-in-the-middle lors d'une prochaine visite à partir du même navigateur (par exemple, vous vous connectez à un routeur malveillant dans un café qui vous redirige vers une version HTTP de la page), votre navigateur se souviendra il est censé être uniquement HTTPS et vous empêche de divulguer vos informations par inadvertance. Mais soyez prudent à ce sujet, vous ne pouvez pas changer d'avis et décider plus tard qu'une partie de votre domaine sera servie via HTTP (jusqu'à ce que les 10 ans se soient écoulés depuis la suppression de cette ligne). Alors planifiez à l'avance; Par exemple, si vous pensez que votre application pourrait bientôt gagner en popularité et que vous devrez être sur un gros CDN qui ne gère pas bien HTTPS à un prix abordable, vous pourriez avoir un problème.

Assurez-vous également de désactiver les protocoles faibles. Soumettez votre domaine à un test SSL pour vérifier les problèmes potentiels (clé trop courte, ne pas utiliser TLSv1.2, utiliser des protocoles défectueux, etc.). Par exemple, dans nginx, j'utilise:

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH + ECDSA + AESGCM EECDH + aRSA + AESGCM EECD SHA + ECDH SHA256 EECDH + aRSA + SHA384 EECDH + aRSA + SHA256 EECDH + aRSA + RC4 EECDH EDH + aRSA RC4! ANULL! ENULL! LOW! 3DES! MD5! EXP! PSK! SRP! DSS ";  
Cependant, en théorie, si vous accédez à une page http, un attaquant pourrait changer la redirection vers une page contrôlée par un attaquant, n'est-ce pas? Ils ne peuvent pas voler le cookie, mais ils pourraient quand même faire des dégâts.
mikeazo: Je suis d'accord si un utilisateur se rend sur http://example.com qui est censé rediriger vers https://example.com, un attaquant peut usurper mon site vers un qui redirige vers un autre serveur https dont il a même potentiellement des certificats signés légitimement pour. Cependant, ce problème ne peut pas être résolu; l'utilisateur a essayé d'accéder à un site non sécurisé. (Même si je désactive simplement ma version http; si les utilisateurs accèdent encore occasionnellement à la version http, un attaquant MITM pourrait toujours rediriger ces personnes.) Espérons que les utilisateurs remarqueront le nom de domaine différent ou apprendront simplement à utiliser la version https uniquement.
droit, mais dans ce cas, l'utilisateur ne se rend pas intentionnellement sur une page Web non sécurisée. L'utilisateur accède à une page Web sécurisée, clique sur Soumettre, est automatiquement envoyé vers une page Web non sécurisée et est automatiquement redirigé vers une page sécurisée.
Une partie du problème @drjimbob, est que DJango * crée * des liens internes - quand je fais un HttpResponseRedirect vers un nom de vue inversé, le résultat final a un préfixe http. Maintenant, je viens de coder un décorateur qui remplace http par https, donc Django redirigera correctement. ** Question **, cependant - Je n'ai pas trouvé CSRF_COOKIE_SECURE dans la documentation Django 1.3, d'où vient-il? Merci.
Soupir ... Je viens de trouver [CSRF_COOKIE_SECURE] (https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#csrf-cookie-secure). Pour une raison quelconque, le standard [Django Docs] (https://docs.djangoproject.com/en/1.3/) ne voulait pas le trouver. Apparemment, c'est dans la documentation de développement, mais pas dans la documentation de la version 1.3. Maintenant, je dois décider si cela vaut la peine de télécharger la dernière version. :)
@JohnC Je suis juste curieux. Cette solution vous a-t-elle aidé à résoudre votre problème? Plus précisément, avec le lien interne, est-il toujours http ou https maintenant? Merci.
@CppLearner, Je soupçonne que ma question n'était pas très claire. Django semblait générer des liens en utilisant un préfixe `http`, que le serveur nginx a redirigé vers` https` - et tout ce que je me demandais, c'était s'il y avait des problèmes de sécurité avec ce processus. Depuis, j'ai écrit un middleware qui ajoute un `https` à toutes les pages générées en interne par Django, donc la question n'est pas vraiment pertinente (du moins pour moi). Et jimbob, en fait, je n'essayais pas * d'utiliser `http` dans une partie du site, il semblait simplement que Django n'avait pas d'autre option, à l'époque.
@JohnC Merci pour la réponse rapide, ainsi qu'au Dr Jimbob. Je vais essayer ceci plus tard cette semaine. JohnC, votre question est certainement quelque chose que je me pose également. Merci.
dr jimbob, edit-4 est une * excellente * solution au problème, bien meilleure que l'écriture d'un composant middleware. Pourriez-vous l'ajouter comme réponse à [ma question ici] (http://stackoverflow.com/q/8015685/78409), et je vais le cocher.
@JohnC - Désolé pour les réponses originales incorrectes. Je n'utilisais pas de `HttpRedirectResponse` dans mes applications d'origine et je n'ai jamais eu le problème; mais une fois que vous en avez parlé; a fait une recherche rapide du code source et a trouvé le correctif. J'ai reformaté la réponse ici et également mis SO.
C'est génial, merci! Une remarque importante dans vos paramètres.py ** DEBUG ** doit être ** False **
@Gourneau - Pourquoi pensez-vous que «DEBUG» doit être «False»? Évidemment, cela devrait être dans une application sécurisée (donner aux attaquants des informations de débogage les aide énormément), mais chaque partie de la réponse semble fonctionner quel que soit le paramètre du mode de débogage.
@drjimbob Vous avez raison. J'ai pris cela pour un autre problème. Lors de l'utilisation de heroku request.is_sercure () renvoie toujours False en raison de leurs proxys http inversés. Cela provoquait la redirection de APPEND_SLASH vers http au lieu de https. La solution consiste à ajouter `SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https',)` à settings.py
excellente solution. J'utilise nginx + uwsgi au lieu de mod_wsgi. Comment définir `os.environ ['HTTPS'] =" on "` dans uwsgi s'il vous plaît? cette partie n'était pas très claire pour moi.
@Kave - Merci. Vous devez définir une variable d'environnement avec une clé «HTTPS» sur «on». Donc, si vous appelez uwsgi à partir de la ligne de commande via le premier exemple sur la [page django uwsgi] (https://docs.djangoproject.com/en/1.4/howto/deployment/wsgi/uwsgi/), vous devez ajouter le flag `--env HTTPS = on`. Ou si vous aviez un fichier `uwsgi.ini`, vous ajouteriez la ligne:` env = HTTPS = on`. (La configuration est exactement identique à ce que vous faites pour définir la variable d'environnement DJANGO_SETTINGS_MODULE. Remplacez simplement `DJANGO_SETTINGS_MODULE` par` HTTPS` et sa valeur par `on`).
Il pourrait être intéressant de mentionner l'inclusion de l'en-tête HSTS (comme suggéré par @that-guy-from-over-there). Plus d'informations à ce sujet ici: http://mikkel.hoegh.org/blog/2010/09/09/protecting-your-users-phishing-apache-rules-hsts/
Si vous utilisez wsgi pour héberger votre application django, vous devez définir une variable d'environnement: environ ['wsgi.url_scheme'] = 'https' pour https://github.com/django/django/blob/master/django/ core / handlers / wsgi.py # L115
@VijayendraBapte - Ajoutera cela. Notez qu'ils ont toujours le paramètre `environ ['HTTPS'] = 'on'` dans d'autres endroits (par exemple, voir: https://github.com/django/django/blob/master/django/http/request.py# L137-L138). Certes, je ne suis pas sûr de la logique si votre application rend `WSGIRequest`s ou` HttpRequest`s quand et si le `_get_scheme` dans` HttpRequest` est remplacé. Probablement plus sûr d'utiliser les deux.
La recommandation est d'ajouter `environ ['HTTPS'] = 'on'` à wsgi.py et` os.environ [' wsgi.url_scheme '] =' https'` à settings.py. Ces deux éléments peuvent-ils être stockés en toute sécurité dans wsgi.py?
esskar
2011-11-17 05:19:48 UTC
view on stackexchange narkive permalink

La redirection de n'importe quelle page http: // vers la page https: // correspondante n'est pas la bonne approche.Configurez nginx pour rediriger le port 80 vers https: //yourdomain.ext/

  serveur {écoute 80; réécrire ^ /? https: // $ hôte / permanent; }  

ou similaire (consultez le prochain manuel nginx près de chez vous) et n'exécutez pas du tout votre application sur le port 80 (http). Ainsi, d'autres requêtes sur le port 80 se résolvent en 404 ou similaire (personnalisez-le, en disant que votre application est désormais sécurisée et ne fonctionne que sur https avec un lien pointant vers https: //yourdomain.ext/) . Exécutez ensuite votre application uniquement sur le port d'écoute 443 (https). L'utilisation de chemins relatifs dans votre code est désormais sécurisée, car ils se résolvent tous vers le chemin complet https: // et vous évitez le rebond de http vers https!

Malheureusement, c'est exactement comme ça que je le fais - j'ai configuré nginx pour écouter sur 80, réécrire en https et un autre bloc de serveur qui écoute sur 443 et passe par Django (enfin, uWsgi). Pourtant, c'est Django qui génère les liens http (et je n'ai pas encore trouvé comment changer cela). Je ne vois pas comment ils se résolvent en https, sans passer par le navigateur client au préalable :(
Sebastian
2012-07-10 02:43:00 UTC
view on stackexchange narkive permalink

Une configuration courante vous permettra de transférer le trafic https de votre serveur Web (c'est-à-dire Nginx) vers un serveur http local exécutant l'application Django.

Dans ce cas, il sera plus facile d'utiliser le SECURE_PROXY_SSL_HEADER paramètre (disponible depuis Django 1.4.)

https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER

that guy from over there
2013-07-14 21:08:11 UTC
view on stackexchange narkive permalink

vous devez en outre envoyer un HSTS-Header depuis nginx, indiquant aux clients (navigateurs) qu'ils utiliseront uniquement HTTPS

  add_header Strict-Transport-Security max -age = 31536000;  
Cet en-tête HSTS peut également être défini dans Django, bien que notez la [documentation Django conseille] (https://docs.djangoproject.com/en/1.10/ref/middleware/#http-strict-transport-security) "c'estune bonne idée d'utiliser d'abord une petite valeur pour tester, par exemple, [...] 3600 pendant une heure "au cas où ce paramètre casse quoi que ce soit.Je suppose que la même chose s'appliquerait pour ce qui précède.
bstpierre
2011-11-17 21:08:04 UTC
view on stackexchange narkive permalink

Je pense que vous recherchez un middleware Django qui réécrira http en https . Quelque chose de similaire à ce qui est abordé dans cette question sur SO, où une réponse pointe vers ce middleware. Vous devrez probablement écrire votre propre middleware, mais cela devrait être simple. (Une question bien ciblée sur le SO vous orientera dans la bonne direction si vous avez besoin d'aide pour commencer.)

Mark
2015-06-14 17:22:12 UTC
view on stackexchange narkive permalink

Dans la plupart des cas, vous pouvez configurer Apache ou quelque chose pour rediriger vers https, comme décrit dans la réponse acceptée. Et si vous le pouvez, ce serait mieux, pour les performances et pour les fichiers servis en dehors de Django.

Mais si vous ne pouvez pas, ou voulez faire du débogage, alors je voudrais souligner que Django récemment (1.8) a introduit un SecurityMiddleware qui a des redirections https comme l'une de ses nombreuses fonctions.

Plus d'informations sont disponibles dans la documentation. En gros, ajoutez django.middleware.security.SecurityMiddleware et définissez SECURE_SSL_REDIRECT = True .

(L'en-tête mentionné par la réponse acceptée peut également être défini par ce middleware.)

yfeldblum
2011-11-18 08:07:37 UTC
view on stackexchange narkive permalink

Vous devez configurer django pour générer des liens

  1. https: // domaine / chemin avec le schéma https: ,
  2. // domaine / chemin liens sans schéma (le navigateur les interprétera comme ayant le même schéma que la page sur laquelle il est actuellement ouvert), ou
  3. Liens / path sans schéma ni domaine (le navigateur les interprétera comme ayant le même schéma et le même domaine que la page vers laquelle il pointe actuellement).


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...