From 95e9707349aa7a0d693a43be4229b8c9a9f88c04 Mon Sep 17 00:00:00 2001 From: Sliim Date: Thu, 16 Nov 2017 22:56:55 +0100 Subject: [PATCH 1/3] Call db event handlers Implemented plugins handlers defined in lib/msf/core/database_event.rb: - on_db_client - on_db_host - on_db_service - on_db_vuln - on_db_host_state - on_db_ref - on_db_service_state --- lib/msf/core/db_manager/client.rb | 8 ++++++++ lib/msf/core/db_manager/host.rb | 18 ++++++++++++++++++ lib/msf/core/db_manager/ref.rb | 8 ++++++++ lib/msf/core/db_manager/service.rb | 13 +++++++++++++ lib/msf/core/db_manager/vuln.rb | 8 ++++++++ 5 files changed, 55 insertions(+) diff --git a/lib/msf/core/db_manager/client.rb b/lib/msf/core/db_manager/client.rb index 10793e1c54..f1b4eb5845 100644 --- a/lib/msf/core/db_manager/client.rb +++ b/lib/msf/core/db_manager/client.rb @@ -57,6 +57,14 @@ module Msf::DBManager::Client dlog("Unknown attribute for Client: #{k}") end end + + begin + framework.events.on_db_client(client) if client.new_record? + rescue ::Exception => e + wlog("Exception in on_db_client event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + if client && client.changed? client.save! end diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index f9af660efb..8522c3c04f 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -120,6 +120,15 @@ module Msf::DBManager::Host norm_host end + def host_updated(host) + begin + framework.events.on_db_host_state(host) + rescue ::Exception => e + wlog("Exception in on_db_host_state event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + end + # # Report a host's attributes such as operating system and service pack # @@ -207,9 +216,17 @@ module Msf::DBManager::Host host.comm = '' if !host.comm host.workspace = wspace if !host.workspace + begin + framework.events.on_db_host(host) if host.new_record? + rescue ::Exception => e + wlog("Exception in on_db_host event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + if host.changed? msf_import_timestamps(opts,host) host.save! + host_updated(host) end if opts[:task] @@ -334,6 +351,7 @@ module Msf::DBManager::Host if host.changed? host.save! + host_updated(host) end host diff --git a/lib/msf/core/db_manager/ref.rb b/lib/msf/core/db_manager/ref.rb index ff6087d086..232c47b9ab 100644 --- a/lib/msf/core/db_manager/ref.rb +++ b/lib/msf/core/db_manager/ref.rb @@ -9,6 +9,14 @@ module Msf::DBManager::Ref ::ActiveRecord::Base.connection_pool.with_connection { ref = ::Mdm::Ref.where(name: opts[:name]).first_or_initialize + + begin + framework.events.on_db_ref(ref) if ref + rescue ::Exception => e + wlog("Exception in on_db_ref event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + if ref and ref.changed? ref.save! end diff --git a/lib/msf/core/db_manager/service.rb b/lib/msf/core/db_manager/service.rb index b829defb18..212cc0e2ea 100644 --- a/lib/msf/core/db_manager/service.rb +++ b/lib/msf/core/db_manager/service.rb @@ -99,9 +99,22 @@ module Msf::DBManager::Service service.state ||= Msf::ServiceState::Open service.info ||= "" + begin + framework.events.on_db_service(service) if service.new_record? + rescue ::Exception => e + wlog("Exception in on_db_service event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + if (service and service.changed?) msf_import_timestamps(opts,service) service.save! + begin + framework.events.on_db_service_state(service) + rescue ::Exception => e + wlog("Exception in on_db_service_state event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end end if opts[:task] diff --git a/lib/msf/core/db_manager/vuln.rb b/lib/msf/core/db_manager/vuln.rb index 9eb549fca6..b50bbd77b4 100644 --- a/lib/msf/core/db_manager/vuln.rb +++ b/lib/msf/core/db_manager/vuln.rb @@ -198,6 +198,14 @@ module Msf::DBManager::Vuln vinf[:service_id] = service.id if service vuln = Mdm::Vuln.create(vinf) + + begin + framework.events.on_db_vuln(vuln) if vuln + rescue ::Exception => e + wlog("Exception in on_db_vuln event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + end end From 7f1803590eaf4407f0f89cdf8731fbad979f1c88 Mon Sep 17 00:00:00 2001 From: Sliim Date: Thu, 25 Jan 2018 21:47:38 +0100 Subject: [PATCH 2/3] Fixed on_db_*_state db events Missed arguments for on_db_host_state and on_db_service_state methods. Call these methods only when host/service state changed and pass the old state as argument `ostate` (not sure about what `ostate` meens..) --- lib/msf/core/db_manager/host.rb | 17 ++++++++++------- lib/msf/core/db_manager/service.rb | 14 ++++++++------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index 8522c3c04f..fe59b6633e 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -120,9 +120,9 @@ module Msf::DBManager::Host norm_host end - def host_updated(host) + def host_state_changed(host, ostate) begin - framework.events.on_db_host_state(host) + framework.events.on_db_host_state(host, ostate) rescue ::Exception => e wlog("Exception in on_db_host_state event handler: #{e.class}: #{e}") wlog("Call Stack\n#{e.backtrace.join("\n")}") @@ -180,6 +180,8 @@ module Msf::DBManager::Host host = addr end + ostate = host.state + # Truncate the info field at the maximum field length if opts[:info] opts[:info] = opts[:info][0,65535] @@ -223,10 +225,11 @@ module Msf::DBManager::Host wlog("Call Stack\n#{e.backtrace.join("\n")}") end + host_state_changed(host, ostate) if host.state != ostate + if host.changed? msf_import_timestamps(opts,host) host.save! - host_updated(host) end if opts[:task] @@ -296,6 +299,8 @@ module Msf::DBManager::Host host = addr end + ostate = host.state + res = {} if info['Computer'] @@ -349,10 +354,8 @@ module Msf::DBManager::Host host.comm = '' if !host.comm host.workspace = wspace if !host.workspace - if host.changed? - host.save! - host_updated(host) - end + host.save! if host.changed? + host_state_changed(host, ostate) if host.state != ostate host } diff --git a/lib/msf/core/db_manager/service.rb b/lib/msf/core/db_manager/service.rb index 212cc0e2ea..9fdc26e7f7 100644 --- a/lib/msf/core/db_manager/service.rb +++ b/lib/msf/core/db_manager/service.rb @@ -89,6 +89,7 @@ module Msf::DBManager::Service proto = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO service = host.services.where(port: opts[:port].to_i, proto: proto).first_or_initialize + ostate = service.state opts.each { |k,v| if (service.attribute_names.include?(k.to_s)) service[k] = ((v and k == :name) ? v.to_s.downcase : v) @@ -106,15 +107,16 @@ module Msf::DBManager::Service wlog("Call Stack\n#{e.backtrace.join("\n")}") end + begin + framework.events.on_db_service_state(service, service.port, ostate) if service.state != ostate + rescue ::Exception => e + wlog("Exception in on_db_service_state event handler: #{e.class}: #{e}") + wlog("Call Stack\n#{e.backtrace.join("\n")}") + end + if (service and service.changed?) msf_import_timestamps(opts,service) service.save! - begin - framework.events.on_db_service_state(service) - rescue ::Exception => e - wlog("Exception in on_db_service_state event handler: #{e.class}: #{e}") - wlog("Call Stack\n#{e.backtrace.join("\n")}") - end end if opts[:task] From 36d6162534c645891cf49b414a9cd3c4c50a1512 Mon Sep 17 00:00:00 2001 From: Sliim Date: Sun, 4 Feb 2018 17:51:24 +0100 Subject: [PATCH 3/3] Add libnotify plugin --- plugins/libnotify.rb | 91 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 plugins/libnotify.rb diff --git a/plugins/libnotify.rb b/plugins/libnotify.rb new file mode 100644 index 0000000000..85168df162 --- /dev/null +++ b/plugins/libnotify.rb @@ -0,0 +1,91 @@ +### +# +# This plugin hooks all session creation and db events +# and send desktop notifications using notify-send command. +# +### + +module Msf + +class Plugin::EventLibnotify < Msf::Plugin + include Msf::SessionEvent + include Msf::DatabaseEvent + + def initialize(framework, opts) + super + + @bin = opts[:bin] || opts['bin'] || `which notify-send`.chomp + @bin_opts = opts[:opts] || opts['opts'] || '-a Metasploit' + + raise 'libnotify not found' if @bin.empty? + + self.framework.events.add_session_subscriber(self) + self.framework.events.add_db_subscriber(self) + end + + def notify_send(urgency, title, message) + system("#{@bin} #{@bin_opts} -u #{urgency} '#{title}' '#{message}'") + end + + def on_session_open(session) + notify_send('normal', 'Got Shell!', + "New Session: #{session.sid}\nIP: #{session.session_host}\nPeer: #{session.tunnel_peer}\n"\ + "Platform: #{session.platform}\nType: #{session.type}") + end + + def on_session_close(session, reason='') + notify_send('normal', 'Connection closed', + "Session:#{session.sid} Type:#{session.type} closed.\n#{reason}") + end + + def on_session_fail(reason='') + notify_send('critical', 'Session Failure!', reason) + end + + def on_db_host(host) + notify_send('normal', 'New host', + "Addess: #{host.address}\nOS: #{host.os_name}") + end + + def on_db_host_state(host, ostate) + notify_send('normal', "Host #{host.address} changed", + "OS: #{host.os_name}\nNb Services: #{host.service_count}\nNb vulns: #{host.vuln_count}\n") + end + + def on_db_service(service) + notify_send('normal', 'New service', + "New service: #{service.host.address}:#{service.port}") + end + + def on_db_service_state(service, port, ostate) + notify_send('normal', "Service #{service.host.address}:#{service.port} changed", + "Name: #{service.name}\nState: #{service.state}\nProto: #{service.proto}\nInfo: #{service.info}") + end + + def on_db_vuln(vuln) + notify_send('critical', "New vulnerability on #{vuln.host.address}:#{vuln.service ? vuln.service.port : '0'}", + "Vuln: #{vuln.name}\nInfos: #{vuln.info}") + end + + def on_db_ref(ref) + notify_send('normal', 'New ref', "Reference #{ref.name} added in database.") + end + + def on_db_client(client) + notify_send('critical', 'New client', "New client connected: #{client.ua_string}") + end + + def cleanup + self.framework.events.remove_session_subscriber(self) + self.framework.events.remove_db_subscriber(self) + end + + def name + 'libnotify' + end + + def desc + 'Send desktop notification with libnotify on sessions & db events' + end +end +end