Cercando di creare un sito basato su Django usa solo HTTPS, non sono sicuro che sia sicuro?

62

Il FEP raccomanda utilizzando HTTPS ovunque sul tuo sito, e sono sicuro che questo sito sarebbe d'accordo . Quando ho posto una domanda sull'utilizzo di Django per implementare HTTPS nella mia pagina di accesso, è stato sicuramente la risposta che ho ricevuto :)

Quindi sto cercando di fare proprio questo. Ho una configurazione di Django / nginx che sto cercando di configurare solo per HTTPS - è un po 'funzionante, ma ci sono dei problemi. Ancora più importante, sono sicuro che sia veramente sicuro , nonostante veda il prefisso link .

Ho configurato nginx per reindirizzare tutte le pagine http a https, e quella parte funziona. Tuttavia ... Dire che ho una pagina, https://mysite.com/search/ , con un modulo di ricerca / pulsante su di esso. Faccio clic sul pulsante, Django elabora il modulo e reindirizza a una pagina risultati , che è http://mysite.com/search/results?term="foo" .

Questo URL viene inviato al browser, che lo invia back al server nginx, che esegue un reindirizzamento permanente a una versione% della versione della pagina con% co_de -prefixed. (Almeno io penso questo è ciò che sta accadendo - certamente IE mi avverte che sto andando a una pagina non sicura, e poi di nuovo a una pagina sicura:)

Ma questo veramente è sicuro? O almeno la sicurezza di un sito HTTPS standard? Il fatto che Django trasmetta un URL prefisso http, qualcuno compromette la sicurezza? Sì, per quello che posso dire, solo le pagine che hanno un prefisso https vengono risposte, ma semplicemente sentono giusto :) La sicurezza è funky, come può attestare questo sito, e Sono preoccupato che ci sia qualcosa che mi manca.

    
posta John C 16.11.2011 - 21:46
fonte

7 risposte

66

Proteggi i tuoi cookie

In settings.py inserisci le righe

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

e i cookie verranno inviati solo tramite le connessioni HTTPS. Inoltre, probabilmente vuoi anche SESSION_EXPIRE_AT_BROWSER_CLOSE=True . Nota se stai usando versioni precedenti di django (meno di 1.4), non c'è un'impostazione per i cookie CSRF sicuri. Come soluzione rapida, puoi semplicemente rendere sicuro il cookie CSRF quando il cookie di sessione è sicuro ( SESSION_COOKIE_SECURE=True ), modificando django/middleware/csrf.py :

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)

Richieste HTTP dirette a HTTPS nel server web

Successivamente vuoi una regola di riscrittura che reindirizzi le richieste http a https, ad es. in nginx

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

La funzione reverse di Django e i tag modello url restituiscono solo collegamenti relativi; quindi se sei su una pagina https i tuoi link ti terranno sul sito https.

Imposta la variabile ambientale del sistema operativo HTTPS su

