add dingtalk's code
This commit is contained in:
parent
736511f930
commit
f26133bef0
|
@ -1,9 +1,12 @@
|
|||
require 'net/https'
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
module Msf
|
||||
class Plugin::SessionNotifier < Msf::Plugin
|
||||
|
||||
include Msf::SessionEvent
|
||||
|
||||
class Exception < ::RuntimeError ; end
|
||||
class Exception < ::RuntimeError; end
|
||||
|
||||
class SessionNotifierCommandDispatcher
|
||||
|
||||
|
@ -19,6 +22,7 @@ module Msf
|
|||
attr_reader :smtp_from
|
||||
attr_reader :minimum_ip
|
||||
attr_reader :maximum_ip
|
||||
attr_reader :dingtalk_webhook
|
||||
|
||||
def name
|
||||
'SessionNotifier'
|
||||
|
@ -35,6 +39,7 @@ module Msf
|
|||
'set_session_mobile_carrier' => 'Set the mobile carrier of the phone',
|
||||
'set_session_minimum_ip' => 'Set the minimum session IP range you want to be notified for',
|
||||
'set_session_maximum_ip' => 'Set the maximum session IP range you want to be notified for',
|
||||
'set_session_dingtalk_webhook' => 'Set the DingTalk webhook for the session notifier (keyword: session).',
|
||||
'save_session_notifier_settings' => 'Save all the session notifier settings to framework',
|
||||
'start_session_notifier' => 'Start notifying sessions',
|
||||
'stop_session_notifier' => 'Stop notifying sessions',
|
||||
|
@ -107,38 +112,52 @@ module Msf
|
|||
end
|
||||
end
|
||||
|
||||
def cmd_save_session_notifier_settings(*args)
|
||||
save_settings_to_config
|
||||
print_status("Session Notifier settings saved in config file.")
|
||||
def cmd_set_session_dingtalk_webhook(*args)
|
||||
webhook_url = args[0]
|
||||
if webhook_url.blank?
|
||||
@dingtalk_webhook = nil
|
||||
elsif !(webhook_url =~ URI::DEFAULT_PARSER.make_regexp).nil?
|
||||
@dingtalk_webhook = webhook_url
|
||||
else
|
||||
print_error('Invalid webhook_url')
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_start_session_notifier(*args)
|
||||
if is_session_notifier_subscribed?
|
||||
def cmd_save_session_notifier_settings(*_args)
|
||||
save_settings_to_config
|
||||
print_status('Session Notifier settings saved in config file.')
|
||||
end
|
||||
|
||||
def cmd_start_session_notifier(*_args)
|
||||
if session_notifier_subscribed?
|
||||
print_status('You already have an active session notifier.')
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
validate_settings!
|
||||
self.framework.events.add_session_subscriber(self)
|
||||
smtp = Rex::Proto::Sms::Model::Smtp.new(
|
||||
address: self.smtp_address,
|
||||
port: self.smtp_port,
|
||||
username: self.smtp_username,
|
||||
password: self.smtp_password,
|
||||
login_type: :login,
|
||||
from: self.smtp_from
|
||||
)
|
||||
@sms_client = Rex::Proto::Sms::Client.new(carrier: self.sms_carrier, smtp_server: smtp)
|
||||
print_status("Session notification started.")
|
||||
framework.events.add_session_subscriber(self)
|
||||
if validate_sms_settings?
|
||||
smtp = Rex::Proto::Sms::Model::Smtp.new(
|
||||
address: smtp_address,
|
||||
port: smtp_port,
|
||||
username: smtp_username,
|
||||
password: smtp_password,
|
||||
login_type: :login,
|
||||
from: smtp_from
|
||||
)
|
||||
@sms_client = Rex::Proto::Sms::Client.new(carrier: sms_carrier, smtp_server: smtp)
|
||||
print_status('Session notification started.')
|
||||
elsif !dingtalk_webhook.nil?
|
||||
print_status('DingTalk notification started.')
|
||||
end
|
||||
rescue Msf::Plugin::SessionNotifier::Exception, Rex::Proto::Sms::Exception => e
|
||||
print_error(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_stop_session_notifier(*args)
|
||||
self.framework.events.remove_session_subscriber(self)
|
||||
print_status("Session notification stopped.")
|
||||
def cmd_stop_session_notifier(*_args)
|
||||
framework.events.remove_session_subscriber(self)
|
||||
print_status('Session notification stopped.')
|
||||
end
|
||||
|
||||
def cmd_restart_session_notifier(*args)
|
||||
|
@ -148,7 +167,7 @@ module Msf
|
|||
|
||||
def on_session_open(session)
|
||||
subject = "You have a new #{session.type} session!"
|
||||
msg = "#{session.tunnel_peer} (#{session.session_host}) #{session.info ? "\"#{session.info.to_s}\"" : nil}"
|
||||
msg = "#{session.tunnel_peer} (#{session.session_host}) #{session.info ? "\"#{session.info}\"" : nil}"
|
||||
notify_session(session, subject, msg)
|
||||
end
|
||||
|
||||
|
@ -158,15 +177,16 @@ module Msf
|
|||
config_file = Msf::Config.config_file
|
||||
ini = Rex::Parser::Ini.new(config_file)
|
||||
ini.add_group(name) unless ini[name]
|
||||
ini[name]['smtp_address'] = self.smtp_address
|
||||
ini[name]['smtp_port'] = self.smtp_port
|
||||
ini[name]['smtp_username'] = self.smtp_username
|
||||
ini[name]['smtp_password'] = self.smtp_password
|
||||
ini[name]['smtp_from'] = self.smtp_from
|
||||
ini[name]['sms_number'] = self.sms_number
|
||||
ini[name]['sms_carrier'] = self.sms_carrier
|
||||
ini[name]['minimum_ip'] = self.minimum_ip.to_s unless self.minimum_ip.blank?
|
||||
ini[name]['maximum_ip'] = self.maximum_ip.to_s unless self.maximum_ip.blank?
|
||||
ini[name]['smtp_address'] = smtp_address
|
||||
ini[name]['smtp_port'] = smtp_port
|
||||
ini[name]['smtp_username'] = smtp_username
|
||||
ini[name]['smtp_password'] = smtp_password
|
||||
ini[name]['smtp_from'] = smtp_from
|
||||
ini[name]['sms_number'] = sms_number
|
||||
ini[name]['sms_carrier'] = sms_carrier
|
||||
ini[name]['minimum_ip'] = minimum_ip.to_s unless minimum_ip.blank?
|
||||
ini[name]['maximum_ip'] = maximum_ip.to_s unless maximum_ip.blank?
|
||||
ini[name]['dingtalk_webhook'] = dingtalk_webhook.to_s unless dingtalk_webhook.blank?
|
||||
ini.to_file(config_file)
|
||||
end
|
||||
|
||||
|
@ -175,57 +195,81 @@ module Msf
|
|||
ini = Rex::Parser::Ini.new(config_file)
|
||||
group = ini[name]
|
||||
if group
|
||||
@sms_carrier = group['sms_carrier'].to_sym if group['sms_carrier']
|
||||
@sms_number = group['sms_number'] if group['sms_number']
|
||||
@smtp_address = group['smtp_address'] if group['smtp_address']
|
||||
@smtp_port = group['smtp_port'] if group['smtp_port']
|
||||
@smtp_username = group['smtp_username'] if group['smtp_username']
|
||||
@smtp_password = group['smtp_password'] if group['smtp_password']
|
||||
@smtp_from = group['smtp_from'] if group['smtp_from']
|
||||
@minimum_ip = IPAddr.new(group['minimum_ip']) if group['minimum_ip']
|
||||
@maximum_ip = IPAddr.new(group['maximum_ip']) if group['maximum_ip']
|
||||
@sms_carrier = group['sms_carrier'].to_sym if group['sms_carrier']
|
||||
@sms_number = group['sms_number'] if group['sms_number']
|
||||
@smtp_address = group['smtp_address'] if group['smtp_address']
|
||||
@smtp_port = group['smtp_port'] if group['smtp_port']
|
||||
@smtp_username = group['smtp_username'] if group['smtp_username']
|
||||
@smtp_password = group['smtp_password'] if group['smtp_password']
|
||||
@smtp_from = group['smtp_from'] if group['smtp_from']
|
||||
@minimum_ip = IPAddr.new(group['minimum_ip']) if group['minimum_ip']
|
||||
@maximum_ip = IPAddr.new(group['maximum_ip']) if group['maximum_ip']
|
||||
@dingtalk_webhook = group['dingtalk_webhook'] if group['dingtalk_webhook']
|
||||
|
||||
print_status('Session Notifier settings loaded from config file.')
|
||||
end
|
||||
end
|
||||
|
||||
def is_session_notifier_subscribed?
|
||||
subscribers = framework.events.instance_variable_get(:@session_event_subscribers).collect { |s| s.class }
|
||||
def session_notifier_subscribed?
|
||||
subscribers = framework.events.instance_variable_get(:@session_event_subscribers).collect(&:class)
|
||||
subscribers.include?(self.class)
|
||||
end
|
||||
|
||||
def send_text_to_dingtalk(session)
|
||||
# https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq/9e91d73c
|
||||
uri_parser = URI.parse(dingtalk_webhook)
|
||||
markdown_text = "## You have a new #{session.type} session!\n\n" \
|
||||
"**platform** : #{session.platform}\n\n" \
|
||||
"**tunnel** : #{session.tunnel_to_s}\n\n" \
|
||||
"**arch** : #{session.arch}\n\n" \
|
||||
"**info** : > #{session.info ? session.info.to_s : nil}"
|
||||
json_post_data = JSON.pretty_generate({
|
||||
msgtype: 'markdown',
|
||||
markdown: { title: 'Session Notifier', text: markdown_text }
|
||||
})
|
||||
http = Net::HTTP.new(uri_parser.host, uri_parser.port)
|
||||
http.use_ssl = true
|
||||
request = Net::HTTP::Post.new(uri_parser.request_uri)
|
||||
request.content_type = 'application/json'
|
||||
request.body = json_post_data
|
||||
res = http.request(request)
|
||||
body = JSON.parse(res.body)
|
||||
print_status((body['errcode'] == 0) ? 'Session notified to DingTalk.' : 'Failed to send notification.')
|
||||
end
|
||||
|
||||
def notify_session(session, subject, msg)
|
||||
if is_in_range?(session)
|
||||
@sms_client.send_text_to_phones([self.sms_number], subject, msg)
|
||||
print_status("Session notified to: #{self.sms_number}")
|
||||
if in_range?(session) && validate_sms_settings?
|
||||
@sms_client.send_text_to_phones([sms_number], subject, msg)
|
||||
print_status("Session notified to: #{sms_number}")
|
||||
end
|
||||
if in_range?(session) && !dingtalk_webhook.nil?
|
||||
send_text_to_dingtalk(session)
|
||||
end
|
||||
end
|
||||
|
||||
def is_in_range?(session)
|
||||
def in_range?(session)
|
||||
# If both blank, it means we're not setting a range.
|
||||
return true if self.minimum_ip.blank? && self.maximum_ip.blank?
|
||||
return true if minimum_ip.blank? && maximum_ip.blank?
|
||||
|
||||
ip = IPAddr.new(session.session_host)
|
||||
|
||||
if self.minimum_ip && !self.maximum_ip
|
||||
if minimum_ip && !maximum_ip
|
||||
# There is only a minimum IP
|
||||
self.minimum_ip < ip
|
||||
elsif !self.minimum_ip && self.maximum_ip
|
||||
minimum_ip < ip
|
||||
elsif !minimum_ip && maximum_ip
|
||||
# There is only a max IP
|
||||
self.maximum_ip > ip
|
||||
maximum_ip > ip
|
||||
else
|
||||
# Both ends are set
|
||||
range = self.minimum_ip..self.maximum_ip
|
||||
range = minimum_ip..maximum_ip
|
||||
range.include?(ip)
|
||||
end
|
||||
end
|
||||
|
||||
def validate_settings!
|
||||
if self.smtp_address.nil? || self.smtp_port.nil? ||
|
||||
self.smtp_username.nil? || self.smtp_password.nil? ||
|
||||
self.smtp_from.nil?
|
||||
raise Msf::Plugin::SessionNotifier::Exception, "All Session Notifier's settings must be configured."
|
||||
end
|
||||
def validate_sms_settings?
|
||||
!(smtp_address.nil? || smtp_port.nil? ||
|
||||
smtp_username.nil? || smtp_password.nil? ||
|
||||
smtp_from.nil?)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -243,13 +287,9 @@ module Msf
|
|||
remove_console_dispatcher(name)
|
||||
end
|
||||
|
||||
def name
|
||||
'SessionNotifier'
|
||||
end
|
||||
|
||||
def desc
|
||||
'This plugin notifies you a new session via SMS.'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue