From 717120b8c54621f1ff19768bb30f7ec05eaf60da Mon Sep 17 00:00:00 2001 From: sinn3r Date: Thu, 9 Apr 2015 00:34:09 -0500 Subject: [PATCH 1/4] Add #get_hidden_inputs for Metasploit::Framework::LoginScanner::HTTP --- .../framework/login_scanner/http.rb | 27 +++++++++++ .../framework/login_scanner/http_spec.rb | 47 +++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index fda5c5d0c7..b35266b052 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -1,6 +1,7 @@ require 'rex/proto/http' require 'metasploit/framework/login_scanner/base' require 'metasploit/framework/login_scanner/rex_socket' +require 'nokogiri' module Metasploit module Framework @@ -241,6 +242,32 @@ module Metasploit end + # Returns a collection of found hidden inputs + # + # @param res [Rex::Proto::Http::Response] A response object that contains a body + # @return [Array] An array, each element represents a form that contains a hash of found hidden inputs + # * 'name' [String] The hidden input's original name. The value is the hidden input's original value. + # @example + # res = send_request('uri'=>'/') + # inputs = get_hidden_inputs(res) + # session_id = inputs[0]['sessionid'] # The first form's 'sessionid' hidden input + def get_hidden_inputs(res) + forms = [] + noko = Nokogiri::HTML(res.body) + noko.search("form").each_entry do |form| + found_inputs = {} + form.search("input").each_entry do |input| + input_name = input.attributes['name'] ? input.attributes['name'].value : '' + input_value = input.attributes['value'] ? input.attributes['value'].value : '' + found_inputs[input_name] = input_value unless input_name.empty? + end + forms << found_inputs unless found_inputs.empty? + end + + forms + end + + # Attempt a single login with a single credential against the target. # # @param credential [Credential] The credential object to attempt to diff --git a/spec/lib/metasploit/framework/login_scanner/http_spec.rb b/spec/lib/metasploit/framework/login_scanner/http_spec.rb index 5f26ff7271..75ebe37d7d 100644 --- a/spec/lib/metasploit/framework/login_scanner/http_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/http_spec.rb @@ -30,4 +30,51 @@ describe Metasploit::Framework::LoginScanner::HTTP do end end + describe '#get_hidden_inputs' do + let(:response) do + res = Rex::Proto::Http::Response.new(200, 'OK') + res.body = %Q| + + + +
+ +
+
+ + +
+ + + + | + res + end + + + context 'when an HTML page contains two forms containing hidden inputs' do + it 'returns an array' do + expect(subject.get_hidden_inputs(response)).to be_kind_of(Array) + end + + it 'returns hashes in the array' do + subject.get_hidden_inputs(response).each do |form| + expect(form).to be_kind_of(Hash) + end + end + + it 'returns \'some_value_1\' in the input_1 hidden input from the first element' do + expect(subject.get_hidden_inputs(response)[0]['input_1']).to eq('some_value_1') + end + + it 'returns two hidden inputs in the second element' do + expect(subject.get_hidden_inputs(response)[1].length).to eq(2) + end + + it 'returns an empty string for the input_2 hidden input from the second element' do + expect(subject.get_hidden_inputs(response)[1]['input_2']).to be_empty + end + end + end + end From 3fc25a00d84bbf5d82d039fc77d8088049b6ea99 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Thu, 9 Apr 2015 01:09:00 -0500 Subject: [PATCH 2/4] Make sure we are only grabbing hidden inputs --- lib/metasploit/framework/login_scanner/http.rb | 3 +++ spec/lib/metasploit/framework/login_scanner/http_spec.rb | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index b35266b052..185536833e 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -257,6 +257,9 @@ module Metasploit noko.search("form").each_entry do |form| found_inputs = {} form.search("input").each_entry do |input| + input_type = input.attributes['type'] ? input.attributes['type'].value : '' + next if input_type !~ /hidden/i + input_name = input.attributes['name'] ? input.attributes['name'].value : '' input_value = input.attributes['value'] ? input.attributes['value'].value : '' found_inputs[input_name] = input_value unless input_name.empty? diff --git a/spec/lib/metasploit/framework/login_scanner/http_spec.rb b/spec/lib/metasploit/framework/login_scanner/http_spec.rb index 75ebe37d7d..c4c4ecad7e 100644 --- a/spec/lib/metasploit/framework/login_scanner/http_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/http_spec.rb @@ -41,6 +41,7 @@ describe Metasploit::Framework::LoginScanner::HTTP do
+
From 3493d25ff9e4a64ab4b4c5f5b4b9a3cd81fb577c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 16 Apr 2015 21:07:23 -0500 Subject: [PATCH 3/4] Move all this to Rex --- .../framework/login_scanner/http.rb | 29 --------- lib/rex/proto/http/response.rb | 28 ++++++++ .../framework/login_scanner/http_spec.rb | 48 -------------- spec/lib/rex/proto/http/response_spec.rb | 65 +++++++++++++++++++ 4 files changed, 93 insertions(+), 77 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index 185536833e..f825ebc94b 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -242,35 +242,6 @@ module Metasploit end - # Returns a collection of found hidden inputs - # - # @param res [Rex::Proto::Http::Response] A response object that contains a body - # @return [Array] An array, each element represents a form that contains a hash of found hidden inputs - # * 'name' [String] The hidden input's original name. The value is the hidden input's original value. - # @example - # res = send_request('uri'=>'/') - # inputs = get_hidden_inputs(res) - # session_id = inputs[0]['sessionid'] # The first form's 'sessionid' hidden input - def get_hidden_inputs(res) - forms = [] - noko = Nokogiri::HTML(res.body) - noko.search("form").each_entry do |form| - found_inputs = {} - form.search("input").each_entry do |input| - input_type = input.attributes['type'] ? input.attributes['type'].value : '' - next if input_type !~ /hidden/i - - input_name = input.attributes['name'] ? input.attributes['name'].value : '' - input_value = input.attributes['value'] ? input.attributes['value'].value : '' - found_inputs[input_name] = input_value unless input_name.empty? - end - forms << found_inputs unless found_inputs.empty? - end - - forms - end - - # Attempt a single login with a single credential against the target. # # @param credential [Credential] The credential object to attempt to diff --git a/lib/rex/proto/http/response.rb b/lib/rex/proto/http/response.rb index 1a08d13264..79913196d0 100644 --- a/lib/rex/proto/http/response.rb +++ b/lib/rex/proto/http/response.rb @@ -82,6 +82,34 @@ class Response < Packet return cookies.strip end + + # Returns a collection of found hidden inputs + # + # @return [Array] An array, each element represents a form that contains a hash of found hidden inputs + # * 'name' [String] The hidden input's original name. The value is the hidden input's original value. + # @example + # res = send_request_cgi('uri'=>'/') + # inputs = res.get_hidden_inputs + # session_id = inputs[0]['sessionid'] # The first form's 'sessionid' hidden input + def get_hidden_inputs + forms = [] + noko = Nokogiri::HTML(self.body) + noko.search("form").each_entry do |form| + found_inputs = {} + form.search("input").each_entry do |input| + input_type = input.attributes['type'] ? input.attributes['type'].value : '' + next if input_type !~ /hidden/i + + input_name = input.attributes['name'] ? input.attributes['name'].value : '' + input_value = input.attributes['value'] ? input.attributes['value'].value : '' + found_inputs[input_name] = input_value unless input_name.empty? + end + forms << found_inputs unless found_inputs.empty? + end + + forms + end + # # Updates the various parts of the HTTP response command string. # diff --git a/spec/lib/metasploit/framework/login_scanner/http_spec.rb b/spec/lib/metasploit/framework/login_scanner/http_spec.rb index c4c4ecad7e..5f26ff7271 100644 --- a/spec/lib/metasploit/framework/login_scanner/http_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/http_spec.rb @@ -30,52 +30,4 @@ describe Metasploit::Framework::LoginScanner::HTTP do end end - describe '#get_hidden_inputs' do - let(:response) do - res = Rex::Proto::Http::Response.new(200, 'OK') - res.body = %Q| - - - -
- -
-
- - - -
- - - - | - res - end - - - context 'when an HTML page contains two forms containing hidden inputs' do - it 'returns an array' do - expect(subject.get_hidden_inputs(response)).to be_kind_of(Array) - end - - it 'returns hashes in the array' do - subject.get_hidden_inputs(response).each do |form| - expect(form).to be_kind_of(Hash) - end - end - - it 'returns \'some_value_1\' in the input_1 hidden input from the first element' do - expect(subject.get_hidden_inputs(response)[0]['input_1']).to eq('some_value_1') - end - - it 'returns two hidden inputs in the second element' do - expect(subject.get_hidden_inputs(response)[1].length).to eq(2) - end - - it 'returns an empty string for the input_2 hidden input from the second element' do - expect(subject.get_hidden_inputs(response)[1]['input_2']).to be_empty - end - end - end - end diff --git a/spec/lib/rex/proto/http/response_spec.rb b/spec/lib/rex/proto/http/response_spec.rb index 67c23c9588..d5f332ca91 100644 --- a/spec/lib/rex/proto/http/response_spec.rb +++ b/spec/lib/rex/proto/http/response_spec.rb @@ -141,6 +141,71 @@ describe Rex::Proto::Http::Response do cookies.split(';').map(&:strip) end + + describe '#get_hidden_inputs' do + let(:response) do + res = Rex::Proto::Http::Response.new(200, 'OK') + res.body = %Q| + + + +
+ +
+
+ + + +
+ + + + | + res + end + + subject do + cli = Rex::Proto::Http::Client.new('127.0.0.1') + cli.connect + req = cli.request_cgi({'uri'=>'/'}) + res = cli.send_recv(req) + res + end + + before(:each) do + allow_any_instance_of(Rex::Proto::Http::Client).to receive(:request_cgi).with(any_args) + allow_any_instance_of(Rex::Proto::Http::Client).to receive(:send_recv).with(any_args).and_return(response) + allow_any_instance_of(Rex::Proto::Http::Client).to receive(:set_config).with(any_args) + allow_any_instance_of(Rex::Proto::Http::Client).to receive(:close) + allow_any_instance_of(Rex::Proto::Http::Client).to receive(:connect) + end + + context 'when an HTML page contains two forms containing hidden inputs' do + it 'returns an array' do + expect(subject.get_hidden_inputs).to be_kind_of(Array) + end + + it 'returns hashes in the array' do + subject.get_hidden_inputs.each do |form| + expect(form).to be_kind_of(Hash) + end + end + + it 'returns \'some_value_1\' in the input_1 hidden input from the first element' do + expect(subject.get_hidden_inputs[0]['input_1']).to eq('some_value_1') + end + + it 'returns two hidden inputs in the second element' do + expect(subject.get_hidden_inputs[1].length).to eq(2) + end + + it 'returns an empty string for the input_2 hidden input from the second element' do + expect(subject.get_hidden_inputs[1]['input_2']).to be_empty + end + end + end + + context "#get_cookies" do it 'returns empty string for no Set-Cookies' do From f280e5191b0af007962a083b0228f440800aa138 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 16 Apr 2015 21:11:09 -0500 Subject: [PATCH 4/4] I forgot to move this require statement --- lib/metasploit/framework/login_scanner/http.rb | 1 - lib/rex/proto/http/response.rb | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index f825ebc94b..fda5c5d0c7 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -1,7 +1,6 @@ require 'rex/proto/http' require 'metasploit/framework/login_scanner/base' require 'metasploit/framework/login_scanner/rex_socket' -require 'nokogiri' module Metasploit module Framework diff --git a/lib/rex/proto/http/response.rb b/lib/rex/proto/http/response.rb index 79913196d0..406d670fc9 100644 --- a/lib/rex/proto/http/response.rb +++ b/lib/rex/proto/http/response.rb @@ -1,6 +1,7 @@ # -*- coding: binary -*- require 'uri' require 'rex/proto/http' +require 'nokogiri' module Rex module Proto