Infine, (e la mia risposta originale l'ha escluso), è necessario abilitare la variabile ambientale del sistema operativo HTTPS in 'on' , quindi django farà precedere https ai collegamenti generati completamente (ad esempio, come con HttpRedirectRequest s). Se stai utilizzando mod_wsgi, puoi aggiungere la riga:

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

al tuo script wsgi . Se stai utilizzando uwsgi, puoi aggiungere una variabile ambientale tramite l'interruttore della riga di comando --env HTTPS=on o aggiungendo la riga env = HTTPS=on al tuo file uwsgi .ini . Come ultima risorsa, se non funziona nient'altro, puoi modificare il tuo file delle impostazioni per avere le righe import os e os.environ['HTTPS'] = "on" , che dovrebbe funzionare anche.

Se stai usando wsgi, potresti voler impostare ulteriormente la variabile ambientale wsgi.url_scheme in 'https' aggiungendo questo al tuo settings.py :

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

Il consiglio wsgi per gentile concessione di commento di Vijayendra Bapte .

Puoi vedere la necessità di questa variabile ambientale leggendo django/http/__init__.py :

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"

Altre cose del server Web:

Prendi i consigli di quel ragazzo e attiva le intestazioni HSTS nel tuo server web aggiungendo una riga a nginx:

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

Questo indica al tuo browser web che il tuo sito web per i prossimi 10 anni utilizzerà solo HTTPS. Se c'è un attacco Man-in-the-middle su qualsiasi visita futura dallo stesso browser (ad esempio, si accede a un router malevolo in una caffetteria che reindirizza a una versione HTTP della pagina), il browser si ricorderà dovrebbe essere solo HTTPS e impedirti di rinunciare inavvertitamente alle tue informazioni. Ma fai attenzione a questo, non puoi cambiare idea e in seguito decidere che parte del tuo dominio verrà servita su HTTP (fino a quando sono trascorsi 10 anni dalla rimozione di questa riga). Quindi pianificare in anticipo; ad es., se ritieni che la tua applicazione possa presto diventare popolare e dovrai trovarti su un CDN di grandi dimensioni che non gestisce bene HTTPS a un prezzo che ti puoi permettere, potresti avere un problema.

Assicurati anche di disabilitare i protocolli deboli. Invia il tuo dominio a un Test SSL per verificare potenziali problemi (chiave troppo corta, non utilizzando TLSv1.2, utilizzando protocolli non funzionanti, eccetera.). Ad esempio, in nginx io uso:

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";
    
risposta data 17.03.2017 - 14:14
fonte
3

Il reindirizzamento da qualsiasi http: // alla pagina https: // corrispondente è l'approccio sbagliato. Configura nginx per reindirizzare la porta 80 su link

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

o simile (controlla il prossimo manuale di nginx vicino a te) e non eseguire la tua applicazione sulla porta 80 (http). Quindi, altre richieste sulla porta 80 si risolvono in un 404 o simile (personalizzalo, dicendo che la tua app ora è sicura e funziona solo su https con un link che punta a link ). Quindi esegui la tua app solo sulla porta di ascolto 443 (https). L'utilizzo di percorsi relativi nel codice è ora sicuro, poiché tutti si risolvono nel percorso completo https: // e si evita il rimbalzo da http a https!

    
risposta data 17.11.2011 - 00:19
fonte
3

Una configurazione comune ti farà inoltrare il traffico https dal tuo server web (ad esempio Nginx) a un server http locale che esegue l'app Django.

In questo caso sarà più facile usare l'impostazione SECURE_PROXY_SSL_HEADER (disponibile da Django 1.4.)

link

    
risposta data 09.07.2012 - 23:43
fonte
3

dovresti inoltre inviare una HSTS-Header da nginx, che indica ai client (browser) che devono utilizzare solo HTTPS

add_header Strict-Transport-Security max-age=31536000;
    
risposta data 14.07.2013 - 18:08
fonte
2

Penso che quello che stai cercando sia un middleware Django che riscrive http in https . Qualcosa di simile a ciò che viene affrontato in questa domanda su SO , dove un punto di risposta a questo middleware . Probabilmente dovrai scrivere il tuo middleware, ma dovrebbe essere semplice. (Una domanda ben focalizzata su SO ti porterà nella giusta direzione se hai bisogno di aiuto per iniziare.)

    
risposta data 17.11.2011 - 16:08
fonte
2

Nella maggior parte dei casi puoi impostare Apache o qualcosa da reindirizzare a https, come descritto nella risposta accettata. E se puoi, sarebbe meglio, per le prestazioni e per i file serviti al di fuori di Django.

Ma se non puoi, o vuoi fare il debugging, vorrei sottolineare che Django di recente (1.8) ha introdotto un SecurityMiddleware che ha https-redirect come una delle sue numerose funzioni.

Ulteriori informazioni sono disponibili in la documentazione . In sostanza, aggiungi django.middleware.security.SecurityMiddleware e imposta SECURE_SSL_REDIRECT = True .

(L'intestazione menzionata dalla risposta accettata può anche essere impostata da questo middleware.)

    
risposta data 14.06.2015 - 14:22
fonte
1

Devi configurare django per generare o

  1. https://domain/path link con lo schema https: ,
  2. //domain/path link senza schema (il browser interpreterà questi come aventi lo stesso schema della pagina in cui è attualmente aperto), o
  3. /path link senza schema o dominio (il browser interpreterà questi come aventi lo stesso schema e dominio della pagina a cui è attualmente indirizzata).
risposta data 18.11.2011 - 03:07
fonte

Leggi altre domande sui tag