Skip to content

Commit 18d95b6

Browse files
committed
Land rapid7#8346, Templatize shims for external modules
2 parents b242fb0 + 42fd287 commit 18d95b6

File tree

5 files changed

+120
-80
lines changed

5 files changed

+120
-80
lines changed

lib/msf/core/module/external.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Msf::Module::External
2+
def wait_status(mod)
3+
while mod.running
4+
m = mod.get_status
5+
if m
6+
case m['level']
7+
when 'error'
8+
print_error m['message']
9+
when 'warning'
10+
print_warning m['message']
11+
when 'good'
12+
print_good m['message']
13+
when 'info'
14+
print_status m['message']
15+
when 'debug'
16+
vprint_status m['message']
17+
else
18+
print_status m['message']
19+
end
20+
end
21+
end
22+
end
23+
end

lib/msf/core/modules/external/shim.rb

Lines changed: 37 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -7,95 +7,53 @@ def self.generate(module_path)
77
mod = Msf::Modules::External::Bridge.open(module_path)
88
return '' unless mod.meta
99
case mod.meta['type']
10-
when 'remote_exploit.cmd_stager.wget'
10+
when 'remote_exploit_cmd_stager'
1111
remote_exploit_cmd_stager(mod)
1212
end
1313
end
1414

15-
def self.remote_exploit_cmd_stager(mod)
16-
%Q|
17-
require 'msf/core/modules/external/bridge'
18-
19-
class MetasploitModule < Msf::Exploit::Remote
20-
Rank = ExcellentRanking
21-
22-
include Msf::Exploit::CmdStager
23-
24-
def initialize(info = {})
25-
super(update_info(info,
26-
'Name' => #{mod.meta['name'].dump},
27-
'Description' => #{mod.meta['description'].dump},
28-
'Author' =>
29-
[
30-
#{mod.meta['authors'].map(&:dump).join(', ')}
31-
],
32-
'License' => MSF_LICENSE,
33-
'References' =>
34-
[
35-
#{mod.meta['references'].map do |r|
36-
"[#{r['type'].upcase.dump}, #{r['ref'].dump}]"
37-
end.join(', ')}
38-
],
39-
'DisclosureDate' => #{mod.meta['date'].dump},
40-
'Privileged' => #{mod.meta['privileged'].inspect},
41-
'Platform' => [#{mod.meta['targets'].map{|t| t['platform'].dump}.uniq.join(', ')}],
42-
'Payload' =>
43-
{
44-
'DisableNops' => true
45-
},
46-
'Targets' =>
47-
[
48-
#{mod.meta['targets'].map do |t|
49-
%Q^[#{t['platform'].dump} + ' ' + #{t['arch'].dump},
50-
{'Arch' => ARCH_#{t['arch'].upcase}, 'Platform' => #{t['platform'].dump} }]^
51-
end.join(', ')}
52-
],
53-
'DefaultTarget' => 0,
54-
'DefaultOptions' => { 'WfsDelay' => 5 }
55-
))
56-
57-
register_options([
58-
#{mod.meta['options'].map do |n, o|
59-
"Opt#{o['type'].capitalize}.new(#{n.dump},
60-
[#{o['required']}, #{o['description'].dump}, #{o['default'].inspect}])"
61-
end.join(', ')}
62-
], self.class)
15+
def self.render_template(name, meta = {})
16+
template = File.join(File.dirname(__FILE__), 'templates', name)
17+
ERB.new(File.read(template)).result(binding)
6318
end
6419

65-
def execute_command(cmd, opts)
66-
mod = Msf::Modules::External::Bridge.open(#{mod.path.dump})
67-
mod.run(datastore.merge(command: cmd))
68-
wait_status(mod)
69-
true
20+
def self.common_metadata(meta = {})
21+
render_template('common_metadata.erb', meta)
7022
end
7123

72-
def exploit
73-
print_status("Exploiting...")
74-
execute_cmdstager({:flavor => :wget})
24+
def self.mod_meta_common(mod, meta = {})
25+
meta[:path] = mod.path.dump
26+
meta[:name] = mod.meta['name'].dump
27+
meta[:description] = mod.meta['description'].dump
28+
meta[:authors] = mod.meta['authors'].map(&:dump).join(",\n ")
29+
meta[:date] = mod.meta['date'].dump
30+
meta[:references] = mod.meta['references'].map do |r|
31+
"[#{r['type'].upcase.dump}, #{r['ref'].dump}]"
32+
end.join(",\n ")
33+
34+
meta[:options] = mod.meta['options'].map do |n, o|
35+
"Opt#{o['type'].capitalize}.new(#{n.dump},
36+
[#{o['required']}, #{o['description'].dump}, #{o['default'].inspect}])"
37+
end.join(",\n ")
38+
meta
7539
end
7640

77-
def wait_status(mod)
78-
while mod.running
79-
m = mod.get_status
80-
if m
81-
case m['level']
82-
when 'error'
83-
print_error m['message']
84-
when 'warning'
85-
print_warning m['message']
86-
when 'good'
87-
print_good m['message']
88-
when 'info'
89-
print_status m['message']
90-
when 'debug'
91-
vprint_status m['message']
92-
else
93-
print_status m['message']
94-
end
95-
end
96-
end
41+
def self.mod_meta_exploit(mod, meta = {})
42+
meta[:wfsdelay] = mod.meta['wfsdelay'] || 5
43+
meta[:privileged] = mod.meta['privileged'].inspect
44+
meta[:platform] = mod.meta['targets'].map do |t|
45+
t['platform'].dump
46+
end.uniq.join(",\n ")
47+
meta[:targets] = mod.meta['targets'].map do |t|
48+
"[#{t['platform'].dump} + ' ' + #{t['arch'].dump}, {'Arch' => ARCH_#{t['arch'].upcase}, 'Platform' => #{t['platform'].dump} }]"
49+
end.join(",\n ")
50+
meta
9751
end
98-
end
99-
|
52+
53+
def self.remote_exploit_cmd_stager(mod)
54+
meta = mod_meta_common(mod)
55+
meta = mod_meta_exploit(mod, meta)
56+
meta[:command_stager_flavor] = mod.meta['payload']['command_stager_flavor'].dump
57+
render_template('remote_exploit_cmd_stager.erb', meta)
10058
end
10159
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'Name' => <%= meta[:name] %>,
2+
'Description' => <%= meta[:description] %>,
3+
'Author' =>
4+
[
5+
<%= meta[:authors] %>
6+
],
7+
'License' => MSF_LICENSE,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
require 'msf/core/modules/external/bridge'
2+
require 'msf/core/module/external'
3+
4+
class MetasploitModule < Msf::Exploit::Remote
5+
Rank = ExcellentRanking
6+
7+
include Msf::Module::External
8+
include Msf::Exploit::CmdStager
9+
10+
def initialize(info = {})
11+
super(update_info(info,
12+
<%= common_metadata meta %>
13+
'References' =>
14+
[
15+
<%= meta[:references] %>
16+
],
17+
'DisclosureDate' => <%= meta[:date] %>,
18+
'Privileged' => <%= meta[:privileged] %>,
19+
'Platform' => [<%= meta[:platform] %>],
20+
'Payload' =>
21+
{
22+
'DisableNops' => true
23+
},
24+
'Targets' =>
25+
[
26+
<%= meta[:targets] %>
27+
],
28+
'DefaultTarget' => 0,
29+
'DefaultOptions' => { 'WfsDelay' => <%= meta[:wfsdelay] %> }
30+
))
31+
32+
register_options([
33+
<%= meta[:options] %>
34+
])
35+
end
36+
37+
def execute_command(cmd, opts)
38+
mod = Msf::Modules::External::Bridge.open(<%= meta[:path] %>)
39+
mod.run(datastore.merge(command: cmd))
40+
wait_status(mod)
41+
true
42+
end
43+
44+
def exploit
45+
print_status("Exploiting...")
46+
execute_cmdstager({:flavor => :<%= meta[:command_stager_flavor] %>})
47+
end
48+
end

modules/exploits/linux/smtp/haraka.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@
3434
{'type': 'edb', 'ref': '41162'},
3535
{'type': 'url', 'ref': 'https://github.com/haraka/Haraka/pull/1606'},
3636
],
37-
'type': 'remote_exploit.cmd_stager.wget',
37+
'type': 'remote_exploit_cmd_stager',
38+
'wfsdelay': 5,
3839
'privileged': True,
3940
'targets': [
4041
{'platform': 'linux', 'arch': 'x64'},
4142
{'platform': 'linux', 'arch': 'x86'}
4243
],
44+
'payload': {
45+
'command_stager_flavor': 'wget'
46+
},
4347
'options': {
4448
'email_to': {'type': 'string', 'description': 'Email to send to, must be accepted by the server', 'required': True, 'default': 'admin@localhost'},
4549
'email_from': {'type': 'string', 'description': 'Address to send from', 'required': True, 'default': '[email protected]'},

0 commit comments

Comments
 (0)