Django'nun SuspiciousOperation Invalid HTTP_HOST başlığı


96

Django 1.5'e yükselttikten sonra aşağıdaki gibi hatalar almaya başladım:

Traceback (most recent call last):

File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 92, in get_response
response = middleware_method(request)

File "/usr/local/lib/python2.7/dist-packages/django/middleware/common.py", line 57, in process_request
host = request.get_host()

File "/usr/local/lib/python2.7/dist-packages/django/http/request.py", line 72, in get_host
"Invalid HTTP_HOST header (you may need to set ALLOWED_HOSTS): %s" % host)

SuspiciousOperation: Invalid HTTP_HOST header (you may need to set ALLOWED_HOSTS): www.google.com

<WSGIRequest
path:/,
GET:<QueryDict: {}>,
POST:<QueryDict: {}>,
COOKIES:{},
META:{'CONTENT_LENGTH': '',
'CONTENT_TYPE': '',
'DOCUMENT_ROOT': '/etc/nginx/html',
'HTTP_ACCEPT': 'text/html',
'HTTP_HOST': 'www.google.com',
'HTTP_PROXY_CONNECTION': 'close',
'HTTP_USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'PATH_INFO': u'/',
'QUERY_STRING': '',
'REMOTE_ADDR': '210.245.91.104',
'REMOTE_PORT': '49347',
'REQUEST_METHOD': 'GET',
'REQUEST_URI': '/',
u'SCRIPT_NAME': u'',
'SERVER_NAME': 'www.derekkwok.net',
'SERVER_PORT': '80',
'SERVER_PROTOCOL': 'HTTP/1.0',
'uwsgi.node': 'derekkwok',
'uwsgi.version': '1.4.4',
'wsgi.errors': <open file 'wsgi_errors', mode 'w' at 0xb6d99c28>,
'wsgi.file_wrapper': <built-in function uwsgi_sendfile>,
'wsgi.input': <uwsgi._Input object at 0x953e698>,
'wsgi.multiprocess': True,
'wsgi.multithread': False,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)}>

ALLOWED_HOSTS = ['.derekkwok.net'] Settings.py dosyamda ayarladım .

Burada neler oluyor? Google gibi davranan ve siteme erişen biri mi? Yoksa birisinin HTTP_HOST üstbilgisini yanlış ayarlaması zararsız bir durum mu?


Bunu nasıl düzelteceğinizi buldunuz mu? Aynı problemle karşı karşıya. Her gün bu hatalardan yaklaşık yüz tanesi günlüğe kaydediliyor. Endişelenmem gereken bir şey olup olmadığı hakkında hiçbir fikrim yok.
körük

3
Bu blog yazısı, e-postaları durdurmanın güzel bir yolunu sunuyor: tiwoc.de/blog/2013/03/…
Derek Kwok

Yanıtlar:


64

Eğer ALLOWED_HOSTSdoğru bir şekilde ayarlanmışsa, o zaman birisi başlıkta sahtecilik yaparak sitenizi güvenlik açığı için araştırıyor olabilir.

Şu anda Django geliştiricileri, bunu 500 dahili sunucu hatasından 400 yanıtına çevirmek için tartışıyor. Bu bileti görün .


1
Bence daha olası bir açıklama, web tarayıcılarının (robotlar) yalnızca 80 numaralı bağlantı noktasındaki genel IP adreslerini taramasıdır - bu durumda onlara izin vermek istersiniz.
markmnl

16
@markmnl Meşru bir web tarayıcısı, ana bilgisayar başlıklarını taklit etmemelidir.
Brian Neal

1
Sadece etki alanı adını değil IP adresini kullanarak bağlanıyor ve IP adresi ALLOWED_HOSTS'da değil - ya da en azından benim başıma gelen buydu - tarayıcımı IP adresine yönlendirerek yeniden üretebilirim.
markmnl

Evet. Ve yarı meşgul herhangi bir sitede, bu her gün tüm gün olur. Şimdi düzelttiler, ancak burada bir hata oranı filtresiyle birlikte tüm sürümlerde sıralayan bir "açılır" uygulama var. github.com/litchfield/django-safelogging
s29

Web sitemi internete yerleştirdikten sonra. Geçersiz ana bilgisayar kullanarak web siteme erişmeye çalışan birçok kişi buldum. Sadece IP adresini kullanmakla kalmaz. Sanırım bu, bir csrf saldırısını savunamayan bir web sitesi bulmaya çalışan bazı insanlar olabilir.
ramwin

132

Gunicorn / Apache / uWSGI üzerinde çalışan Django'ya istek iletmek için Nginx kullanıyorsanız, kötü istekleri engellemek için aşağıdakileri kullanabilirsiniz. Öneri için @ PaulM'a teşekkürler .

