reu / omniauth-steam

Steam authentication strategy for OmniAuth
93 stars 38 forks source link

Anyone can login using self-owned fake openid server #24

Closed zharikovpro closed 7 years ago

zharikovpro commented 8 years ago

This plugin acccepts params:

"openid.op_endpoint"=>"https://steamcommunity.com/openid/login",
"openid.claimed_id"=>"http://steamcommunity.com/openid/id/64bitsteamid",
"openid.identity"=>"http://steamcommunity.com/openid/id/64bitsteamid"

Turned out that attacker can modify op_endpoint and/or other steamcommunity links and route auth request to self-owned openid server which will grant access to any steam id of choice. That way attacker is able to authenticate as any user on site, having it's steam64 id.

Right this vulnerability can be closed using global middleware - to check that openid.op_endpoint must start with https://steamcommunity.com/openid and openid.claimed_id, openid.identity must start with http://steamcommunity.com/openid , otherwise request will fail.

zharikovpro commented 8 years ago

Bandaid in config/initializers/omniauth.rb:

# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# omniauth-steam doesn't check openid.op_endpoint
# Attacker can use it's own fake openid server which always grants auth
# and route auth calls to it with requests like
#
# http://api.localhost:3000/omniauth/steam/callback?auth_origin_url=http%3A%2F%2Fwww.site.com&resource_class=User&_method=post&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.mode=id_res&openid.op_endpoint=https%3A%2F%2Ffakeserver.com%2Fopenid%2Flogin&openid.claimed_id=http%3A%2F%2Fsteamcommunity.com%2Fopenid%2Fid%2F76561198168285384&openid.identity=http%3A%2F%2Fsteamcommunity.com%2Fopenid%2Fid%2F76561198168285384&openid.return_to=http%3A%2F%2Fsite.com%2Fomniauth%2Fsteam%2Fcallback%3Fauth_origin_url%3Dhttp%253A%252F%252Fwww.site.com%26resource_class%3DUser%26_method%3Dpost&openid.response_nonce=2016-10-25T14%3A21%3A45ZtfzZbrgiBUBNDEdvmsmGMb%2FQKWY%3D&openid.assoc_handle=1234567890&openid.signed=signed%2Cop_endpoint%2Cclaimed_id%2Cidentity%2Creturn_to%2Cresponse_nonce%2Cassoc_handle&openid.sig=KVlpWTA8NqBU6oKog1fNkg%2B9Wwc%3D
# (this example contains fakeserver.com instead of steamcommunity.com in openid.op_endpoint param)
#
# also check openid.claimed_id and openid.identity for legitimate value from Steam, as they may have different URLs
class OpenidProtection
  def initialize(app)
    @app = app
  end

  def redirect
    [303, {'Location' => 'http://site.com/api/v1/auth/steam?auth_origin_url=http://www.site.com', 'Content-Type' => 'text/html'}, ['See Other']]
  end

  def call(env)
    request = Rack::Request.new(env)

    openid_endpoint = request.params['openid.op_endpoint']
    if openid_endpoint.present?
      unless openid_endpoint.start_with?('https://steamcommunity.com/openid')
        return redirect
      end
    end

    openid_claimed_id = request.params['openid.claimed_id']
    if openid_claimed_id.present?
      unless openid_claimed_id.start_with?('http://steamcommunity.com/openid')
        return redirect
      end
    end

    openid_identity = request.params['openid.identity']
    if openid_identity.present?
      unless openid_identity.start_with?('http://steamcommunity.com/openid')
        return redirect
      end
    end

    origin = request.params['origin']
    if origin.present?
      return redirect
    end

    auth_origin_url = request.params['auth_origin_url']
    if auth_origin_url.present?
      unless DeviseTokenAuth.redirect_whitelist.include?(auth_origin_url)
        return redirect
      end
    end

    @app.call(env)
  end
end

Rails.application.config.middleware.use OpenidProtection
reu commented 8 years ago

Thanks a lot for the report @zharikovpro! Does anyone has an idea of how could we patch this? Should it be patched on omniauth-steam or in the omniauth-openid?

scholtzm commented 7 years ago

@reu You should be validating claimed identifier format. As per docs, it should be http://steamcommunity.com/openid/id/<steamid>.

This is not an issue in omniauth-openid as the OpenID spec actually allows this.

2called-chaos commented 7 years ago

I just wanted to note that you can retrieve SteamID64 from any SteamID format and/or profile URL (be it custom URL or not).