Skip to content

Instantly share code, notes, and snippets.

@abrom
Last active March 30, 2022 07:43
Show Gist options
  • Save abrom/effe58b27a4f4ac1b97fb85593d7c3be to your computer and use it in GitHub Desktop.
Save abrom/effe58b27a4f4ac1b97fb85593d7c3be to your computer and use it in GitHub Desktop.
Address CVE-2015-9284 for generic Rack apps (eg Sinatra) for Omniauth
require 'omniauth/strategies/<your strategy>'
require_relative 'omniauth_authenticity_checker'
OmniAuth.config.allowed_request_methods = [:post]
OmniAuth.config.before_request_phase = OmniauthAuthenticityChecker.new(reaction: :drop_session)
# And if you haven't already, you should be loading in the `Rack::Protection` middleware:
use Rack::Protection, reaction: :drop_session, use: :authenticity_token
# You will also need to make sure your users are POSTing to your authorise route, and not simply
# linking/redirecting to it. This change would make GETing the authorise route 404 so you may wish to
# handle this by rendering a nicer error message, and/or rendering a form with a button to POST to your
# authorise route.
require 'rack-protection'
class OmniauthAuthenticityChecker < Rack::Protection::AuthenticityToken
def initialize(options = {})
@options = default_options.merge(options)
end
def call(env)
unless accepts? env
instrument env
react env
end
end
def deny(env)
warn env, "attack prevented by #{self.class}"
raise Net::HTTPForbidden, options[:message]
end
end
@abrom
Copy link
Author

abrom commented Dec 26, 2019

It sounds like it was working exactly as expected?! i.e. returning a 403 (from the raise Net::HTTPForbidden in the deny method) if you don't include the authenticity token. That's the whole point of the gist :)

Am I missing something??

@pascalw
Copy link

pascalw commented Dec 26, 2019

Ah no, sorry I wasn't clear. I included only the code I posted, so I didn't use the OmniauthAuthenticityChecker class, nor OmniAuth.config.before_request_phase.

Also note how I configured Rack Protection. use Rack::Protection, reaction: :drop_session, use: :authenticity_token didn't work, but use Rack::Protection::AuthenticityToken did.

@abrom
Copy link
Author

abrom commented Dec 26, 2019

Not sure I can add anything. No doubt something else in your app is configured differently - middleware order etc.

If your solution works for you and it verifies the authenticity token (and acts appropriately on failure) then happy days.

@pascalw
Copy link

pascalw commented Dec 26, 2019

Absolutely! Thanks for pointing me in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment