Are both GET and POST request vulnerable to CSRF? Should we use PUT instead?
-
2I'm afraid it doesn't have just to do with the type of request, but with how you perform them. Please read https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet carefully. – Steve Dodier-Lazaro May 25 '15 at 03:53
-
Thanks a lot! Yes you were right, its not just because a type of request :) – Ngoc Huynh May 25 '15 at 03:58
-
Is the client a web browser? – curiousguy May 25 '15 at 10:56
-
@curiousguy: Yes, – Ngoc Huynh May 25 '15 at 12:47
3 Answers
Yes, both GET and POST are vulnerable to CSRF.
However, RFC 7231 states
the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe".
Therefore, if a website has kept to the standard and only implements "unsafe" actions as POSTs, then here only POST requests are vulnerable. However, many websites don't do this for all of their "unsafe" actions - for example, logout functionality is often overlooked (although this is usually considered very low risk).
Although PUT is safe without CORS, it isn't the correct method to use in most cases. PUT is idempotent, therefore the request can be replayed without consequence, whereas POST is not. Not that any browser will arbitrarily retry PUT requests, but it might be an issue if some JavaScript does it on an event expecting no further state changes, for example. If you're implementing CSRF protection, a good method for protecting XHR requests is to add a header such as X-Requested-With
to your requests and then validate this header server side. You could combine this with a random value that is checked server side to add further protection in the case of browser plugins like Flash containing vulnerabilities that accidentally allow the header. See this answer and this one.
- 33,698
- 6
- 69
- 185
GET and POST can both be vulnerable to CSRF unless the server puts a strong Anti-CSRF mechanism in place, the server cant rely on the browser to prevent cross-domain requests. As for PUT requests, there is a slight difference, theoretically it is vulnerable too, however, it requires the circumstances to be more conducive. Here is why:
While GET and POST requests can be easily made through HTML forms, images, script tags etc, making a PUT request is slightly more complicated, you cant make a PUT request without the browser interfering with the request.
If you use the XmlHttpRequest API to set the request method as PUT, the browser first sends a CORS(Cross Origin Resource Sharing) 'pre-flight' request to the target server basically seeking permission to make the request, what happens is that an OPTIONS request is made to the target server with a header set to the Origin of the request say: http://example.com (where your script is hosted) and Access-Control-Request-Method and Access-Control-Request-Headers. If the server responds with Access-Control-Allow-Origin: http://example.com, then the browser sends your request forward. Pertinently, you need the server to return value for the Origin header as your server, if the Origin header is set to '*', then credentials cannot be sent with the request. As making a PUT request with credentials(cookies) to a server that allows Origin: * is not allowed. From https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS:
Preflighted requests
Unlike simple requests (discussed above), "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted. It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
So, conducting a CSRF attack against a page that uses PUT is slightly harder, as it requires the cooperation of the target server. However, this shouldn't be relied on as a viable anti-CSRF mechanism as browser quirks may render this mechanism for protection useless.
Also, as for the circumstances that may render dependence on PUT method as a protection have been summed up well in this answer: https://stackoverflow.com/a/11972282/4399898
Hope that helped.
- 581
- 4
- 10
-
Claiming that simple requests can only use one of those three `Content-Type` values is a dangerous oversimplification. See https://github.com/mdn/content/pull/11077. – jub0bs Jul 18 '22 at 17:22
The method; i.e. put, post, delete, request, get etc., of sending data is irrelevant. A CSRF (Cross Site Request Forgery) attack allows for un-trusted content to be injected and processed by the web server.
- 929
- 5
- 9