variable rails authenticity ruby-on-rails ruby ruby-on-rails-3

ruby on rails - authenticity - ¿Cómo funciona la protección Rails CSRF?



rails session (2)

Rails genera un InvalidAuthenticityToken cuando el token CSRF no coincide. Pero, al leer la source , no puedo entender cómo sucede esto realmente. Empiezo haciendo clic en el árbol para esa clase:

$ 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 hits, ignorando el comentario. La primera es la definición de la clase:

class InvalidAuthenticityToken < ActionControllerError #:nodoc: end

El segundo es traducir la excepción a un código de estado HTTP. La protección CSRF se habilita al llamar a protect_from_forgery en el controlador, así que veamos eso:

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

Añade un filtro:

def verify_authenticity_token verified_request? || handle_unverified_request end

Que llama a esto cuando falla la verificación:

def handle_unverified_request reset_session end

Entonces, ¿cómo se InvalidAuthenticityToken realmente InvalidAuthenticityToken ?


El comportamiento ha cambiado bastante recientemente, pero la documentación aún no se ha actualizado. El nuevo enfoque que se está utilizando es suponer que la sesión ha sido secuestrada y, por lo tanto, limpiar 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 garantiza que el usuario esté autenticado para esta acción, su solicitud será redirigida a una página de inicio de sesión (o como sea) elegir manejar un usuario no registrado). Sin embargo, para solicitudes que no están autenticadas, como un formulario de registro, la solicitud pasaría por el uso de una sesión vacía.

Parece que este compromiso también va a cerrar una vulnerabilidad CSRF , pero no leí los detalles de eso.

Para obtener el comportamiento anterior, simplemente definirías este método:

def handle_unverified_request raise(ActionController::InvalidAuthenticityToken) end

Puede leer más sobre CSRF y otros problemas de seguridad de Rails en la Guía de seguridad de Ruby on Rails .


Verify_authenticity_token solía definirse como

verified_request? || raise(ActionController::InvalidAuthenticityToken)

pero como handle_unverified_request , ahora llama a handle_unverified_request , que a su vez llama reset_session

No creo que Rails en realidad lance esa excepción nunca más.

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

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

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