There is an url that is normally operated using POST requests (i.e. POST request is sent when user submits form). But attacker can form GET request with parameters that are sent in POST request. This request will be approved by server and associated action will be done. I know that it's recommended not to allow GET requests to prevent CSRF attacks. But tokens should be submitted to make action executed.

Should urls that are normally operated using POST requests accept only POST requests?

7 Answers
7

If the transaction has any side effects, yes, you should set up your web server so it does not process those GET requests. You should not allow any GET request to cause side effects on your server.

I can't point to any particular attack that will necessarily cause problems for you, but there are subtle vulnerabilities if you allow processing of a GET request to cause side effects, so if you allow GET requests to have side effects, you're starting to edge into "there be dragons" territory. For instance, I know of one subtle attack on sites that use the Referer header to defend against CSRF attacks, and that allow GET requests to have side effects. Browsers haven't deployed fixes to stop that attack because the reaction is "duh, GET requests aren't supposed to have side effects, so it's the web site's own fault". So rather than enter potentially dangerous territory, I suggest you set up your web server so it only processes those requests via POST, not via GET.

As in, in PHP, check the $_POST array, not the $_REQUEST array.
–
TRiGOct 25 '11 at 17:34

Problem with GET with side-effects: some browsers did, do, or might in the future decide to pre-fetch HTTP GET URL for faster rendering (as this practice badly breaks with quite a few web-applications, browsers are likely to limit this feature to alleged "safe cases", but you never know if the definition of "safe cases" is good enough). No browser ever has, does, or will "pre-fetch" HTTP POST requests.
–
curiousguyJul 11 '12 at 3:29

Some programs speed up response time by prefetching linked pages, so trigger bogus request.

The URL cannot be bookmarked, preventing accidental submission (though the CSRF token may be time-limited anyway).

The form data (which could include CSRF tokens) does not show up in the address bar, bookmarks, browser history or server logs.

POST does not provide any noteworthy protection against CRSF. Only unguessable tokens can do that, as you said. If you are only using "POST" in your forms, none of the listed issues apply to you because normal users will use the POST-variant.

Of course there is the notion of disabling things that are not used to reduce the attackable surfaces.

Reason why you should not use GET method for sensitive data are already listed above, so I will not write it all over again. And as I understand by default your application would generate a Post request for the resources in question.
Some Reasons why you should still block GET method by configuration or programmatically

Few Users tend to bookmark pages with the Parameters in URL( even Login requests). So if your application does not process the GET request the bookmark will not work and hence they will not really use the bookmarks. Hence avoiding the exposure of sensitive data in URL

When you have an enterprise application same request handler may be invoked from different components on the application, so one developer might use Post to invoke this but some other developer in future might use GET to invoke it. So by diabling the GET method you will make sure that he/she fails the unit testing.

Why not just restrict your use of individual variables to their intended sources?

This request will be approved by server and action will be done

This sounds like you are not scoping your variables properly. You didn't mention what server side language you are using, but most can distinguish between GET and POST. For example, if you're expecting a variable named 'foo' via POST, in PHP using $_POST['foo'] rather than $_REQUEST['foo'] will remove the ambiguity.

If your application is designed to expect one type of behavior under normal use (e.g. a POST) but then receives something unexpected (e.g. a GET in this case) then you also have a good scenario to detect potentially malicious users.