From b1c633faf66529011cc88d81b332c3ca897e5b14 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 21 Aug 2018 21:27:58 -0500 Subject: [PATCH 1/5] Add Group Policy Preferences support to db_import And take the Jaden Smith approach, as @busterb quipped to me. :) This one's a little weird, since you normally import scans into Metasploit, but now that creds are first-class in the database, it makes more sense to be able to import them. Currently, your alternatives are post/windows/gather/credentials/gpp, which requires a session, and auxiliary/scanner/smb/smb_enum_gpp, which requires a network scan. --- lib/msf/core/db_manager/import.rb | 6 ++++ lib/msf/core/db_manager/import/gpp.rb | 36 +++++++++++++++++++ lib/msf/core/rpc/v10/rpc_db.rb | 1 + lib/msf/ui/console/command_dispatcher/db.rb | 1 + .../ui/console/command_dispatcher/db_spec.rb | 1 + .../shared/examples/msf/db_manager/import.rb | 3 +- .../examples/msf/db_manager/import/gpp.rb | 3 ++ 7 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 lib/msf/core/db_manager/import/gpp.rb create mode 100644 spec/support/shared/examples/msf/db_manager/import/gpp.rb diff --git a/lib/msf/core/db_manager/import.rb b/lib/msf/core/db_manager/import.rb index 61702f442d..3778a58788 100644 --- a/lib/msf/core/db_manager/import.rb +++ b/lib/msf/core/db_manager/import.rb @@ -21,6 +21,7 @@ module Msf::DBManager::Import autoload :CI, 'msf/core/db_manager/import/ci' autoload :Foundstone, 'msf/core/db_manager/import/foundstone' autoload :FusionVM, 'msf/core/db_manager/import/fusion_vm' + autoload :GPP, 'msf/core/db_manager/import/gpp' autoload :IP360, 'msf/core/db_manager/import/ip360' autoload :IPList, 'msf/core/db_manager/import/ip_list' autoload :Libpcap, 'msf/core/db_manager/import/libpcap' @@ -47,6 +48,7 @@ module Msf::DBManager::Import include Msf::DBManager::Import::CI include Msf::DBManager::Import::Foundstone include Msf::DBManager::Import::FusionVM + include Msf::DBManager::Import::GPP include Msf::DBManager::Import::IP360 include Msf::DBManager::Import::IPList include Msf::DBManager::Import::Libpcap @@ -164,6 +166,7 @@ module Msf::DBManager::Import # :ci_xml # :foundstone_xml # :fusionvm_xml + # :gpp_xml # :ip360_aspl_xml # :ip360_xml_v3 # :ip_list @@ -358,6 +361,9 @@ module Msf::DBManager::Import when "main" @import_filedata[:type] = "Outpost24 XML" return :outpost24_xml + when "Groups" + @import_filedata[:type] = "Group Policy Preferences" + return :gpp_xml else # Give up if we haven't hit the root tag in the first few lines break if line_count > 10 diff --git a/lib/msf/core/db_manager/import/gpp.rb b/lib/msf/core/db_manager/import/gpp.rb new file mode 100644 index 0000000000..ebd68a48e2 --- /dev/null +++ b/lib/msf/core/db_manager/import/gpp.rb @@ -0,0 +1,36 @@ +require 'rex/parser/group_policy_preferences' + +module Msf::DBManager::Import::GPP + def import_gpp_xml(args = {}, &block) + return unless args && args[:data] && !args[:data].empty? + + gpp = Rex::Parser::GPP.parse(args[:data]) + + return unless gpp && gpp.any? + + wspace = find_workspace(args[:workspace]) + + return unless wspace && wspace.respond_to?(:id) + + gpp.each do |p| + create_credential( + workspace_id: wspace.id, + origin_type: :import, + filename: args[:filename], + username: p[:USER], + private_data: p[:PASS], + private_type: :password + ) + end + + report_loot( + workspace: wspace, + path: args[:filename], + name: File.basename(args[:filename]), + data: args[:data], + type: 'microsoft.windows.gpp', + ctype: 'text/xml', + info: gpp + ) + end +end diff --git a/lib/msf/core/rpc/v10/rpc_db.rb b/lib/msf/core/rpc/v10/rpc_db.rb index db88cc0a73..fc6d900424 100644 --- a/lib/msf/core/rpc/v10/rpc_db.rb +++ b/lib/msf/core/rpc/v10/rpc_db.rb @@ -1493,6 +1493,7 @@ public # * :ci_xml # * :foundstone_xml # * :fusionvm_xml + # * :gpp_xml # * :ip360_aspl_xml # * :ip360_xml_v3 # * :ip_list diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index cdb2458e7a..4177e82d32 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -1428,6 +1428,7 @@ class Db print_line " CI" print_line " Foundstone" print_line " FusionVM XML" + print_line " Group Policy Preferences" print_line " IP Address List" print_line " IP360 ASPL" print_line " IP360 XML v3" diff --git a/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb b/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb index 11f413805e..f26b8f3660 100644 --- a/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb +++ b/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb @@ -84,6 +84,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do " CI", " Foundstone", " FusionVM XML", + " Group Policy Preferences", " IP Address List", " IP360 ASPL", " IP360 XML v3", diff --git a/spec/support/shared/examples/msf/db_manager/import.rb b/spec/support/shared/examples/msf/db_manager/import.rb index cbff4ad158..872b4d8667 100644 --- a/spec/support/shared/examples/msf/db_manager/import.rb +++ b/spec/support/shared/examples/msf/db_manager/import.rb @@ -21,6 +21,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import' do it_should_behave_like 'Msf::DBManager::Import::CI' it_should_behave_like 'Msf::DBManager::Import::Foundstone' it_should_behave_like 'Msf::DBManager::Import::FusionVM' + it_should_behave_like 'Msf::DBManager::Import::GPP' it_should_behave_like 'Msf::DBManager::Import::IP360' it_should_behave_like 'Msf::DBManager::Import::IPList' it_should_behave_like 'Msf::DBManager::Import::Libpcap' @@ -38,4 +39,4 @@ RSpec.shared_examples_for 'Msf::DBManager::Import' do it_should_behave_like 'Msf::DBManager::Import::Retina' it_should_behave_like 'Msf::DBManager::Import::Spiceworks' it_should_behave_like 'Msf::DBManager::Import::Wapiti' -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/db_manager/import/gpp.rb b/spec/support/shared/examples/msf/db_manager/import/gpp.rb new file mode 100644 index 0000000000..0d1ab1c373 --- /dev/null +++ b/spec/support/shared/examples/msf/db_manager/import/gpp.rb @@ -0,0 +1,3 @@ +RSpec.shared_examples_for 'Msf::DBManager::Import::GPP' do + it { is_expected.to respond_to :import_gpp_xml } +end From 6fa04950ee85b5813b28b9f6b12b30efdedb4e7f Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 22 Aug 2018 14:19:50 -0500 Subject: [PATCH 2/5] Store parsed GPP data as a note And refactor slightly. --- lib/msf/core/db_manager/import/gpp.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/import/gpp.rb b/lib/msf/core/db_manager/import/gpp.rb index ebd68a48e2..7cd5bd2bf6 100644 --- a/lib/msf/core/db_manager/import/gpp.rb +++ b/lib/msf/core/db_manager/import/gpp.rb @@ -13,6 +13,17 @@ module Msf::DBManager::Import::GPP return unless wspace && wspace.respond_to?(:id) gpp.each do |p| + # Store parsed data as a note + report_note( + workspace: wspace, + type: 'Group Policy Preferences', + data: gpp + ) + + # Skip incomplete creds + next unless p[:USER] && p[:PASS] + + # Store decrypted creds create_credential( workspace_id: wspace.id, origin_type: :import, @@ -23,6 +34,7 @@ module Msf::DBManager::Import::GPP ) end + # Store entire file as loot report_loot( workspace: wspace, path: args[:filename], @@ -30,7 +42,7 @@ module Msf::DBManager::Import::GPP data: args[:data], type: 'microsoft.windows.gpp', ctype: 'text/xml', - info: gpp + info: 'Group Policy Preferences' ) end end From 1e4eb0eae0d9d0e4dcac4f7b9db7d7a65885a99d Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 22 Aug 2018 14:34:09 -0500 Subject: [PATCH 3/5] Revert report_note, since it added nothing A bit of misunderstanding. We're in agreement that loot was enough. --- lib/msf/core/db_manager/import/gpp.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/msf/core/db_manager/import/gpp.rb b/lib/msf/core/db_manager/import/gpp.rb index 7cd5bd2bf6..c810fcf2c5 100644 --- a/lib/msf/core/db_manager/import/gpp.rb +++ b/lib/msf/core/db_manager/import/gpp.rb @@ -13,13 +13,6 @@ module Msf::DBManager::Import::GPP return unless wspace && wspace.respond_to?(:id) gpp.each do |p| - # Store parsed data as a note - report_note( - workspace: wspace, - type: 'Group Policy Preferences', - data: gpp - ) - # Skip incomplete creds next unless p[:USER] && p[:PASS] @@ -34,7 +27,7 @@ module Msf::DBManager::Import::GPP ) end - # Store entire file as loot + # Store entire file as loot, including metadata report_loot( workspace: wspace, path: args[:filename], @@ -42,7 +35,7 @@ module Msf::DBManager::Import::GPP data: args[:data], type: 'microsoft.windows.gpp', ctype: 'text/xml', - info: 'Group Policy Preferences' + info: gpp ) end end From 289125554924d2d2c95646690ee68d2d3a79f4a1 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 22 Aug 2018 15:50:38 -0500 Subject: [PATCH 4/5] Clarify what is being imported currently Since the parser is focused on creds. --- lib/msf/core/db_manager/import.rb | 2 +- lib/msf/ui/console/command_dispatcher/db.rb | 2 +- spec/lib/msf/ui/console/command_dispatcher/db_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/db_manager/import.rb b/lib/msf/core/db_manager/import.rb index 3778a58788..cf9e4c11d5 100644 --- a/lib/msf/core/db_manager/import.rb +++ b/lib/msf/core/db_manager/import.rb @@ -362,7 +362,7 @@ module Msf::DBManager::Import @import_filedata[:type] = "Outpost24 XML" return :outpost24_xml when "Groups" - @import_filedata[:type] = "Group Policy Preferences" + @import_filedata[:type] = "Group Policy Preferences Credentials" return :gpp_xml else # Give up if we haven't hit the root tag in the first few lines diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index 4177e82d32..9b66d56b5d 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -1428,7 +1428,7 @@ class Db print_line " CI" print_line " Foundstone" print_line " FusionVM XML" - print_line " Group Policy Preferences" + print_line " Group Policy Preferences Credentials" print_line " IP Address List" print_line " IP360 ASPL" print_line " IP360 XML v3" diff --git a/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb b/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb index f26b8f3660..d216e410b7 100644 --- a/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb +++ b/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb @@ -84,7 +84,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do " CI", " Foundstone", " FusionVM XML", - " Group Policy Preferences", + " Group Policy Preferences Credentials", " IP Address List", " IP360 ASPL", " IP360 XML v3", From 9b3e0d83064f5ba6e6f08ef990d899c4113f4e24 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 22 Aug 2018 16:25:57 -0500 Subject: [PATCH 5/5] Add additional root tags for GPP XML Finally ran through all the samples and cross-referenced with MS14-025. https://msdn.microsoft.com/en-us/library/cc232650.aspx https://support.microsoft.com/en-us/help/2962486/ms14-025-vulnerability-in-group-policy-preferences-could-allow-elevati --- lib/msf/core/db_manager/import.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/import.rb b/lib/msf/core/db_manager/import.rb index cf9e4c11d5..b7aef3225a 100644 --- a/lib/msf/core/db_manager/import.rb +++ b/lib/msf/core/db_manager/import.rb @@ -361,7 +361,7 @@ module Msf::DBManager::Import when "main" @import_filedata[:type] = "Outpost24 XML" return :outpost24_xml - when "Groups" + when /Groups|DataSources|Drives|ScheduledTasks|NTServices/ @import_filedata[:type] = "Group Policy Preferences Credentials" return :gpp_xml else