Django’s SuspiciousOperation Intestazione HTTP_HOST non valida

Dopo l’aggiornamento a Django 1.5, ho iniziato a ricevere errori come questo:

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:, POST:, 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': , 'wsgi.file_wrapper': , 'wsgi.input': , 'wsgi.multiprocess': True, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0)}> 

Ho impostato ALLOWED_HOSTS = ['.derekkwok.net'] nel mio file settings.py.

Che cosa sta succedendo qui? Qualcuno che finge di essere Google e che accede al mio sito? O è un caso benigno in cui qualcuno imposta erroneamente la propria intestazione HTTP_HOST?

Se il tuo ALLOWED_HOSTS è impostato correttamente, allora è ansible che qualcuno stia sondando il tuo sito per la vulnerabilità falsificando l’intestazione.

Al momento gli sviluppatori di Django stanno discutendo di questo cambiamento da un errore del server interno 500 a una risposta 400. Vedi questo biglietto .

Se stai utilizzando Nginx per inoltrare richieste a Django in esecuzione su Gunicorn / Apache / uWSGI, puoi utilizzare quanto segue per bloccare le richieste non valide. Grazie a @PaulM per il suggerimento e questo post sul blog per un esempio.

 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; ... } } 

Quando usi Nginx puoi configurare i tuoi server in un certo modo solo le richieste agli host che vuoi raggiungere a Django, in primo luogo. Questo non dovrebbe più causare errori di SuspiciousOperation.

 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 } 

Questo problema è stato risolto nelle versioni più recenti di Django, ma se si utilizza una versione interessata (ad esempio 1.5) è ansible aggiungere un filtro al gestore del registratore per sbarazzarsi di questi, come descritto in questo post del blog.

spoiler:

 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, }, } }