2011-02-15 10 views
20

Rails levanta un InvalidAuthenticityToken cuando el token CSRF no coincide. Pero, al leer el source, no puedo entender cómo sucede esto en realidad. Comienzo anotando el árbol para esa clase:¿Cómo funciona la protección Rails CSRF?

$ ack --ignore-dir=test InvalidAuthenticityToken 

actionpack/lib/action_controller/metal/request_forgery_protection.rb 
4: class InvalidAuthenticityToken < ActionControllerError #:nodoc: 
17: # which will check the token and raise an ActionController::InvalidAuthenticityToken 

actionpack/lib/action_dispatch/middleware/show_exceptions.rb 
22:  'ActionController::InvalidAuthenticityToken' => :unprocessable_entity 

Solo dos aciertos, ignorando el comentario. El primero es la definición de clase:

class InvalidAuthenticityToken < ActionControllerError #:nodoc: 
end 

El segundo es traducir la excepción en un código de estado HTTP. protección CSRF se habilita llamando protect_from_forgery en el controlador, por lo que vamos a ver que:

def protect_from_forgery(options = {}) 
    self.request_forgery_protection_token ||= :authenticity_token 
    before_filter :verify_authenticity_token, options 
end 

Se añade un filtro:

def verify_authenticity_token 
    verified_request? || handle_unverified_request 
end 

¿Qué le llama a esto cuando la verificación falla:

def handle_unverified_request 
    reset_session 
end 

Entonces, ¿cómo se plantea realmente InvalidAuthenticityToken?

Respuesta

21

El comportamiento fue changed fairly recently pero la documentación aún no se ha actualizado. El nuevo enfoque que se utiliza es suponer que la sesión ha sido secuestrada y, por lo tanto, borrar la sesión. Suponiendo que su sesión contiene la información de autenticación más importante para esta solicitud (como el hecho de que haya iniciado sesión como alice) y su controlador asegura que el usuario está autenticado para esta acción, su solicitud será redireccionada a una página de inicio de sesión (o como quiera que sea elige manejar un usuario no conectado). Sin embargo, para las solicitudes que no están autenticadas, como un formulario de registro, la solicitud se procesará utilizando una sesión vacía.

Parece que este compromiso también cierra un CSRF vulnerability, pero no leí los detalles de eso.

para obtener el comportamiento de edad, sólo tendría que definir este método:

def handle_unverified_request 
    raise(ActionController::InvalidAuthenticityToken) 
end 

Puede leer más sobre CSRF y otros problemas de seguridad Rieles en el Ruby on Rails Security Guide.

+0

Gracias! Eso es lo que obtengo al ejecutar 3.0.3 pero leyendo la fuente de master. Gran explicación del razonamiento detrás de este cambio: es incluso mejor que lo que figura en la publicación oficial del blog. –

9

verify_authenticity_token utilizado para definir como

verified_request? || raise(ActionController::InvalidAuthenticityToken) 

pero como se ha señalado, ahora llama handle_unverified_request, que a su vez llama a reset_session

No creo rieles realidad arroja esa excepción más.

http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails estados

Después de aplicar este parche fallaron CSRF solicitudes ya no generarán HTTP 500 errores, en lugar de la sesión se se restablecerá. Los usuarios pueden anular este comportamiento anulando handle_unverified_request en sus propios controladores .

https://github.com/rails/rails/commit/66ce3843d32e9f2ac3b1da20067af53019bbb034

+0

Gracias! Desearía poder aceptar ambas respuestas. –

Cuestiones relacionadas