it-swarm-eu.dev

Versuchen Sie, eine Django-basierte Site dazu zu bringen, nur HTTPS zu verwenden, und sind Sie sich nicht sicher, ob sie sicher ist?

Der EFF empfiehlt überall HTTPS verwenden auf Ihrer Site, und ich bin sicher, dass diese Site zustimmen würde. Als ich eine Frage zur Verwendung von Django] zum Implementieren von HTTPS auf meiner Anmeldeseite stellte, war das sicherlich die Antwort, die ich erhielt :)

Also versuche ich genau das zu tun. Ich habe ein Django/Nginx-Setup, das ich nur für HTTPS konfigurieren möchte - es funktioniert, aber es gibt Probleme. Noch wichtiger ist, ich bin sicher, ob es wirklich sicher ist , obwohl ich die https Präfix.

Ich habe nginx so konfiguriert, dass alle http-Seiten zu https umgeleitet werden, und dieser Teil funktioniert. Allerdings ... Angenommen, ich habe eine Seite https://mysite.com/search/ Mit einem Suchformular/einer Suchschaltfläche. Ich klicke auf die Schaltfläche, Django verarbeitet das Formular und leitet auf eine Ergebnisseite um, die http://mysite.com/search/results?term="foo".

Diese URL wird an den Browser gesendet, der sie zurück an den Nginx-Server sendet, der eine permanente Umleitung zu einem https- Präfix durchführt Version der Seite. (Zumindest denke ich , dass das passiert - sicherlich IE warnt mich, dass ich auf eine unsichere Seite gehe und dann gleich zurück zu einer sicheren Seite :)

Aber ist das wirklich sicher? Oder mindestens so viel Sicherheit wie eine Standard-HTTPS-Site? Ist die Tatsache, dass Django eine http-Präfix-URL überträgt, jemand, der die Sicherheit gefährdet? Ja, soweit ich das beurteilen kann, werden nur Seiten mit einem https-Präfix beantwortet, aber es wird einfach nicht beantwortet 't fühle mich richtig :) Sicherheit ist funky, wie diese Seite bestätigen kann, und ich mache mir Sorgen, dass mir etwas fehlt.

63
John C

Sichern Sie Ihre Cookies

In settings.py setzen Sie die Zeilen

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

cookies werden nur über HTTPS-Verbindungen gesendet. Außerdem möchten Sie wahrscheinlich auch SESSION_EXPIRE_AT_BROWSER_CLOSE=True. Hinweis: Wenn Sie ältere Versionen von Django (weniger als 1.4)) verwenden, gibt es keine Einstellung für sichere CSRF-Cookies. Als schnelle Lösung können Sie CSRF-Cookies nur dann sicher machen, wenn die Sitzungscookie ist sicher (SESSION_COOKIE_SECURE=True), indem Django/middleware/csrf.py bearbeitet wird:

class CsrfViewMiddleware(object):
   ...
   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 or None)

Direkte HTTP-Anforderungen an HTTPS im Webserver

Als Nächstes möchten Sie eine Umschreiberegel, die http-Anforderungen an https umleitet, z. B. in Nginx

server {
   listen 80;
   rewrite ^(.*) https://$Host$1 permanent;
}

Djangos reverse -Funktions- und URL-Vorlagen-Tags geben nur relative Links zurück. Wenn Sie sich also auf einer https-Seite befinden, werden Sie über Ihre Links auf der https-Site gehalten.

Setzen Sie die OS-Umgebungsvariable HTTPS auf on

Schließlich (und meine ursprüngliche Antwort hat dies ausgeschlossen) müssen Sie die Umgebungsvariable des Betriebssystems HTTPS auf 'on' Aktivieren, damit Django https vollständig generierten Links voranstellt (zB wie bei HttpRedirectRequests). Wenn Sie mod_wsgi verwenden, können Sie die folgende Zeile hinzufügen:

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

zu deinem wsgi script . Wenn Sie uwsgi verwenden, können Sie eine Umgebungsvariable über den Befehlszeilenschalter --env HTTPS=on Oder durch Hinzufügen der Zeile env = HTTPS=on Zu Ihrer uwsgi-Datei .ini Hinzufügen. Wenn nichts anderes funktioniert, können Sie als letzten Ausweg Ihre Einstellungsdatei so bearbeiten, dass die Zeilen import os Und os.environ['HTTPS'] = "on" Angegeben werden, die ebenfalls funktionieren sollten.

Wenn Sie wsgi verwenden, möchten Sie möglicherweise zusätzlich die Umgebungsvariable wsgi.url_scheme Auf 'https' Setzen, indem Sie diese zu Ihrem settings.py Hinzufügen:

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

Der wsgi-Rat mit freundlicher Genehmigung von Kommentar von Vijayendra Bapte .

Sie können die Notwendigkeit dieser Umgebungsvariablen erkennen, indem Sie Django/http/__init__.py Lesen:

