From 1bb0284d6e668b8b3d31167790ed6db1f6ccc4be Mon Sep 17 00:00:00 2001 From: Benjamin Eckel Date: Tue, 7 Nov 2017 18:18:23 -0600 Subject: [PATCH] Fix SSRF vulnerability in Resource#find --- lib/recurly/api.rb | 8 ++++++++ lib/recurly/api/net_http_adapter.rb | 1 + lib/recurly/resource.rb | 3 +-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/recurly/api.rb b/lib/recurly/api.rb index 08408a58e..00d9e42d2 100644 --- a/lib/recurly/api.rb +++ b/lib/recurly/api.rb @@ -15,6 +15,7 @@ class API require 'recurly/api/errors' @@base_uri = "https://api.recurly.com/v2/" + @@valid_domains = [".recurly.com"] RECURLY_API_VERSION = '2.8' @@ -75,6 +76,13 @@ def base_uri URI.parse @@base_uri.sub('api', Recurly.subdomain) end + def validate_uri!(uri) + domain = @@valid_domains.detect { |d| uri.host.end_with?(d) } + unless domain + raise ArgumentError, "URI #{uri} is invalid. You may only make requests to a Recurly domain." + end + end + # @return [String] def user_agent "Recurly/#{Version}; #{RUBY_DESCRIPTION}" diff --git a/lib/recurly/api/net_http_adapter.rb b/lib/recurly/api/net_http_adapter.rb index 39d34d884..7f7c849bb 100644 --- a/lib/recurly/api/net_http_adapter.rb +++ b/lib/recurly/api/net_http_adapter.rb @@ -43,6 +43,7 @@ def request method, uri, options = {} } uri += "?#{pairs.join '&'}" end + self.validate_uri!(uri) request = METHODS[method].new uri.request_uri, head request.basic_auth(*[Recurly.api_key, nil].flatten[0, 2]) if options[:body] diff --git a/lib/recurly/resource.rb b/lib/recurly/resource.rb index 16901640c..9fe3b4791 100644 --- a/lib/recurly/resource.rb +++ b/lib/recurly/resource.rb @@ -335,9 +335,8 @@ def find(uuid, options = {}) raise NotFound, "can't find a record with nil identifier" end - uri = uuid =~ /^http/ ? uuid : member_path(uuid) begin - from_response API.get(uri, {}, options) + from_response API.get(member_path(uuid), {}, options) rescue API::NotFound => e raise NotFound, e.description end