5

I have a Django web site with medium traffic (about 4000/5000 visits per day). Today I configured the "LOGGING" option on settings.py to send an email with "Info" level, just check if everything was ok...

There was my surprise, I am getting the following error: [Django] WARNING (EXTERNAL IP): Forbidden (CSRF cookie not set.)

No stack trace available

<WSGIRequest
path:/cadastro/usuario/,
GET:<QueryDict: {}>,
POST:<QueryDict: {**xxxxxxx (some varibles....) and**: u'csrfmiddlewaretoken': [u'4wqRKQXZsTmXJaOkCsGobWyG1rzihc8x'], }>,
COOKIES:{},
META:{'CONTENT_LENGTH': '381',
 'CONTENT_TYPE': 'application/x-www-form-urlencoded',
 'CSRF_COOKIE': 'qzc4i7JdHoQLJ8N5aI9MTlamOZMOKmP0',
 'DOCUMENT_ROOT': '/opt/nginx/html',
 'HTTP_ACCEPT': 'text/html, application/xhtml+xml, */*',
 'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
 'HTTP_ACCEPT_LANGUAGE': 'pt-BR',
 'HTTP_CACHE_CONTROL': 'no-cache',
 'HTTP_CONNECTION': 'Keep-Alive',
 'HTTP_CONTENT_LENGTH': '381',
 'HTTP_CONTENT_TYPE': 'application/x-www-form-urlencoded',
 'HTTP_HOST': 'xxxxxx',
 'HTTP_REFERER': 'http://xxxx/y/z',
 'HTTP_USER_AGENT': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
 'PATH_INFO': u'/y/z',
 'QUERY_STRING': '',
 'REMOTE_ADDR': '187.27.35.123',
 'REMOTE_PORT': '54221',
 'REQUEST_METHOD': 'POST',
 'REQUEST_URI': 'y/z',
 'SCRIPT_NAME': u'',
 'SERVER_NAME': 'xxxxxxx',
 'SERVER_PORT': '80',
 'SERVER_PROTOCOL': 'HTTP/1.1',
 'uwsgi.version': '0.9.6.5',
 'wsgi.errors': <open file 'wsgi_input', mode 'w' at 0xa126338>,
 'wsgi.file_wrapper': <built-in function uwsgi_sendfile>,
 'wsgi.input': <open file 'wsgi_input', mode 'r' at 0xa126a70>,


 'wsgi.multiprocess': True,
 'wsgi.multithread': False,
 'wsgi.run_once': False,
 'wsgi.url_scheme': 'http',
 'wsgi.version': (1, 0)}>

I tried to reproduce this error, but I couldn´t. I test on Firefox and Chrome, cleaned all cookies... Everything is fine. But I am getting this error a dozen of time, always with different IP, so I suppose that it isn't an attack... All my form has {% csrf_token %} and django.middleware.csrf.CsrfViewMiddleware is configured on MIDDLEWARE_CLASSES.

The log message above is very clear that CSRF_COOKIE isnt empty. I am using Django 1.4.

[UPDATED] I Think that theses users dont have cookies enabled... So... The problem is: How to use CSRF with users that don´t have cookies enabled?

Thomas
  • 2,256
  • 6
  • 32
  • 47
  • Could it be that the client doesnt have cookies enabled? Maybe its a crawler or some random client type. – jdi Apr 22 '12 at 01:32
  • Hello Jdi, POST variable I can see that it is a valid user (not a crawler). If the client dont have cookie enable the "CSRF_COOKIE" wouldn´t be empty? – Thomas Apr 22 '12 at 01:38
  • Jdi, I just did this test here... I removed CSRF_COOKIE with firecookie and I get the error. I am not sure if this is the problem because I am getting the a lot of errors like that, but do you know how can I alert the user to enable cookies? – Thomas Apr 22 '12 at 01:44
  • Maybe a javascript test? http://forums.asp.net/t/1149145.aspx/1 – jdi Apr 22 '12 at 01:59
  • I am trying to look for some other solution, does anyone have an idea? – Thomas Apr 22 '12 at 22:31
  • So... The problem is: How to use CSRF with users that don´t have cookies enabled? – Thomas Apr 22 '12 at 23:40
  • If cookies are not enabled, then a CSRF attack is no longer possible. So all in all, you shouldn't need to handle whether their cookies are enabled or not. Form submissions will fail directly if they require CSRF. And you can control the view that is used to handle the CSRF failure: https://docs.djangoproject.com/en/dev/ref/settings/#std%3asetting-CSRF_FAILURE_VIEW – jdi Apr 23 '12 at 00:02

1 Answers1

2

As I had mentioned in my main comment, you will see that error when a 403 is raised because of a CSRF failure.

You should not need to worry about trying to handle CSRF protection against users without cookies enabled. The very nature of a CSRF attack requires the use of browser cookies. If they are not used, the CSRF-protected request will fail (as you have seen). Thus, you are still protected.

Django lets you set a specific view to use for the client in the event of a CSRF failure: https://docs.djangoproject.com/en/dev/ref/settings/#std%3asetting-CSRF_FAILURE_VIEW

Really, you should not need to do anything other than note that there are requests that are trying to POST to your server in an invalid way.

jdi
  • 90,542
  • 19
  • 167
  • 203