2015-05-21 8 views
6

Używam wzorca tokenu synchronizatora dla standardowych formularzy (useToken = true), ale nie mogę znaleźć żadnej zalecanej metody radzenia sobie z tym przez AJAX.Grails - Czy istnieje zalecany sposób radzenia sobie z atakami CSRF w formularzach AJAX?

EDIT

Od opublikowania tego, mam walcowane moje własne rozwiązanie zawierające Grails dotychczasowego wzoru z góry.

W jQuery ajax umieszczam cały formularz (który zawiera wstrzyknięte pola ukryte SYNCHRONIZER_TOKEN i SYNCHRONIZER_URI) tak, że zamknięcie withForm może działać zgodnie z oczekiwaniami w kontrolerze.

Problem polega na tym, że po pomyślnej odpowiedzi nie ma nowego zestawu znaczników (ponieważ strona nie jest ponownie ładowana, a tag g: form nie jest wywoływany), więc robię to ręcznie w kontrolerze, wywołując tę ​​samą bibliotekę, co g: form taglib, i zwróć go w odpowiedzi ajax, a następnie zresetuj wartość ukrytego pola. Patrz poniżej:

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); 
    } 
}) 

w kontrolerze:

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 
} 

Czy ktoś może określić, czy ja nieświadomie wprowadził lukę bezpieczeństwa w powyższym roztworze. Wydaje mi się to odpowiednie, ale nie podoba mi się ręczne przetasowanie czegokolwiek związanego z bezpieczeństwem.

Odpowiedz

0

Nice!

IMO, lepiej zresetować token w tym samym czasie.

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

a jeśli masz wiele formularzy w tej samej stronie, zdefiniować zmienną do przechowywania żetonów wrócił z każdego żądania AJAX.

btw, dlaczego nie wdrożyć wzoru tokena na własną rękę?

  • Wygeneruj token, na przykład UUID.randomUUID().toString(), i zapisz go w sesji z adresem URL jako kluczem.
  • Sprawdź i zresetuj token w satrt po akcji.
+0

Właściwie to od czasu wprowadzenia zmian w tej implementacji odesłanie tokenu dla następnego żądania oznaczało, że osoba atakująca mająca podstawową wiedzę na temat implementacji tokenów synchronizatora Grails mogłaby z powodzeniem ją wykorzystać. Tak więc zachowałem powyższą implementację, aby zapobiec powielaniu formularzy i ulepszałem je za pomocą własnego rozwiązania o zasięgu sesji, generując mój własny identyfikator UUID w taki sam sposób jak wspomniałeś powyżej. – dre

+0

Rozumiem. Może powinieneś pomyśleć o zresetowaniu tokena w 'complete' zamiast' success'. W moim projekcie istnieje mnóstwo odwołań ajaxowych na tej samej stronie, więc dołączam i resetuję tokena w ajaxSend i ajaxStop na całym świecie. – Yang

+0

Tak, dobry punkt na zrobienie tego w * pełnym * zamiast * sukcesie *. Dla mojej własnej realizacji, generuję token i dodam do sesji, jak tylko trafisz kontroler. Nie widzę przewagi ciągłej regeneracji, jest mało prawdopodobne, że ktoś ją zgadnie w rozsądnym czasie. Oczywiście, gdy użytkownik opuści stronę i wróci do niej, generowany jest nowy. – dre

Powiązane problemy