it-swarm-eu.dev

Při pokusu o to, aby web založený na Djangu používal pouze HTTPS, nejste si jisti, zda je zabezpečený?

EFF doporučuje používat HTTPS všude na vašem webu, a jsem si jistý, že tento web by souhlasil. Když jsem se zeptal, jak používat Django k implementaci HTTPS na mé přihlašovací stránce), určitě to bylo odpověď jsem dostal :)

Takže se to snažím udělat. Mám nastavení Django/nginx, které se snažím konfigurovat pouze pro HTTPS - je to trochu funkční, ale existují problémy. Ještě důležitější je, že jsem si jistý, zda je to opravdu zabezpečeno, přestože vidím předponu https.

Nakonfiguroval jsem nginx, aby přesměroval všechny http stránky na https, a tato část funguje. Nicméně ... Řekněme, že mám stránku, https://mysite.com/search/, s vyhledávacím formulářem/tlačítkem na něm. Kliknu na tlačítko, Django zpracovává formulář a přesměruje na stránku výsledky, což je http://mysite.com/search/results?term="foo".

Tato adresa URL bude odeslána do prohlížeče, který ji odešle zpět ​​na server nginx, který provede trvalé přesměrování na https- prefixovanou verzi stránky. (Alespoň já myslím to se děje - určitě IE mě varuje, že jdu na nezabezpečenou stránku, a pak hned zpátky na zabezpečenou stránku :)

Ale je to opravd bezpečné? Nebo přinejmenším tolik zabezpečení, jaké by měl standardní server HTTPS? Je skutečnost, že Django přenáší adresu URL s předponou http, někdo ohrožuje zabezpečení? Ano, pokud mohu říci, odpoví na to pouze stránky, které mají předponu https-prefix, ale prostě ne. 't feel right :) Zabezpečení je funky, protože tento web může dosvědčit, a obávám se, že mi něco chybí.

63
John C

Zabezpečte své cookies

Do settings.py vložte řádky

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

a soubory cookie budou zasílány pouze prostřednictvím připojení HTTPS. Navíc pravděpodobně budete také chtít SESSION_EXPIRE_AT_BROWSER_CLOSE=True. Upozorňujeme, že pokud používáte starší verze Django (méně než 1,4)), neexistuje žádné nastavení pro zabezpečené cookies CSRF. Jako rychlá oprava stačí mít zabezpečený cookie CSRF, když cookie relace je zabezpečené (SESSION_COOKIE_SECURE=True), úpravou 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)

Přímé požadavky HTTP na HTTPS ve webovém serveru

Dále chcete přepisovací pravidlo, které přesměruje http požadavky na https, např. V nginx

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

Funkce reverse funkce Django a značky šablon adresy URL vrací pouze relativní odkazy; takže pokud jste na stránce https, vaše odkazy vás budou udržovat na webu https.

Nastavte proměnnou prostředí HTTPS OS na zapnuto

Nakonec (a moje původní odpověď toto vyloučila) musíte povolit proměnnou prostředí OS HTTPS to 'on' so Django připraví https na plně vygenerované odkazy (např. jako u HttpRedirectRequests). Pokud používáte mod_wsgi, můžete přidat řádek:

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

k vašemu wsgi skript . Pokud používáte uwsgi, můžete přidat proměnnou prostředí pomocí přepínače příkazového řádku --env HTTPS=on nebo přidáním řádku env = HTTPS=on k vašemu uwsgi .ini soubor. Jako poslední možnost, pokud nic jiného nefunguje, můžete upravit svůj soubor nastavení tak, aby obsahoval řádky import os a os.environ['HTTPS'] = "on", které by také mělo fungovat.

Pokud používáte wsgi, možná budete chtít dodatečně nastavit proměnnou prostředí wsgi.url_scheme to 'https' přidáním tohoto do svého settings.py:

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

Poradce wsgi s laskavým svolením komentář Vijayendry Bapte .

Potřeba této proměnné prostředí můžete vidět čtením 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"

Další věci webového serveru:

Vezměte rada toho chlapa a zapněte záhlaví HSTS na webovém serveru přidáním řádku do nginx:

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

