Search code examples
djangopython-2.7django-viewsdjango-csrfdjango-1.5

Using @csrf_protect on view GET methods


Most of my GET requests are fired by Angular which makes it easy to set the CSRF Token in the header. This already works out of the box for POST requests, however I was wondering whether I could use CSRF protection for GET requests as well.

My initial instinct was to add @csrf_protect before the View's get method, for instance:

class ProjectView(View):
    @csrf_protect
    def get(self, request, *args, **kwargs):
        ...

However this produces the error:

AttributeError at /project
'ProjectView' object has no attribute 'COOKIES'

File "c:\Apps\msysgit\simpletask\lib\site-packages\django\middleware\csrf.py" in process_view
  95.                 request.COOKIES[settings.CSRF_COOKIE_NAME])

So I'm guessing there's something which a POST request provides which a GET request does not. Is there a better way to do this?

Also, before anybody mentions that all sensitive information should be pulled via POST requests (as I've seen a few times lately), my reason for trying to stick with GET is I'm trying to build according to RESTful guidelines, meaning GET requests are for pulling data, POST is for new records, PUT is for updates and DELETE is for data deletion.

EDIT:

Since there seems to be a sentiment that I shouldn't be attempting the above, while I do now agree somewhat, the exploit(s) I'm attempting to prevent are discussed in these 3 links:


Solution

  • I don't think you quite understand what CSRF actually protects. CSRF exploits the trust that a site has in a user's browser; by exploiting a session cookie that allows the attacker to run commands on behalf of the user.

    The site trusts the request because it hasn't expired the session cookie for the browser. This is why in most CSRF mitigation techniques a unique OTP for each request that has a side effect is generated. The attacker would not know the key generated for the OTP, and hence cannot forge a legitimate request.

    For all URLs that have a side effect (like POST, PUT, DELETE) you would need CSRF. For GET it doesn't make any sense to have it, since GET requests - if you are doing REST correctly - should be idempotent - if run multiple times, they return the same results and they should not have any side effects.

    CSRF protection does not prevent information disclosure or man in the middle attacks. So if you have sensitive information you want to protect, use HTTPS. To prevent unregulated use of your API, use authentication and authorization.