Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Powershell payload options to be set to false #11778

Merged
merged 1 commit into from Apr 26, 2019

Conversation

Projects
None yet
3 participants
@space-r7
Copy link
Contributor

commented Apr 25, 2019

Referencing #11693, Powershell payload options that default to true cannot be set to false. This change allows those options to be set to false.

Verification

  • Find a module that makes use of the cmd_psh_payload function in lib/msf/core/exploit/powershell.rb
  • Set a Powershell payload option that is true by default to false
  • Verify said option was actually set to false

I copied Pearce's method in #11660 and used pry to verify the option values before and after the call to cmd_psh_payload.

Scenarios

Testing exploit/windows/http/octopusdeploy_deploy

Before change:

msf5 exploit(windows/http/octopusdeploy_deploy) > run

[*] Started reverse TCP handler on 192.168.37.1:4444 

From: /Users/space/metasploit-framework/modules/exploits/windows/http/octopusdeploy_deploy.rb @ line 84 Msf::Modules::Exploit__Windows__Http__Octopusdeploy_deploy::MetasploitModule#exploit:

    79:     CheckCode::Appears
    80:   end
    81: 
    82:   def exploit
    83:     require 'pry'
 => 84:     binding.pry
    85:     # Generate the powershell payload
    86:     command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, wrap_double_quotes: true)
    87:     step_name = datastore['STEPNAME'] || rand_text_alphanumeric(4 + rand(32 - 4))
    88:     session = create_octopus_session unless datastore['APIKEY']
    89: 

[1] pry(#<Msf::Modules::Exploit__Windows__Http__Octopusdeploy_deploy::MetasploitModule>)> command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, wrap_double_quotes: false)


From: /Users/space/metasploit-framework/lib/msf/core/exploit/powershell.rb @ line 230 Msf::Exploit::Powershell#cmd_psh_payload:

    224: def cmd_psh_payload(pay, payload_arch, opts = {})
    225:   %i[persist prepend_sleep exec_in_place encode_final_payload encode_inner_payload
    226:   remove_comspec noninteractive wrap_double_quotes no_equals method].map do |opt|
    227:     opts[opt] ||= datastore["Powershell::#{opt}"]
    228:   end
    229:   require 'pry'
 => 230:   binding.pry
    231: 
    232:   unless opts.key? :shorten
    233:     opts[:shorten] = (datastore['Powershell::method'] != 'old')
    234:   end
    235: 
    236:   template_path = Rex::Powershell::Templates::TEMPLATE_DIR
    237:   command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, template_path, opts)
    238:   vprint_status("Powershell command length: #{command.length}")
    239: 
    240:   command
    241: end

[1] pry(#<Msf::Modules::Exploit__Windows__Http__Octopusdeploy_deploy::MetasploitModule>)> p opts
{:remove_comspec=>true, :wrap_double_quotes=>true, :persist=>false, :prepend_sleep=>nil, :exec_in_place=>false, :encode_final_payload=>false, :encode_inner_payload=>false, :noninteractive=>true, :no_equals=>false, :method=>"reflection"}
=> {:remove_comspec=>true,
 :wrap_double_quotes=>true,
 :persist=>false,
 :prepend_sleep=>nil,
 :exec_in_place=>false,
 :encode_final_payload=>false,
 :encode_inner_payload=>false,
 :noninteractive=>true,
 :no_equals=>false,
 :method=>"reflection"}

After change:

msf5 exploit(windows/http/octopusdeploy_deploy) > run

[*] Started reverse TCP handler on 192.168.37.1:4444 

From: /Users/space/metasploit-framework/modules/exploits/windows/http/octopusdeploy_deploy.rb @ line 84 Msf::Modules::Exploit__Windows__Http__Octopusdeploy_deploy::MetasploitModule#exploit:

    79:     CheckCode::Appears
    80:   end
    81: 
    82:   def exploit
    83:     require 'pry'
 => 84:     binding.pry
    85:     # Generate the powershell payload
    86:     command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, wrap_double_quotes: true)
    87:     step_name = datastore['STEPNAME'] || rand_text_alphanumeric(4 + rand(32 - 4))
    88:     session = create_octopus_session unless datastore['APIKEY']
    89: 

[1] pry(#<Msf::Modules::Exploit__Windows__Http__Octopusdeploy_deploy::MetasploitModule>)> command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, wrap_double_quotes: false)

From: /Users/space/metasploit-framework/lib/msf/core/exploit/powershell.rb @ line 230 Msf::Exploit::Powershell#cmd_psh_payload:

    224: def cmd_psh_payload(pay, payload_arch, opts = {})
    225:   %i[persist prepend_sleep exec_in_place encode_final_payload encode_inner_payload
    226:   remove_comspec noninteractive wrap_double_quotes no_equals method].map do |opt|
    227:     opts[opt] = opts[opt].nil? ? datastore["Powershell::#{opt}"] : opts[opt]
    228:   end
    229:   require 'pry'
 => 230:   binding.pry
    231: 
    232:   unless opts.key? :shorten
    233:     opts[:shorten] = (datastore['Powershell::method'] != 'old')
    234:   end
    235: 
    236:   template_path = Rex::Powershell::Templates::TEMPLATE_DIR
    237:   command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, template_path, opts)
    238:   vprint_status("Powershell command length: #{command.length}")
    239: 
    240:   command
    241: end