Váš webový prohlížeč to řekne, že váš web bude následujících 10 let používat pouze protokol HTTPS. Pokud při jakékoli budoucí návštěvě ze stejného prohlížeče dojde k útoku typu Man-in-the-middle (např. Přihlásíte se k škodlivému routeru v kavárně, který vás přesměruje na HTTP verzi stránky), váš prohlížeč si pamatuje má to být pouze protokol HTTPS a brání vám nechtěnému vzdání se vašich informací. Ale pozor na to, nemůžete změnit názor a později se rozhodněte, že část vaší domény bude doručena prostřednictvím protokolu HTTP (dokud neuplyne 10 let od odstranění tohoto řádku). Takže plánujte dopředu; např. pokud si myslíte, že vaše aplikace může brzy vzrůst v popularitě a budete muset být na velkém CDN, který HTTPS nezvládá dobře za cenu, kterou si můžete dovolit, může se jednat o problém.

Nezapomeňte také zakázat slabé protokoly. Odešlete svou doménu do SSL Test , abyste zkontrolovali možné problémy (příliš krátký klíč, nepoužíváte TLSv1.2, používající rozbité protokoly atd.). Například v nginxu používám:

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

Přesměrování z libovolného http: // na odpovídající stránku https: // je nesprávný přístup. Nakonfigurujte nginx tak, aby přesměroval port 80 na https: //yourdomain.ext/

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

nebo podobné (podívejte se na příští příručku nginx ve vašem okolí) a nespouštějte svou aplikaci vůbec na portu 80 (http). Ostatní požadavky na portu 80 se tedy upravují na 404 nebo podobné (přizpůsobte je a řekněte, že vaše aplikace je nyní zabezpečená a běží pouze na https s odkazem směřujícím na https: //yourdomain.ext/ ) . Poté spusťte aplikaci pouze na portu 443 pro poslech (https). Použití relativních cest ve vašem kódu je nyní bezpečné, protože všechny se rozcházejí na úplnou cestu https: // a vyhnete se http na https skákací!

3
esskar

měli byste navíc poslat HSTS-Header z nginx, což naznačuje klientům (prohlížečům), že budou používat pouze HTTPS

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

Při běžném nastavení budete předávat provoz https z vašeho webového serveru (tj. Nginx) na místní http server, na kterém je spuštěna aplikace Django).

V tomto případě bude snazší použít SECURE_PROXY_SSL_HEADER nastavení (k dispozici od Django 1.4.)

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

3
Sebastian

Myslím, že to, co hledáte, je Django middleware, který přepíše http na https. Něco podobného tomu, co je adresováno toto otázka na SO , kde jedna odpověď ukazuje na tento middleware . Pravděpodobně budete muset napsat svůj vlastní middleware, ale mělo by to být jednoduché. (Dobře zaměřená otázka na SO vás nasměruje správným směrem, pokud potřebujete pomoci s tím, jak začít.)

2
bstpierre

Ve většině případů můžete nastavit Apache nebo něco tak, aby přesměrovávalo na https, jak je popsáno v přijaté odpovědi. A pokud je to možné, bylo by to lepší pro výkon a pro soubory doručované mimo Django.

Ale pokud nemůžete, nebo chcete provést ladění, pak bych rád poukázal na to, že Django nedávno (1.8)) zavedl SecurityMiddleware, který má https-přesměrování jako jedno z jeho několik funkcí.

Více informací je k dispozici v dokumentace . V podstatě přidejte Django.middleware.security.SecurityMiddleware a nastavte SECURE_SSL_REDIRECT = True.

(Záhlaví zmíněná v přijaté odpovědi lze také nastavit pomocí tohoto middlewaru.)

2
Mark

Abyste mohli generovat, musíte nakonfigurovat Django)

  1. https://domain/path odkazy na https: schéma,
  2. //domain/path odkazy bez schématu (prohlížeč je interpretuje tak, že má stejné schéma jako stránka, na kterou je aktuálně otevřen), nebo
  3. /path odkazy bez schématu nebo domény (prohlížeč je interpretuje tak, že mají stejné schéma a doménu jako stránka, na kterou je aktuálně označen).
1
yfeldblum