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