[1] pry(#<Msf::Modules::Exploit__Windows__Http__Octopusdeploy_deploy::MetasploitModule>)> p opts
{:remove_comspec=>true, :wrap_double_quotes=>false, :persist=>false, :prepend_sleep=>nil, :exec_in_place=>false, :encode_final_payload=>false, :encode_inner_payload=>false, :noninteractive=>true, :no_equals=>false, :method=>"reflection"}
=> {:remove_comspec=>true,
 :wrap_double_quotes=>false,
 :persist=>false,
 :prepend_sleep=>nil,
 :exec_in_place=>false,
 :encode_final_payload=>false,
 :encode_inner_payload=>false,
 :noninteractive=>true,
 :no_equals=>false,
 :method=>"reflection"}

Testing exploit/multi/fileformat/libreoffice_macro_exec

Before change:

msf5 exploit(multi/fileformat/libreoffice_macro_exec) > run

From: /Users/space/metasploit-framework/modules/exploits/multi/fileformat/libreoffice_macro_exec.rb @ line 83 Msf::Modules::Exploit__Multi__Fileformat__Libreoffice_macro_exec::MetasploitModule#gen_windows_cmd:

    75: def gen_windows_cmd
    76:   opts =
    77:   {
    78:     :remove_comspec       =>  true,
    79:     :method               =>  'reflection',
    80:     :encode_final_payload =>  true
    81:   }
    82:   require 'pry'
 => 83:   binding.pry
    84:   @cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, opts)
    85:   @cmd << ' &amp;&amp; echo'
    86: end

[1] pry(#<Msf::Modules::Exploit__Multi__Fileformat__Libreoffice_macro_exec::MetasploitModule>)> @cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {:remove_comspec => true, :method => 'reflection', :encode_final_payload => true, :wrap_double_quotes => false, :noninteractive => false})

From: /Users/space/metasploit-framework/lib/msf/core/exploit/powershell.rb @ line 230 Msf::Exploit::Powershell#cmd_psh_payload:

    224: def cmd_psh_payload(pay, payload_arch, opts = {})
    225:   %i[persist prepend_sleep exec_in_place encode_final_payload encode_inner_payload
    226:   remove_comspec noninteractive wrap_double_quotes no_equals method].map do |opt|
    227:     opts[opt] ||= datastore["Powershell::#{opt}"]
    228:   end
    229:   require 'pry'
 => 230:   binding.pry
    231: 
    232:   unless opts.key? :shorten
    233:     opts[:shorten] = (datastore['Powershell::method'] != 'old')
    234:   end
    235: 
    236:   template_path = Rex::Powershell::Templates::TEMPLATE_DIR
    237:   command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, template_path, opts)
    238:   vprint_status("Powershell command length: #{command.length}")
    239: 
    240:   command
    241: end

[1] pry(#<Msf::Modules::Exploit__Multi__Fileformat__Libreoffice_macro_exec::MetasploitModule>)> p opts
{:remove_comspec=>true, :method=>"reflection", :encode_final_payload=>true, :wrap_double_quotes=>true, :noninteractive=>true, :persist=>false, :prepend_sleep=>nil, :exec_in_place=>false, :encode_inner_payload=>false, :no_equals=>false}
=> {:remove_comspec=>true,
 :method=>"reflection",
 :encode_final_payload=>true,
 :wrap_double_quotes=>true,
 :noninteractive=>true,
 :persist=>false,
 :prepend_sleep=>nil,
 :exec_in_place=>false,
 :encode_inner_payload=>false,
 :no_equals=>false}

After change:

msf5 exploit(multi/fileformat/libreoffice_macro_exec) > run

From: /Users/space/metasploit-framework/modules/exploits/multi/fileformat/libreoffice_macro_exec.rb @ line 83 Msf::Modules::Exploit__Multi__Fileformat__Libreoffice_macro_exec::MetasploitModule#gen_windows_cmd:

    75: def gen_windows_cmd
    76:   opts =
    77:   {
    78:     :remove_comspec       =>  true,
    79:     :method               =>  'reflection',
    80:     :encode_final_payload =>  true
    81:   }
    82:   require 'pry'
 => 83:   binding.pry
    84:   @cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, opts)
    85:   @cmd << ' &amp;&amp; echo'
    86: end

