From 0be24225890a19060bae5edf103aa94442cef4e7 Mon Sep 17 00:00:00 2001 From: mohamedhafez Date: Mon, 26 Sep 2011 20:39:12 -0700 Subject: [PATCH 1/3] Allows the optional declaration of a whitelist of methods to expose through DRb for any class DRb will be sharing an instance of. (The current behavior of exposing all public methods of a class can leave a pretty scary security hole in some applications) If drb_safe_methods is used in a class's definition, then any attempt to call a non-whitelisted method on that class through DRb will fail. There is no change to DRb's normal behavior if drb_safe_methods has not been called in a class's definition. --- lib/drb/drb.rb | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb index 69456b1db2e9e0..588e42182b6b27 100644 --- a/lib/drb/drb.rb +++ b/lib/drb/drb.rb @@ -1437,8 +1437,12 @@ def run ] # Has a method been included in the list of insecure methods? + # Or, if a list of drb-safe methods has been defined for the + # front object, is this method not included in that list? def insecure_method?(msg_id) - INSECURE_METHOD.include?(msg_id) + INSECURE_METHOD.include?(msg_id) || + (@front.respond_to?(:drb_safe_methods_list) && + !@front.drb_safe_methods_list.include?(msg_id)) end # Coerce an object to a string, providing our own representation if @@ -1768,6 +1772,31 @@ def fetch_server(uri) module_function :fetch_server end + +# Declare a list of methods to expose to DRb +# +# Allows the optional declaration of a whitelist of methods to expose +# through DRb for any class DRb will be sharing an instance of. If +# drb_safe_methods is used, then any attempt to call a non-whitelisted +# method on that class through DRb will fail. +# +# EXAMPLE USAGE: +# def MyClass +# drb_safe_methods :method1, :method2 +# end +# +# NOTE: if you are using irb as the client and :to_s isn't in the list, +# you will get a DRb::DRbConnError when you create the DRbObject, but only +# because irb calls to_s to display the result; the DRbObject is still +# usable. +class Class + def drb_safe_methods(*symbols) + define_method(:drb_safe_methods_list) do + symbols + end + end +end + # :stopdoc: DRbObject = DRb::DRbObject DRbUndumped = DRb::DRbUndumped From 704c7a6fc13bd65415d3bfa259765d2f1ead1625 Mon Sep 17 00:00:00 2001 From: mohamedhafez Date: Wed, 28 Sep 2011 21:05:27 -0700 Subject: [PATCH 2/3] whoops, I was checking @front each time for the drb_safe_methods_list, in order to deal correctly for DRbUndumped objects i needed to pass it the actual obj from check_insecure_method and check that instead --- lib/drb/drb.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb index 588e42182b6b27..785d85d6f02905 100644 --- a/lib/drb/drb.rb +++ b/lib/drb/drb.rb @@ -1439,12 +1439,13 @@ def run # Has a method been included in the list of insecure methods? # Or, if a list of drb-safe methods has been defined for the # front object, is this method not included in that list? - def insecure_method?(msg_id) + def insecure_method?(obj, msg_id) INSECURE_METHOD.include?(msg_id) || - (@front.respond_to?(:drb_safe_methods_list) && - !@front.drb_safe_methods_list.include?(msg_id)) + (obj.respond_to?(:drb_safe_methods_list) && + !obj.drb_safe_methods_list.include?(msg_id)) end + # Coerce an object to a string, providing our own representation if # to_s is not defined for the object. def any_to_s(obj) @@ -1464,7 +1465,7 @@ def any_to_s(obj) def check_insecure_method(obj, msg_id) return true if Proc === obj && msg_id == :__drb_yield raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class - raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) + raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(obj, msg_id) if obj.private_methods.include?(msg_id) desc = any_to_s(obj) From 96665e3b27595c338f6b9855a112259117098bd8 Mon Sep 17 00:00:00 2001 From: mohamedhafez Date: Wed, 19 Oct 2011 10:49:42 -0700 Subject: [PATCH 3/3] I was accidentally classifying private methods, protected methods,and unimplemented methods as insecure methods. this commit fixes that --- lib/drb/drb.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb index 785d85d6f02905..c56bfe5f68a4a0 100644 --- a/lib/drb/drb.rb +++ b/lib/drb/drb.rb @@ -1441,7 +1441,8 @@ def run # front object, is this method not included in that list? def insecure_method?(obj, msg_id) INSECURE_METHOD.include?(msg_id) || - (obj.respond_to?(:drb_safe_methods_list) && + (obj.public_methods.include?(:drb_safe_methods_list) && + obj.public_methods.include?(msg_id) && !obj.drb_safe_methods_list.include?(msg_id)) end