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가 제시 한 예제 if는 server블록이 아닌 블록 내부를 사용합니다 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.