[1] pry(#<Msf::Modules::Exploit__Multi__Fileformat__Libreoffice_macro_exec::MetasploitModule>)> @cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {:remove_comspec => true, :method => 'reflection', :encode_final_payload => true, :wrap_double_quotes => false, :noninteractive => false})

From: /Users/space/metasploit-framework/lib/msf/core/exploit/powershell.rb @ line 230 Msf::Exploit::Powershell#cmd_psh_payload:

    224: def cmd_psh_payload(pay, payload_arch, opts = {})
    225:   %i[persist prepend_sleep exec_in_place encode_final_payload encode_inner_payload
    226:   remove_comspec noninteractive wrap_double_quotes no_equals method].map do |opt|
    227:     opts[opt] = opts[opt].nil? ? datastore["Powershell::#{opt}"] : opts[opt]
    228:   end
    229:   require 'pry'
 => 230:   binding.pry
    231: 
    232:   unless opts.key? :shorten
    233:     opts[:shorten] = (datastore['Powershell::method'] != 'old')
    234:   end
    235: 
    236:   template_path = Rex::Powershell::Templates::TEMPLATE_DIR
    237:   command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, template_path, opts)
    238:   vprint_status("Powershell command length: #{command.length}")
    239: 
    240:   command
    241: end

[1] pry(#<Msf::Modules::Exploit__Multi__Fileformat__Libreoffice_macro_exec::MetasploitModule>)> p opts
{:remove_comspec=>true, :method=>"reflection", :encode_final_payload=>true, :wrap_double_quotes=>false, :noninteractive=>false, :persist=>false, :prepend_sleep=>nil, :exec_in_place=>false, :encode_inner_payload=>false, :no_equals=>false}
=> {:remove_comspec=>true,
 :method=>"reflection",
 :encode_final_payload=>true,
 :wrap_double_quotes=>false,
 :noninteractive=>false,
 :persist=>false,
 :prepend_sleep=>nil,
 :exec_in_place=>false,
 :encode_inner_payload=>false,
 :no_equals=>false}

@wvu-r7 wvu-r7 self-assigned this Apr 26, 2019

@wvu-r7

This comment has been minimized.

Copy link
Contributor

commented Apr 26, 2019

wvu@kharak:/rapid7/metasploit-framework:HEAD$ rspec spec/modules/payloads_spec.rb
/Users/wvu/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activesupport-4.2.11.1/lib/active_support/core_ext/object/duplicable.rb:111: warning: BigDecimal.new is deprecated; use BigDecimal() method instead.
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}

Randomized with seed 60270
modules/payloads .........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Top 10 slowest examples (2.27 seconds, 8.7% of total time):
  modules/payloads windows/shell/reverse_ord_tcp it should behave like payload cached size is consistent windows/shell/reverse_ord_tcp can be instantiated
    0.83603 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:151
  modules/payloads android/meterpreter_reverse_http it should behave like payload cached size is consistent android/meterpreter_reverse_http can be instantiated
    0.22657 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:151
  modules/payloads windows/meterpreter/bind_tcp_rc4 it should behave like payload cached size is consistent windows/meterpreter/bind_tcp_rc4 has a valid cached_size
    0.22646 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:174
  modules/payloads android/meterpreter_reverse_tcp it should behave like payload cached size is consistent android/meterpreter_reverse_tcp can be instantiated
    0.17531 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:151
  modules/payloads android/meterpreter/reverse_http it should behave like payload cached size is consistent android/meterpreter/reverse_http is dynamic_size?
    0.13935 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:163
  modules/payloads android/meterpreter_reverse_http it should behave like payload cached size is consistent android/meterpreter_reverse_http is dynamic_size?
    0.13877 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:163
  modules/payloads android/meterpreter/reverse_https it should behave like payload cached size is consistent android/meterpreter/reverse_https is dynamic_size?
    0.13871 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:163
  modules/payloads android/meterpreter_reverse_https it should behave like payload cached size is consistent android/meterpreter_reverse_https can be instantiated
    0.13225 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:151
  modules/payloads android/shell/reverse_https it should behave like payload cached size is consistent android/shell/reverse_https is dynamic_size?
    0.12811 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:163
  modules/payloads windows/meterpreter/reverse_hop_http it should behave like payload cached size is consistent windows/meterpreter/reverse_hop_http has a valid cached_size
    0.12505 seconds ./spec/support/shared/examples/payload_cached_size_is_consistent.rb:174

Finished in 26.12 seconds (files took 6.97 seconds to load)
1753 examples, 0 failures

Randomized with seed 60270
Coverage report generated for RSpec to /rapid7/metasploit-framework/coverage. 5262 / 13686 LOC (38.45%) covered.
wvu@kharak:/rapid7/metasploit-framework:HEAD$

@wvu-r7 wvu-r7 merged commit a97cee4 into rapid7:master Apr 26, 2019

2 of 3 checks passed

continuous-integration/travis-ci/pr The Travis CI build failed
Details
Metasploit Automation - Sanity Test Execution Successfully completed all tests.
Details
Metasploit Automation - Test Execution Successfully completed all tests.
Details

wvu-r7 added a commit that referenced this pull request Apr 26, 2019

Land #11778, cmd_psh_payload options hash fix
nil and false are not equivalent here.

msjenkins-r7 added a commit that referenced this pull request Apr 26, 2019

Land #11778, cmd_psh_payload options hash fix
nil and false are not equivalent here.
@wvu-r7

This comment has been minimized.

Copy link
Contributor

commented Apr 26, 2019

Release Notes

This fixes a bug in cmd_psh_payload where a false value supplied to the options hash would be treated the same as a nil value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.