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 헤더를 잘못 설정하는 것은 무해한 경우입니까?


이 문제를 해결하는 방법을 알아 냈습니까? 같은 문제에 직면하고 있습니다. 매일 수백 개의 이러한 오류를 기록합니다. 내가 걱정해야 할 일인지 모르겠다.
blinduck 2013 년

3
이 블로그 게시물은 이메일을 중지하는 좋은 방법을 제공합니다. tiwoc.de/blog/2013/03/…
Derek Kwok

답변:


64

귀하 ALLOWED_HOSTS가 올바르게 설정 되었다면 누군가 헤더를 스푸핑하여 귀하의 사이트에서 취약점을 조사하고있을 수 있습니다.

현재 Django 개발자가 이것을 500 내부 서버 오류에서 400 응답으로 변경하는 논의가 있습니다. 이 티켓을 참조하십시오 .


1
더 가능성이 높은 설명은 웹 크롤러 (로봇)가 단순히 포트 80에서 공용 IP 주소를 크롤링하는 것입니다.이 경우 허용하고 싶을 것입니다.
markmnl

16
@markmnl 합법적 인 웹 크롤러는 호스트 헤더를 위조해서는 안됩니다.
Brian Neal

1
도메인 이름이 아닌 IP 주소를 사용하여 연결하고 IP 주소가 ALLOWED_HOSTS에 없거나 적어도 저에게 일어난 일입니다. 브라우저를 IP 주소로 지정하여 재현 할 수 있습니다.
markmnl

네. 그리고 반 바쁜 사이트에서 이것은 매일 하루 종일 발생합니다. 그들은 지금 그것을 고쳤지만 여기에 오류율 필터와 함께 모든 버전에서 그것을 분류하는 "드롭 인"앱이 있습니다. github.com/litchfield/django-safelogging
s29

내 웹 사이트를 인터넷에 배포 한 후. 많은 사람들이 유효하지 않은 호스트를 사용하여 내 웹 사이트에 액세스하려고합니다. IP 주소 만 사용하는 것이 아닙니다. 나는 이것이 어떤 사람들이 csrf 공격을 방어 할 수없는 웹 사이트를 찾으려고하는 것일 수 있다고 생각합니다.
ramwin

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
문서에 대한 개선으로 이것을 볼만한 것 힌트 힌트 :
폴 맥밀런

1
@webjunkie, 링크에서 "예를 들어 동등한 지시문이없는 변수를 테스트해야하는 경우와 같이 단순히 if 사용을 피할 수없는 경우가 있습니다." 내 예에서는 올바르게 사용하고 프로덕션 환경에서 잘 작동합니다. 결론적으로 이렇게하세요! :)
Brent O'Connor

2
쉽게 피할 수 있습니다. 필요한 server_name 만 지정하고 나머지는 기본 서버 핸들러가 처리하도록합니다.
webjunkie

1
: 유사한 아파치 구성이 답변을 참조하십시오 stackoverflow.com/a/18792080
데닐손 Sá 마이 아

1
webjunkie에서 제공하는 링크에서 : "위치 컨텍스트에서 사용할 때 문제가있는 경우 지시 사항". Brent가 제시 한 예제 ifserver블록이 아닌 블록 내부를 사용합니다 location. if이 경우에는 괜찮다는 의미 입니까?
brian buck

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 트래픽만을위한 경우 문 접근 방식에 대한 자신의 추천 다음, 그래서 비슷한 문제가 있었다
고언 Antenucci

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에 그것을 가지고 있었다
mehmet

최신 버전의 Django에서는 수정되지 않았습니다. 내가 장고 2.0.10 사용하고 있습니다
javidazac
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.