diff --git a/lib/msf/core/exploit/local/saltstack.rb b/lib/msf/core/exploit/local/saltstack.rb new file mode 100644 index 000000000000..e02eb8278876 --- /dev/null +++ b/lib/msf/core/exploit/local/saltstack.rb @@ -0,0 +1,27 @@ +require 'yaml' + +module Msf + module Exploit::Local::Saltstack + def list_minions(salt_key_exe='salt-key') + # pull minions from a master, returns hash of lists of the output + print_status('Attempting to list minions') + unless command_exists?(salt_key_exe) + print_error('salt-key not present on system') + return + end + + begin + out = cmd_exec(salt_key_exe, '-L --output=yaml', datastore['TIMEOUT']) + vprint_status(out) + minions = YAML.safe_load(out) + rescue Psych::SyntaxError + print_error('Unable to load salt-key -L data') + return + end + + store_path = store_loot('saltstack_minions', 'application/x-yaml', session, minions.to_yaml, 'minions.yaml', 'SaltStack Salt salt-key list') + print_good("#{peer} - minion file successfully retrieved and saved to #{store_path}") + minions + end + end +end \ No newline at end of file diff --git a/modules/exploits/linux/local/saltstack_salt_minion_deployer.rb b/modules/exploits/linux/local/saltstack_salt_minion_deployer.rb index f6be6cd2be73..451c8c0f2088 100644 --- a/modules/exploits/linux/local/saltstack_salt_minion_deployer.rb +++ b/modules/exploits/linux/local/saltstack_salt_minion_deployer.rb @@ -9,6 +9,7 @@ class MetasploitModule < Msf::Exploit::Local include Msf::Post::File include Msf::Exploit::EXE include Msf::Exploit::FileDropper + include Msf::Exploit::Local::Saltstack prepend Msf::Exploit::Remote::AutoCheck @@ -58,7 +59,7 @@ def initialize(info = {}) def salt_master return @salt if @salt - ['/usr/bin/salt-master', datastore['SALT']].each do |exec| + [datastore['SALT'], '/usr/bin/salt-master'].each do |exec| next unless executable?(exec) @salt = exec @@ -66,23 +67,9 @@ def salt_master @salt end - # taken from saltstack_salt.rb module - def list_minions - # pull minions from a master - print_status('Attempting to list minions') - unless command_exists?('salt-key') - print_error('salt-key not present on system') - return - end - - begin - out = cmd_exec('salt-key', '-L --output=yaml', datastore['TIMEOUT']) - vprint_status(out) - minions = YAML.safe_load(out) - rescue Psych::SyntaxError - print_error('Unable to load salt-key -L data') - return - end + def list_minions_printer + minions = list_minions + return if minions.nil? tbl = Rex::Text::Table.new( 'Header' => 'Minions List', @@ -90,8 +77,6 @@ def list_minions 'Columns' => ['Status', 'Minion Name'] ) - store_path = store_loot('saltstack_minions', 'application/x-yaml', session, minions.to_yaml, 'minions.yaml', 'SaltStack Salt salt-key list') - print_good("#{peer} - minion file successfully retrieved and saved to #{store_path}") count = 0 minions['minions'].each do |minion| tbl << ['Accepted', minion] @@ -114,7 +99,7 @@ def check def exploit # Make sure we can write our exploit and payload to the local system fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable" unless writable? datastore['WritableDir'] - list_minions if datastore['CALCULATE'] + list_minions_printer if datastore['CALCULATE'] payload_name = rand_text_alphanumeric(5..10) diff --git a/modules/post/multi/gather/saltstack_salt.rb b/modules/post/multi/gather/saltstack_salt.rb index 92ae318f81a0..9fb4f4c06960 100644 --- a/modules/post/multi/gather/saltstack_salt.rb +++ b/modules/post/multi/gather/saltstack_salt.rb @@ -7,6 +7,7 @@ class MetasploitModule < Msf::Post include Msf::Post::File + include Msf::Exploit::Local::Saltstack def initialize(info = {}) super( @@ -138,21 +139,9 @@ def gather_minion_data end end - def list_minions - # pull minions from a master - print_status('Attempting to list minions') - unless command_exists?('salt-key') - print_error('salt-key not present on system') - return - end - begin - out = cmd_exec('salt-key', '-L --output=yaml', datastore['TIMEOUT']) - vprint_status(out) - minions = YAML.safe_load(out) - rescue Psych::SyntaxError - print_error('Unable to load salt-key -L data') - return - end + def list_minions_printer + minions = list_minions + return if minions.nil? tbl = Rex::Text::Table.new( 'Header' => 'Minions List', @@ -160,9 +149,7 @@ def list_minions 'Columns' => ['Status', 'Minion Name'] ) - store_path = store_loot('saltstack_minions', 'application/x-yaml', session, minions.to_yaml, 'minions.yaml', 'SaltStack Salt salt-key list') - print_good("#{peer} - minion file successfully retrieved and saved to #{store_path}") - minions['minions'].each do |minion| + minions.each do |minion| tbl << ['Accepted', minion] end minions['minions_pre'].each do |minion| @@ -198,7 +185,7 @@ def minion end def master - list_minions + list_minions_printer gather_minion_data if datastore['GETOS'] || datastore['GETHOSTNAME'] || datastore['GETIP'] # get sls files