upstream app_server {
    server unix:/tmp/gunicorn_mydomain.com.sock fail_timeout=0;
}

server {

    ...

    ## Deny illegal Host headers
    if ($host !~* ^(mydomain.com|www.mydomain.com)$ ) {
        return 444;
    }

    location  / {
        proxy_pass               http://app_server;
        ...
    }

}

7
Bunu dokümanlar ipucu ipucunda bir gelişme olarak görmek harika olurdu :)
Paul McMillan

1
@webjunkie, Bağlantınızdan, "Bir if kullanmaktan kaçınamayacağınız durumlar vardır, örneğin eşdeğer yönergesi olmayan bir değişkeni test etmeniz gerekiyorsa." Örneğim onu ​​doğru kullanıyor ve üretim ortamımda iyi çalışıyor. Sonuç olarak, bunu böyle YAPIN! :)
Brent O'Connor

2
Bundan kolayca kaçınabilirsiniz: Yalnızca ihtiyacınız olan sunucu_adını belirtin ve geri kalanının varsayılan bir sunucu işleyicisi tarafından ele alınmasına izin verin.
webjunkie

1
Benzer bir Apache yapılandırması için bu yanıta bakın: stackoverflow.com/a/18792080
Denilson Sá Maia

1
Webjunkie tarafından sağlanan bağlantıdan: "Konum bağlamında kullanıldığında sorun varsa direktif". Brent tarafından verilen örnek if, serverblokta değil , bloğun içini kullanır location. ifBu, bu durumda sorun olmadığı anlamına mı geliyor ?
brian buck

31

Nginx'i kullanırken, sunucularınızı yalnızca ilk etapta Django'ya ulaşmak istediğiniz ana bilgisayarlara talep edecek şekilde ayarlayabilirsiniz. Bu size artık SuspiciousOperation hatası vermemelidir.

server {
    # default server

    listen 80;
    server_name _ default;

    return 444;
}
server {
    # redirects

    listen 80;
    server_name example.com old.stuff.example.com;

    return 301 http://www.example.com$request_uri;
}
server {
    # app

    listen 80;
    server_name www.example.com; # only hosts in ALLOWED_HOSTS here

    location  / {
        # ...
    }
    # ... your config/proxy stuff
}

2
Bu yaklaşımı ifBrent tarafından önerilen yaklaşımı kullanmaktan çok seviyorum , ancak 443 numaralı bağlantı noktasıyla çalışmasını sağlayamıyorum. Önerinizi taklit etmeye çalıştım (dinleme bağlantı noktası değişti) ve gerçek SSL sitem yüklenmiyor - bu eklediğim bu giriş tarafından yakalanır. Nasıl tamir edileceği konusunda fikri olan?
Dolan Antenucci

1
ServerFault.com'daki başka bir posterde benzer sorunlar vardı, bu yüzden onun önerisini yalnızca 443 trafik için if-ifadesi yaklaşımına uydum
Dolan Antenucci

1
SSL isteklerini de yakalamak istiyorsanız (sadece atmak istemenize rağmen) sertifika dosyalarının yolunu belirtmeniz gerekiyor gibi görünüyor: server { listen 80 default_server; listen 443; server_name _; ssl_certificate /path/to/file.crt; ssl_certificate_key /path/to/file.key; return 444; }
n__o

İsteğin HOST geçersizse Nginx ne döndürecektir? 50x mi 40x mi?
laike9m

Bu konfigürasyonda ekstra ne var? Hem yönlendirmelerde hem de uygulama bölümünde sunucu adını belirledim, hala alıyorum Invalid HTTP_HOST header(Django 1.8.x ile)
Csaba Toth

16

Bu, Django'nun daha yeni sürümlerinde düzeltilmiştir, ancak etkilenen bir sürümü kullanıyorsanız (örneğin 1.5), bu blog gönderisinde belirtildiği gibi, bunlardan kurtulmak için günlükçü işleyicinize bir filtre ekleyebilirsiniz .

Bir şeyin önceden reklamı:

from django.core.exceptions import SuspiciousOperation

def skip_suspicious_operations(record):
  if record.exc_info:
    exc_value = record.exc_info[1]
    if isinstance(exc_value, SuspiciousOperation):
      return False
  return True

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        # Define filter
        'skip_suspicious_operations': {
            '()': 'django.utils.log.CallbackFilter',
            'callback': skip_suspicious_operations,
        },
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            # Add filter to list of filters
            'filters': ['require_debug_false', 'skip_suspicious_operations'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}

1
Uygulanan düzeltme veya sürüm için herhangi bir bağlantı var mı? Thx
Marc

1
2.0.5 sürümündeydim
mehmet

Bu, Django'nun daha yeni sürümlerinde düzeltilmemiştir. Django 2.0.10 kullanıyorum
javidazac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.