From 5e9faad4dcd5adee043b55f6e839156e82e97de0 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 9 Oct 2015 14:09:12 -0500 Subject: [PATCH] Revert "Merge branch using Rex sockets as IO" This reverts commit c48246c91ce727ab55caf517cddfd5e17766b9bf, reversing changes made to 3cd9dc4fde06e43e6e7b489cbcb31a2f7eb94b3d. --- lib/msf/java/rmi/client.rb | 48 ++++++++++++++++++- .../exploits/multi/misc/java_rmi_server.rb | 8 +--- .../java/rmi/client/jmx/connection_spec.rb | 24 ++++++++++ .../msf/java/rmi/client/jmx/server_spec.rb | 8 ++++ spec/lib/msf/java/rmi/client_spec.rb | 8 ++++ 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/lib/msf/java/rmi/client.rb b/lib/msf/java/rmi/client.rb index f14ff153da..9cb6987357 100644 --- a/lib/msf/java/rmi/client.rb +++ b/lib/msf/java/rmi/client.rb @@ -19,6 +19,23 @@ module Msf include Msf::Java::Rmi::Client::Jmx include Exploit::Remote::Tcp + def initialize(info = {}) + super + + register_advanced_options( + [ + OptInt.new('RmiReadLoopTimeout', [ true, 'Maximum number of seconds to wait for data between read iterations', 1]) + ], Msf::Java::Rmi::Client + ) + end + + # Returns the timeout to wait for data between read iterations + # + # @return [Fixnum] + def read_loop_timeout + datastore['RmiReadLoopTimeout'] || 1 + end + # Returns the target host # # @return [String] @@ -86,8 +103,9 @@ module Msf # @see Rex::Proto::Rmi::Model::ProtocolAck.decode def recv_protocol_ack(opts = {}) nsock = opts[:sock] || sock + data = safe_get_once(nsock) begin - ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(nsock) + ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data)) rescue Rex::Proto::Rmi::DecodeError return nil end @@ -105,15 +123,41 @@ module Msf # @see Rex::Proto::Rmi::Model::ReturnData.decode def recv_return(opts = {}) nsock = opts[:sock] || sock + data = safe_get_once(nsock) begin - return_data = Rex::Proto::Rmi::Model::ReturnData.decode(nsock) + return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data)) rescue Rex::Proto::Rmi::DecodeError return nil end return_data.return_value end + + # Helper method to read fragmented data from a ```Rex::Socket::Tcp``` + # + # @param nsock [Rex::Socket::Tcp] + # @return [String] + def safe_get_once(nsock = sock, loop_timeout = read_loop_timeout) + data = '' + begin + res = nsock.get_once + rescue ::EOFError + res = nil + end + + while res && nsock.has_read_data?(loop_timeout) + data << res + begin + res = nsock.get_once + rescue ::EOFError + res = nil + end + end + + data << res if res + data + end end end end diff --git a/modules/exploits/multi/misc/java_rmi_server.rb b/modules/exploits/multi/misc/java_rmi_server.rb index dde9a19bad..b557a3bf4b 100644 --- a/modules/exploits/multi/misc/java_rmi_server.rb +++ b/modules/exploits/multi/misc/java_rmi_server.rb @@ -154,13 +154,7 @@ class Metasploit3 < Msf::Exploit::Remote arguments: build_dgc_clean_args(new_url) ) - begin - return_value = recv_return - rescue Rex::StreamClosedError - # There should be a session... - disconnect - return - end + return_value = recv_return if return_value.nil? && !session_created? fail_with(Failure::Unknown, 'RMI Call failed') diff --git a/spec/lib/msf/java/rmi/client/jmx/connection_spec.rb b/spec/lib/msf/java/rmi/client/jmx/connection_spec.rb index 58200f856e..068988f14a 100644 --- a/spec/lib/msf/java/rmi/client/jmx/connection_spec.rb +++ b/spec/lib/msf/java/rmi/client/jmx/connection_spec.rb @@ -101,6 +101,14 @@ describe Msf::Java::Rmi::Client::Jmx::Connection do io.write(get_object_instance_response) io.seek(0) end + + allow_any_instance_of(::StringIO).to receive(:get_once) do |io, length, timeout| + io.read + end + + allow_any_instance_of(::StringIO).to receive(:has_read_data?) do |io| + false + end end it "returns true" do @@ -117,6 +125,14 @@ describe Msf::Java::Rmi::Client::Jmx::Connection do io.write(create_mbean_response) io.seek(0) end + + allow_any_instance_of(::StringIO).to receive(:get_once) do |io, length, timeout| + io.read + end + + allow_any_instance_of(::StringIO).to receive(:has_read_data?) do |io| + false + end end it "returns true" do @@ -133,6 +149,14 @@ describe Msf::Java::Rmi::Client::Jmx::Connection do io.write(invoke_response) io.seek(0) end + + allow_any_instance_of(::StringIO).to receive(:get_once) do |io, length, timeout| + io.read + end + + allow_any_instance_of(::StringIO).to receive(:has_read_data?) do |io| + false + end end it "returns true" do diff --git a/spec/lib/msf/java/rmi/client/jmx/server_spec.rb b/spec/lib/msf/java/rmi/client/jmx/server_spec.rb index c8528f2031..fbc2bf81ed 100644 --- a/spec/lib/msf/java/rmi/client/jmx/server_spec.rb +++ b/spec/lib/msf/java/rmi/client/jmx/server_spec.rb @@ -47,6 +47,14 @@ describe Msf::Java::Rmi::Client::Jmx::Server do io.write(new_client_response) io.seek(0) end + + allow_any_instance_of(::StringIO).to receive(:get_once) do |io, length, timeout| + io.read + end + + allow_any_instance_of(::StringIO).to receive(:has_read_data?) do |io| + false + end end it "returns the reference information" do diff --git a/spec/lib/msf/java/rmi/client_spec.rb b/spec/lib/msf/java/rmi/client_spec.rb index 5ae74bfacc..008b543ae1 100644 --- a/spec/lib/msf/java/rmi/client_spec.rb +++ b/spec/lib/msf/java/rmi/client_spec.rb @@ -44,6 +44,14 @@ describe Msf::Java::Rmi::Client do allow_any_instance_of(::StringIO).to receive(:put) do |io, data| io.write(data) end + + allow_any_instance_of(::StringIO).to receive(:get_once) do |io, length, timeout| + io.read + end + + allow_any_instance_of(::StringIO).to receive(:has_read_data?) do |io| + false + end end describe "#send_header" do