def build_absolute_uri(self, location=None):
    """
    Builds an absolute URI from the location and the variables available in
    this request. If no location is specified, the absolute URI is built on
    ``request.get_full_path()``.
    """
    if not location:
        location = self.get_full_path()
    if not absolute_http_url_re.match(location):
        current_uri = '%s://%s%s' % (self.is_secure() and 'https' or '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"

Zusätzliche Webserver-Dinge:

Nehmen Sie der Rat dieses Typen und aktivieren Sie die HSTS-Header in Ihrem Webserver, indem Sie eine Zeile zu nginx hinzufügen:

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

Dies teilt Ihrem Webbrowser mit, dass Ihre Website in den nächsten 10 Jahren nur HTTPS verwendet. Wenn bei einem zukünftigen Besuch desselben Browsers ein Man-in-the-Middle-Angriff erfolgt (z. B. wenn Sie sich bei einem böswilligen Router in einem Café anmelden, der Sie zu einer HTTP-Version der Seite weiterleitet), wird sich Ihr Browser daran erinnern Es soll nur HTTPS sein und verhindern, dass Sie versehentlich Ihre Informationen preisgeben. Aber seien Sie vorsichtig, Sie können Ihre Meinung nicht ändern und später entscheiden, dass ein Teil Ihrer Domain über HTTP bereitgestellt wird (bis die 10 Jahre vergangen sind, seit Sie diese Zeile entfernt haben). Planen Sie also voraus; Wenn Sie beispielsweise glauben, dass Ihre Anwendung bald an Popularität gewinnt und Sie sich auf einem großen CDN befinden müssen, das HTTPS zu einem Preis, den Sie sich leisten können, nicht gut handhabt, liegt möglicherweise ein Problem vor.

Stellen Sie außerdem sicher, dass Sie schwache Protokolle deaktivieren. Senden Sie Ihre Domain an einen SSL-Test , um nach möglichen Problemen zu suchen (zu kurzer Schlüssel, kein TLSv1.2, fehlerhafte Protokolle usw.). Zum Beispiel verwende ich in Nginx:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
67
dr jimbob

Das Umleiten von einer beliebigen http: // zur entsprechenden https: // Seite ist der falsche Ansatz. Konfigurieren Sie nginx so, dass Port 80 an https: //yourdomain.ext/ umgeleitet wird.

server {
       listen 80;
       rewrite ^/? https://$Host/ permanent;
 }

oder ähnliches (lesen Sie das nächste Nginx-Handbuch in Ihrer Nähe) und führen Sie Ihre Anwendung überhaupt nicht auf Port 80 (http) aus. Andere Anforderungen an Port 80 werden in 404 oder ähnliches aufgelöst (passen Sie sie an und sagen Sie, dass Ihre App jetzt sicher ist und nur unter https ausgeführt wird, wobei ein Link auf https: //IhreDomäne.ext verweist/ ). Führen Sie dann Ihre App nur auf dem Listen-Port 443 (https) aus. Die Verwendung relativer Pfade in Ihrem Code ist jetzt sicher, da alle in den vollständigen https: // Pfad aufgelöst werden und Sie das Abprallen von http zu https vermeiden!

3
esskar

sie sollten zusätzlich ein HSTS-Header von nginx senden, um den Clients (Browsern) anzuzeigen, dass sie nur HTTPS verwenden sollen

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

Bei einem allgemeinen Setup leiten Sie https-Datenverkehr von Ihrem Webserver (d. H. Nginx) an einen lokalen http-Server weiter, auf dem die App Django] ausgeführt wird.

In diesem Fall ist es einfacher, die Einstellung SECURE_PROXY_SSL_HEADER Zu verwenden (verfügbar seit Django 1.4.)

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

3
Sebastian

Ich denke, was Sie suchen, ist eine Django Middleware, die http in https umschreibt. Etwas Ähnliches wie das, was in this Frage zu SO , wobei eine Antwort auf diese Middleware zeigt. Sie müssen wahrscheinlich Ihre eigene Middleware schreiben, aber es sollte einfach sein. (Eine gut fokussierte Frage zu SO bringt Sie in die richtige Richtung, wenn Sie Hilfe beim Einstieg benötigen.)

2
bstpierre

In den meisten Fällen können Sie Apache oder etwas so einstellen, dass es zu https umleitet, wie in der akzeptierten Antwort beschrieben. Und wenn Sie können, wäre das besser für die Leistung und für Dateien, die außerhalb von Django bereitgestellt werden.

Wenn Sie jedoch kein Debugging durchführen können oder möchten, möchte ich darauf hinweisen, dass Django kürzlich (1.8) ein SecurityMiddleware eingeführt hat, das https-Redirects als eines davon enthält mehrere Funktionen.

Weitere Informationen finden Sie in der Dokumentation . Fügen Sie grundsätzlich Django.middleware.security.SecurityMiddleware und setze SECURE_SSL_REDIRECT = True.

(Der in der akzeptierten Antwort erwähnte Header kann auch von dieser Middleware gesetzt werden.)

2
Mark

Sie müssen Django) konfigurieren, um beides zu generieren

  1. https://domain/path Links mit dem https: planen,
  2. //domain/path Links ohne Schema (der Browser interpretiert diese so, dass sie dasselbe Schema haben wie die Seite, für die sie gerade geöffnet sind) oder
  3. /path Links ohne Schema oder Domain (der Browser interpretiert diese so, dass sie dasselbe Schema und dieselbe Domain haben wie die Seite, auf die sie gerade verweisen).
1
yfeldblum