DjangoのSuspiciousOperation無効なHTTP_HOSTヘッダー


95

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ヘッダーを誤って設定しているという無害なケースですか?


これを修正する方法を理解しましたか?同じ問題に直面しています。これらのエラーを毎日約100件記録しています。それが私が心配する必要がある何かであるかどうかわからない。
Blinduck

3
このブログ投稿は、電子メールを停止する良い方法を提供します:tiwoc.de/blog/2013/03/…–
Derek Kwok

回答:


64

ALLOWED_HOSTSが正しく設定されている場合は、誰かがヘッダーを偽装してサイトの脆弱性を調査している可能性があります。

現在、Django開発者は、これを500内部サーバーエラーから400応答に変更するための議論を行っています。こちらのチケットをご覧ください。


1
より可能性の高い説明は、ポート80でパブリックIPアドレスを単にクロールするWebクローラー(ロボット)であると思います。この場合、許可する必要があります。
markmnl 2014年

16
@markmnl正規のWebクローラーがホストヘッダーを偽造してはなりません。
ブライアンニール2014年

1
ドメイン名ではなくIPアドレスを使用して接続しているだけで、IPアドレスがALLOWED_HOSTSに含まれていない-または少なくともそれが私に起こっていた-ブラウザでIPアドレスを指定することで再現できます。
markmnl 2014年

うん。そして、半分忙しいサイトでは、これは毎日一日中起こります。彼らは現在それを修正しましたが、これはエラー率フィルターと共にすべてのバージョンでそれを分類する「ドロップイン」アプリです。github.com/litchfield/django-safelogging
s29

私のウェブサイトをインターネットに展開した後。多くの人が無効なホストを使用して私のウェブサイトにアクセスしようとしているのを発見しました。IPアドレスを使用するだけではありません。これは、csrf攻撃を防御できないWebサイトを見つけようとしている人もいると思います。
ramwin 2018年

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の使用を避けられない場合があります。」私の例ではそれを正しく使用しており、実稼働環境でうまく機能します。結論として、このようにしてください!:)
ブレント・オコナー

2
簡単に回避できます。必要なserver_nameだけを指定し、残りはデフォルトのサーバーハンドラーで処理します。
webjunkie 2013年

1
同様のApacheの設定のためにこの回答を参照してください。stackoverflow.com/a/18792080
デニウソンSáマイア

1
webjunkieによって提供されたリンクから:「場所のコンテキストで使用したときにディレクティブに問題がある場合」。ブレントの例でifは、serverブロック内ではなくブロック内を使用していlocationます。ifこれは、このインスタンスで問題がないことを意味しますか?
ブライアンバック2015

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
ifブレントが提案したアプローチを使用するよりもこのアプローチが好きですが、ポート443で動作させることができません。提案を模倣して(リスンポートを変更して)、実際のSSLサイトが読み込まれません-それは私が追加したこのエントリによってキャプチャされます。修正方法に関するアイデアはありますか?
Dolan Antenucci 2014年

1
ServerFault.comの別のポスターにも同様の問題があったため、443トラフィックのみのifステートメントアプローチに関する彼の推奨事項に従いました
Dolan Antenucci '16

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

リクエストのHOSTが無効な場合、Nginxは何を返しますか?50xまたは40x?
laike9m

この構成の追加は何ですか?リダイレクトとアプリセクションの両方でサーバー名を設定しましたが、まだ取得しています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で持っていました
メフメット2018年

これは、Djangoの新しいバージョンでは修正されていません。私はDjango 2.0.10を使用しています
javidazac
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.