From aae9df3b966eba242a22ed00db46c5cb16d2791b Mon Sep 17 00:00:00 2001 From: Olivier Lacan Date: Thu, 19 Nov 2015 18:25:27 -0500 Subject: [PATCH] Neutralize unsafe (non-local) destination params This addresses a cover redirect vulnerability when the following is used as an authentication URL: http://domain.dev/auth/provider?destination=//google.com Covert redirects (https://www.owasp.org/index.php/Open_redirect) are often used in phishing scams by giving people a link that appears save but surreptitiously redirects them to a different domain. Once on that different domain (which can be designed to look like the original domain), users can be asked their password and give it away because they don't notice that they have been redirected to a different destination. This is not a vulnerability in itself, but used in combination with a rather simple phishing attack, this can be potentially dangerous. --- lib/omniauth/strategies/oauth2.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/omniauth/strategies/oauth2.rb b/lib/omniauth/strategies/oauth2.rb index 3ffff1b..09b7c5b 100644 --- a/lib/omniauth/strategies/oauth2.rb +++ b/lib/omniauth/strategies/oauth2.rb @@ -45,6 +45,8 @@ def client end def request_phase + neutralize_unsafe_destination! + redirect client.auth_code.authorize_url({:redirect_uri => callback_url}.merge(authorize_params)) end @@ -97,6 +99,16 @@ def deep_symbolize(options) hash end + def local_uri?(uri) + uri.relative? || uri.host.include?(request.host) + end + + # if request.params["destination"] does not contain a destination that + # includes + def neutralize_unsafe_destination! + request.params.delete('destination') if unsafe_destination? + end + def options_for(option) hash = {} options.send(:"#{option}_options").select { |key| options[key] }.each do |key| @@ -105,6 +117,18 @@ def options_for(option) hash end + def safe_destination? + true if request.params['destination'].nil? + + uri = URI.parse(request.params['destination']) + + local_uri?(uri) ? true : false + end + + def unsafe_destination? + !safe_destination? + end + # An error that is indicated in the OAuth 2.0 callback. # This could be a `redirect_uri_mismatch` or other class CallbackError < StandardError