it-swarm-tr.com

Django tabanlı bir sitenin yalnızca HTTPS kullanmasını sağlamaya çalışıyorsunuz, güvenli olup olmadığından emin değil misiniz?

EFF sitenizde her yerde HTTPS kullanarak önerir ve bu sitenin kabul edeceğinden eminim. Giriş sayfamda HTTPS uygulamak için Django kullanma hakkında bir soru sorduğumda, bu kesinlikle aldığım yanıt :)

Ben de bunu yapmaya çalışıyorum. Ben sadece HTTPS için yapılandırmaya çalışıyorum bir Django/nginx kurulum var - bu tür bir çalışma, ama sorun var. Daha da önemlisi, https önekini görmesine rağmen gerçekten güvenli olup olmadığından eminim.

Tüm http sayfalarını https'ye yönlendirmek için nginx'i yapılandırdım ve bu bölüm çalışıyor. Ancak ... https://mysite.com/search/ Sayfamın üzerinde arama formunun/düğmesinin bulunduğu bir sayfam olduğunu varsayalım. Düğmeyi tıklıyorum, Django formu işler ve results sayfasına yönlendirir, bu da http://mysite.com/search/results?term="foo".

Bu URL, tarayıcıya gönderilir; bu, sayfanın https - önekli sürümüne kalıcı bir yönlendirme yapan nginx sunucusuna geri gönderir. (En azından ben düşün olan şey bu - kesinlikle IE güvensiz bir sayfaya gideceğim konusunda beni uyarıyor ve sonra tekrar güvenli bir sayfaya geri dönüyorum :)

Ama bu gerçekten güvenli mi? Ya da, en azından standart bir HTTPS sitesinin güvenliği kadar mı? Django bir http-önek URL'si, güvenliği tehlikeye atan biri iletiyor mu?) Evet, anlayabildiğim kadarıyla, sadece https-öneki olan sayfalar yanıtlanıyor, ancak 't feel doğru :) Bu site kanıtlayabileceği için güvenlik korkak ve eksik olduğum bir şey olduğundan endişeleniyorum.

63
John C

Çerezlerinizi koruyun

settings.py satırlarını koy

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

ve çerezler yalnızca HTTPS bağlantıları aracılığıyla gönderilir. Ayrıca, muhtemelen SESSION_EXPIRE_AT_BROWSER_CLOSE=True Django 'un eski sürümlerini (1.4'ten az) kullanıyorsanız, güvenli CSRF çerezleri için bir ayar bulunmadığını unutmayın. Hızlı bir düzeltme olarak, oturum çerezi güvenli olduğunda (SESSION_COOKIE_SECURE=True), CSRF çerezinin Django/middleware/csrf.py 'İ düzenleyerek güvenli olmasını sağlayabilirsiniz:

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)

HTTP isteklerini web sunucusunda HTTPS'ye yönlendirin

Daha sonra http isteklerini https'ye, örneğin nginx'e yönlendiren bir yeniden yazma kuralı istiyorsunuz

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

Django'nun reverse işlevi ve URL şablonu etiketleri yalnızca göreli bağlantılar döndürür; https sayfasındaysanız, bağlantılarınız sizi https sitesinde tutacaktır.

İşletim sistemi ortam değişkeni HTTPS'yi açık olarak ayarla

Son olarak, (ve orijinal yanıtım bunu hariç tuttu), HTTPS ila 'on' İşletim sistemi ortam değişkenini etkinleştirmeniz gerekir, böylece Django https'yi tam olarak oluşturulan bağlantılara önceliklendirir (ör. HttpRedirectRequests). Mod_wsgi kullanıyorsanız, satırı ekleyebilirsiniz:

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

wsgi betiğiniz . Uwsgi kullanıyorsanız, --env HTTPS=on Komut satırı anahtarıyla veya uwsgi env = HTTPS=on Dosyanıza .ini Satırını ekleyerek çevresel bir değişken ekleyebilirsiniz. Başka bir şey işe yaramazsa son çare olarak, ayar dosyanızı import os Ve os.environ['HTTPS'] = "on" Satırlarına sahip olacak şekilde düzenleyebilirsiniz.

Wsgi kullanıyorsanız, bunu wsgi.url_scheme Öğenize ekleyerek çevre değişkenini 'https' Olarak settings.py Olarak ayarlamak isteyebilirsiniz:

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

Wsgi tavsiyesi nezaket Vijayendra Bapte'nin yorum .

Django/http/__init__.py Bölümünü okuyarak bu çevresel değişkene olan ihtiyacı görebilirsiniz:

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"

Ek Web Sunucusu Özellikleri:

o adamın tavsiyesi al ve nginx'e bir satır ekleyerek web sunucunuzdaki HSTS başlıklarını açın:

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

Bu, web tarayıcınıza önümüzdeki 10 yıl boyunca web sitenizin yalnızca HTTPS kullanacağını bildirir. Aynı tarayıcıdan gelecekteki herhangi bir ziyarette ortadaki Adam saldırısı varsa (örneğin, bir kafede sizi sayfanın HTTP sürümüne yönlendiren kötü amaçlı bir yönlendiriciye oturum açarsanız), tarayıcınız hatırlar yalnızca HTTPS olması ve yanlışlıkla bilgi vermenizi engellemesi gerekir. Ancak bu konuda dikkatli olun, fikrinizi değiştiremezsiniz ve daha sonra alan adınızın bir kısmının HTTP üzerinden sunulacağına karar verebilirsiniz (bu satırı kaldırdığınızda 10 yıl geçene kadar). Öyleyse önceden plan yapın; Örneğin, uygulamanızın popülaritesinin yakında büyüyebileceğini düşünüyorsanız ve HTTPS'yi karşılayabileceğiniz bir fiyata iyi işlemeyen büyük bir CDN'de olmanız gerekiyorsa, bir sorununuz olabilir.

Ayrıca zayıf protokolleri devre dışı bıraktığınızdan emin olun. Potansiyel sorunları kontrol etmek için alan adınızı SSL Testi adresine gönderin (çok kısa anahtar, TLSv1.2 kullanmamak, bozuk protokoller kullanmak vb.). Örneğin, nginx'te şunu kullanıyorum:

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

Herhangi bir http: // ifadesinden ilgili https: // sayfasına yönlendirmek yanlış yaklaşımdır. Nginx'i 80 numaralı bağlantı noktasını https: //alanadiniz.ext/ adresine yönlendirecek şekilde yapılandırın

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

veya benzeri (yakınınızdaki bir sonraki nginx kılavuzuna bakın) ve başvurunuzu 80 numaralı bağlantı noktasında (http) hiç çalıştırmayın. Bu nedenle, 80 numaralı bağlantı noktasındaki diğer istekler 404 veya benzeri bir duruma çözümlenir (özelleştirin, uygulamanızın artık güvenli olduğunu ve yalnızca https'de çalıştığını söyleyerek https: //alanadiniz.ext adresine yönlendirin)/ ). Ardından uygulamanızı yalnızca dinleme bağlantı noktası 443'te (https) çalıştırın. Kodunuzda göreli yolları kullanmak artık güvenlidir, çünkü hepsi tam https: // yoluna çözümlenir ve http'den https'ye sıçramasını önlersiniz!

3
esskar

ayrıca nginx'ten istemcilere (tarayıcılar) yalnızca HTTPS kullanacaklarını belirten bir HSTS-Header göndermelisiniz

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

Yaygın bir kurulum, https trafiğini web sunucunuzdan (yani Nginx) Django uygulamasını çalıştıran yerel bir http sunucusuna yönlendirmenizi sağlar).

Bu durumda SECURE_PROXY_SSL_HEADER ayarı (Django 1.4.) tarihinden beri kullanılabilir

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

3
Sebastian

Aradığın, http'i https olarak yeniden yazacak bir Django ara katman yazılımı olduğunu düşünüyorum. Burada ele alınana benzer bir şey SO ile ilgili bu sor , burada bir cevap bu ara katman yazılımı anlamına gelir. Muhtemelen kendi ara katman yazılımınızı yazmanız gerekecek, ancak basit olmalıdır. (SO ile ilgili iyi odaklanmış bir soru, başlamak için yardıma ihtiyacınız olursa sizi doğru yöne yönlendirecektir.)

2
bstpierre

Çoğu durumda, kabul edilen yanıtta açıklandığı gibi Apache'yi veya başka bir şeyi https'ye yönlendirilecek şekilde ayarlayabilirsiniz. Ve eğer yapabiliyorsanız, performans ve Django dışında sunulan dosyalar için bu daha iyi olurdu.

Ancak hata ayıklama yapamıyorsanız veya hata ayıklamak istiyorsanız, Django son zamanlarda (1.8) https-yönlendirmelerinden biri olan bir SecurityMiddleware getirdiğini belirtmek isterim. çeşitli işlevler.

Daha fazla bilgiye belgeler adresinden ulaşılabilir. Temel olarak Django.middleware.security.SecurityMiddleware Ekleyin ve SECURE_SSL_REDIRECT = True Ayarlayın.

(Kabul edilen cevapta belirtilen başlık bu ara katman yazılımı tarafından da ayarlanabilir.)

2
Mark

Django

  1. https://domain/pathhttps: şeması,
  2. //domain/path düzeni olmayan bağlantılar (tarayıcı bunları şu anda açıldığı sayfayla aynı şemaya sahip olarak yorumlayacaktır) veya
  3. /path düzeni veya alanı olmayan bağlantılar (tarayıcı, bunları şu anda işaret ettiği sayfa ile aynı şemaya ve alana sahip olarak yorumlayacaktır).
1
yfeldblum