Skip to content

Commit 835a66c

Browse files
committed
Land 5042, fix issues on reporting exploit success
2 parents bf2d37c + 2fc2213 commit 835a66c

File tree

7 files changed

+272
-266
lines changed

7 files changed

+272
-266
lines changed

lib/msf/core/db_manager.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
class Msf::DBManager
2424
extend Metasploit::Framework::Require
2525

26+
# Default proto for making new `Mdm::Service`s. This should probably be a
27+
# const on `Mdm::Service`
28+
DEFAULT_SERVICE_PROTO = "tcp"
29+
2630
autoload :Adapter, 'msf/core/db_manager/adapter'
2731
autoload :Client, 'msf/core/db_manager/client'
2832
autoload :Connection, 'msf/core/db_manager/connection'

lib/msf/core/db_manager/exploit_attempt.rb

Lines changed: 107 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -27,186 +27,152 @@ def report_exploit_attempt(host, opts)
2727
}
2828
end
2929

30+
# Create an `Mdm::ExploitAttempt` (and possibly an `Mdm::VulnAttempt`, if
31+
# the `vuln` option is passed).
32+
#
33+
# @option (see #do_report_failure_or_success)
34+
# @return (see #do_report_failure_or_success)
3035
def report_exploit_failure(opts)
36+
return unless opts.has_key?(:refs) && !opts[:refs].blank?
37+
host = opts[:host] || return
3138

32-
::ActiveRecord::Base.connection_pool.with_connection {
33-
wspace = opts.delete(:workspace) || workspace
34-
mrefs = opts.delete(:refs) || return
35-
host = opts.delete(:host)
36-
port = opts.delete(:port)
37-
prot = opts.delete(:proto)
38-
svc = opts.delete(:service)
39-
vuln = opts.delete(:vuln)
40-
41-
timestamp = opts.delete(:timestamp)
42-
freason = opts.delete(:fail_reason)
43-
fdetail = opts.delete(:fail_detail)
44-
username = opts.delete(:username)
45-
mname = opts.delete(:module)
39+
wspace = opts[:workspace] || workspace
40+
port = opts[:port]
41+
prot = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
42+
svc = opts[:service]
43+
44+
# Look up the service as appropriate
45+
if port and svc.nil?
46+
svc = get_service(wspace, host, prot, port)
47+
end
4648

4749
# Look up the host as appropriate
48-
if not (host and host.kind_of? ::Mdm::Host)
50+
if !host || !host.kind_of?(::Mdm::Host)
4951
if svc.kind_of? ::Mdm::Service
5052
host = svc.host
5153
else
52-
host = get_host( :workspace => wspace, :address => host )
54+
host = get_host(workspace: wspace, address: host)
5355
end
5456
end
5557

5658
# Bail if we dont have a host object
5759
return if not host
5860

59-
# Look up the service as appropriate
60-
if port and svc.nil?
61-
prot ||= "tcp"
62-
svc = get_service(wspace, host, prot, port) if port
63-
end
64-
65-
if not vuln
66-
# Create a references map from the module list
67-
ref_objs = ::Mdm::Ref.where(:name => mrefs.map { |ref|
68-
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)
69-
"#{ref.ctx_id}-#{ref.ctx_val}"
70-
else
71-
ref.to_s
72-
end
73-
})
74-
75-
# Try find a matching vulnerability
76-
vuln = find_vuln_by_refs(ref_objs, host, svc)
77-
end
78-
79-
# Report a vuln_attempt if we found a match
80-
if vuln
81-
attempt_info = {
82-
:attempted_at => timestamp || Time.now.utc,
83-
:exploited => false,
84-
:fail_reason => freason,
85-
:fail_detail => fdetail,
86-
:username => username || "unknown",
87-
:module => mname
88-
}
89-
90-
vuln.vuln_attempts.create(attempt_info)
91-
end
92-
93-
# Report an exploit attempt all the same
94-
attempt_info = {
95-
:attempted_at => timestamp || Time.now.utc,
96-
:exploited => false,
97-
:username => username || "unknown",
98-
:module => mname,
99-
:fail_reason => freason,
100-
:fail_detail => fdetail
101-
}
102-
103-
attempt_info[:vuln_id] = vuln.id if vuln
104-
105-
if svc
106-
attempt_info[:port] = svc.port
107-
attempt_info[:proto] = svc.proto
108-
end
109-
110-
if port and svc.nil?
111-
attempt_info[:port] = port
112-
attempt_info[:proto] = prot || "tcp"
113-
end
61+
opts = opts.dup
62+
opts[:service] = svc
63+
opts[:host] = host
11464

115-
host.exploit_attempts.create(attempt_info)
116-
}
65+
do_report_failure_or_success(opts)
11766
end
11867

68+
# Create an `Mdm::ExploitAttempt` (and possibly an `Mdm::VulnAttempt`, if
69+
# the `vuln` option is passed).
70+
#
71+
# @return (see #do_report_failure_or_success)
11972
def report_exploit_success(opts)
120-
::ActiveRecord::Base.connection_pool.with_connection {
121-
122-
wspace = opts.delete(:workspace) || workspace
123-
mrefs = opts.delete(:refs) || return
124-
host = opts.delete(:host)
125-
port = opts.delete(:port)
126-
prot = opts.delete(:proto)
127-
svc = opts.delete(:service)
128-
vuln = opts.delete(:vuln)
129-
130-
timestamp = opts.delete(:timestamp)
131-
username = opts.delete(:username)
132-
mname = opts.delete(:module)
133-
134-
# Look up or generate the host as appropriate
135-
if not (host and host.kind_of? ::Mdm::Host)
136-
if svc.kind_of? ::Mdm::Service
137-
host = svc.host
138-
else
139-
host = report_host(:workspace => wspace, :address => host )
140-
end
141-
end
73+
return unless opts[:refs]
74+
host = opts[:host] || return
14275

143-
# Bail if we dont have a host object
144-
return if not host
76+
wspace = opts[:workspace] || workspace
77+
port = opts[:port]
78+
prot = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
79+
svc = opts[:service]
14580

14681
# Look up or generate the service as appropriate
14782
if port and svc.nil?
148-
svc = report_service(:workspace => wspace, :host => host, :port => port, :proto => prot ) if port
83+
# it is rude to modify arguments in place
84+
opts = opts.dup
85+
opts[:proto] ||= Msf::DBManager::DEFAULT_SERVICE_PROTO
86+
opts[:service] = report_service(
87+
workspace: wspace, host: host, port: port, proto: prot
88+
)
14989
end
15090

151-
if not vuln
152-
# Create a references map from the module list
153-
ref_objs = ::Mdm::Ref.where(:name => mrefs.map { |ref|
154-
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)
155-
"#{ref.ctx_id}-#{ref.ctx_val}"
156-
else
157-
ref.to_s
158-
end
159-
})
91+
do_report_failure_or_success(opts)
92+
end
16093

161-
# Try find a matching vulnerability
162-
vuln = find_vuln_by_refs(ref_objs, host, svc)
163-
end
94+
private
95+
96+
# @option opts [Array<String>, Array<Msf::Module::Reference>] :refs
97+
# @option opts [Mdm::Host] :host
98+
# @option opts [Mdm::Service] :service
99+
# @option opts [Integer] :port (nil)
100+
# @option opts ["tcp","udp"] :proto (Msf::DBManager::DEFAULT_SERVICE_PROTO) See `Mdm::Service::PROTOS`
101+
# @option opts [Mdm::Vuln] :vuln (nil)
102+
# @option opts [Time] :timestamp (nil)
103+
# @option opts [Mdm::Vuln] :timestamp (nil)
104+
# @option opts [String] :module (nil)
105+
# @return [void]
106+
def do_report_failure_or_success(opts)
107+
return unless opts[:refs]
108+
::ActiveRecord::Base.connection_pool.with_connection {
109+
mrefs = opts[:refs]
110+
host = opts[:host]
111+
port = opts[:port]
112+
prot = opts[:proto]
113+
svc = opts[:service]
114+
vuln = opts[:vuln]
115+
116+
timestamp = opts[:timestamp]
117+
freason = opts[:fail_reason]
118+
fdetail = opts[:fail_detail]
119+
username = opts[:username]
120+
mname = opts[:module]
121+
122+
if vuln.nil?
123+
ref_names = mrefs.map { |ref|
124+
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)
125+
"#{ref.ctx_id}-#{ref.ctx_val}"
126+
else
127+
ref.to_s
128+
end
129+
}
130+
131+
# Create a references map from the module list
132+
ref_objs = ::Mdm::Ref.where(name: ref_names)
133+
134+
# Try find a matching vulnerability
135+
vuln = find_vuln_by_refs(ref_objs, host, svc)
136+
end
164137

