Grails - Is there a recommended way to deal with CSRF attacks in AJAX forms?

I use the synchronizer marker template for standard forms (useToken = true), but I cannot find any recommended method to deal with this over AJAX.

EDIT

After posting this post, I implemented my own solution, including the existing Grails template on top.

In jQuery ajax, I post the whole form (which will include the hidden fields SYNCHRONIZER_TOKEN and SYNCHRONIZER_URI from Grails), so closing withForm can be done as expected in the controller.

The problem is that with a successful response there is no new set of tokens (since the page does not reload, and g: form taglib is not called), and therefore I do this manually in the controller, calling to the same library as g: form taglib and return it in ajax response, and then reset the value of the hidden field. See below:

var formData = jQuery("form[name=userform]").serializeArray(); $.ajax({ type: 'POST', url: 'delete', data: formData, success: function (data) { // do stuff }, complete: function (data) { // Reset the token on complete $("#SYNCHRONIZER_TOKEN").val(data.newToken); } }) 

in the controller:

 def delete(String selectedCommonName) { def messages = [:] withForm { User user = User.findByName(name) if (user) { userService.delete(user) messages.info = message(code: 'user.deleted.text') } else { messages.error = message(code: 'user.notdeleted.text') } }.invalidToken { messages.error = message(code: 'no.duplicate.submissions') } // Set a new token for CSRF protection messages.newToken = SynchronizerTokensHolder.store(session).generateToken(params.SYNCHRONIZER_URI) render messages as JSON } 

Can anyone determine if I unknowingly presented a security flaw in the above solution. It looks adequate to me, but I do not like how manual pitching has anything to do with security.

+6
source share
1 answer

Nice!

IMO, you better reset the token at the same time.

SynchronizerTokensHolder.store(session).resetToken(params.SYNCHRONIZER_URI)

and if you have multiple forms on the same page, define a variable to hold the tokens returned from each ajax request.

btw, why not implement the token template yourself?

  • Create a token, such as UUID.randomUUID().toString() , and save it in the session with the URL as the key.
  • Check and reset the token when downloading messages.
0
source

Source: https://habr.com/ru/post/987642/


All Articles