Django的SuspiciousOperation无效的HTTP_HOST标头


96

升级到Django 1.5后,我开始出现如下错误:

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文件中进行了设置。

这里发生了什么?有人假装成为Google并访问我的网站吗?还是有人错误地设置其HTTP_HOST标头的良性案例?


您是否知道如何解决此问题?面对同样的问题。每天记录大约一百个此类错误。不知道这是否是我需要担心的。
2013年

3
:本博客文章提供了一个很好的方法来阻止电子邮件tiwoc.de/blog/2013/03/...
郭子健

Answers:


64

如果您ALLOWED_HOSTS的设置正确,则可能有人通过欺骗标头来探测您的站点是否存在漏洞。

Django开发人员正在讨论将其从500内部服务器错误更改为400响应。看这张票


1
我认为更可能的解释是Web爬网程序(机器人)仅在端口80上爬网公共IP地址-在这种情况下,您将希望允许它们。
markmnl 2014年

16
@markmnl合法的Web爬网程序不应伪造主机头。
布莱恩·尼尔

1
它只是使用IP地址而不是域名进行连接,并且IP地址不在ALLOWED_HOSTS中-至少这就是我所发生的事情-我可以通过将浏览器指向IP地址来对其进行复制。
markmnl 2014年

是的 在任何繁忙的站点中,这种情况每天都会发生。他们已经修复了它,但是这里有一个“插入式”应用程序,可以在所有版本中对它进行分类,并附带错误率过滤器。github.com/litchfield/django-safelogging
s29 2014年

在互联网上部署我的网站之后。我发现许多人试图使用无效的主机访问我的网站。不仅使用IP地址。我认为这可能是某些人试图找到无法防御csrf攻击的网站。
ramwin '18

130

如果您使用Nginx将请求转发到在Gunicorn / Apache / uWSGI上运行的Django,则可以使用以下命令阻止错误的请求。感谢@PaulM的建议以及本博客示例。

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
非常高兴看到这是对文档提示提示的一种改进:)
Paul McMillan

1
@webjunkie,在您的链接中,“在某些情况下,您根本无法避免使用if,例如,如果您需要测试没有等效指令的变量”。我的示例正确使用了它,并且在我的生产环境中运行良好。因此,总而言之,请这样做!:)
Brent O'Connor

2
好了,您可以轻松避免它:仅指定所需的server_name,然后让其余的由默认服务器处理程序处理。
webjunkie 2013年

1
请参阅以下答案以获取类似的Apache配置:stackoverflow.com/a/18792080
DenilsonSáMaia 2014年

1
来自webjunkie提供的链接:“在位置上下文中使用时如果出现问题则为伪指令”。布伦特给出的示例使用if内部server块而不是内部location块。这是否表示if在这种情况下还可以?
布莱恩·巴克

31

使用Nginx时,您可以以一种仅首先向您想要到达Django的主机的请求的方式来设置服务器。那应该不会再给您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
}

2
我喜欢这种方法,而不是使用ifBrent建议的方法,但是我无法使其与端口443一起使用。我尝试模仿您的建议(更改了侦听端口),但是我的实际SSL站点无法加载-被我添加的此项捕获。有关如何解决的任何想法?
Dolan Antenucci 2014年

1
ServerFault.com上的另一位发帖人也遇到了类似的问题,因此我遵循了他对仅针对443流量的if声明方法的建议
Dolan Antenucci 2014年

1
似乎如果您也想捕获SSL请求,就必须指定证书文件的路径(即使您只是想丢弃): 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 2014年

如果请求的主机无效,Nginx将返回什么?50倍还是40倍?
laike9m 2015年

在此配置中还有什么?我在重定向和“应用程序”部分中都设置了服务器名称,我仍然得到Invalid HTTP_HOST header(使用Django 1.8.x)
Csaba Toth

16

这在较新的Django版本中已修复,但是,如果您使用的是受影响的版本(例如1.5),则可以在记录器处理程序中添加过滤器以摆脱这些影响,如博文所述。

扰流板:

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
实施此修补程序或版本的任何链接?Thx
Marc

1
我在版本2.0.5上安装了它
穆罕默德(Mehmet)'18年

在较新版本的Django上未解决此问题。我正在使用Django 2.0.10
javidazac,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.