165-
# We have match, lets create a vuln_attempt record
166-
if vuln
167138
attempt_info = {
168-
:vuln_id => vuln.id,
169139
:attempted_at => timestamp || Time.now.utc,
170-
:exploited => true,
140+
:exploited => (freason.nil? ? true : false),
141+
:fail_detail => fdetail,
142+
:fail_reason => freason,
143+
:module => mname,
171144
:username => username || "unknown",
172-
:module => mname
173145
}
174146

175147
attempt_info[:session_id] = opts[:session_id] if opts[:session_id]
176148
attempt_info[:loot_id] = opts[:loot_id] if opts[:loot_id]
177149

178-
vuln.vuln_attempts.create(attempt_info)
150+
# We have match, lets create a vuln_attempt record
151+
if vuln
152+
attempt_info[:vuln_id] = vuln.id
153+
vuln.vuln_attempts.create(attempt_info)
179154

180-
# Correct the vuln's associated service if necessary
181-
if svc and vuln.service_id.nil?
182-
vuln.service = svc
183-
vuln.save
155+
# Correct the vuln's associated service if necessary
156+
if svc and vuln.service_id.nil?
157+
vuln.service = svc
158+
vuln.save
159+
end
184160
end
185-
end
186161

187-
# Report an exploit attempt all the same
188-
attempt_info = {
189-
:attempted_at => timestamp || Time.now.utc,
190-
:exploited => true,
191-
:username => username || "unknown",
192-
:module => mname
193-
}
162+
# Report an exploit attempt all the same
194163

195-
attempt_info[:vuln_id] = vuln.id if vuln
196-
attempt_info[:session_id] = opts[:session_id] if opts[:session_id]
197-
attempt_info[:loot_id] = opts[:loot_id] if opts[:loot_id]
164+
if svc
165+
attempt_info[:port] = svc.port
166+
attempt_info[:proto] = svc.proto
167+
end
198168

199-
if svc
200-
attempt_info[:port] = svc.port
201-
attempt_info[:proto] = svc.proto
202-
end
169+
if port and svc.nil?
170+
attempt_info[:port] = port
171+
attempt_info[:proto] = prot || Msf::DBManager::DEFAULT_SERVICE_PROTO
172+
end
203173

204-
if port and svc.nil?
205-
attempt_info[:port] = port
206-
attempt_info[:proto] = prot || "tcp"
207-
end
174+
host.exploit_attempts.create(attempt_info)
175+
}
208176

209-
host.exploit_attempts.create(attempt_info)
210-
}
211177
end
212178
end

lib/msf/core/db_manager/host.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ def normalize_host(host)
9696
norm_host = host.host
9797
elsif host.respond_to?(:session_host)
9898
# Then it's an Msf::Session object
99-
thost = host.session_host
100-
norm_host = thost
99+
norm_host = host.session_host
101100
end
102101

103102
# If we got here and don't have a norm_host yet, it could be a
@@ -325,4 +324,4 @@ def update_host_via_sysinfo(opts)
325324
host
326325
}
327326
end
328-
end
327+
end

lib/msf/core/db_manager/service.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def report_service(opts)
8585
end
8686
=end
8787

88-
proto = opts[:proto] || 'tcp'
88+
proto = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
8989

9090
service = host.services.where(port: opts[:port].to_i, proto: proto).first_or_initialize
9191
opts.each { |k,v|
@@ -126,4 +126,4 @@ def services(wspace = workspace, only_up = false, proto = nil, addresses = nil,
126126
wspace.services.includes(:host).where(conditions).order("hosts.address, port")
127127
}
128128
end
129-
end
129+
end

0 commit comments

Comments
 (0)