Ejemplo n.º 1
0
class Plugin(plugins.ServerPlugin):
	authors = ['Spencer McIntyre']
	classifiers = ['Plugin :: Server :: Notifications']
	title = 'XMPP Notifications'
	description = """
	A plugin which pushes notifications regarding the King Phisher server to a
	specified XMPP server.
	"""
	homepage = 'https://github.com/securestate/king-phisher-plugins'
	options = [
		plugin_opts.OptionString('jid', 'the username to login with'),
		plugin_opts.OptionString('password', 'the password to login with'),
		plugin_opts.OptionString('room', 'the room to send notifications to'),
		plugin_opts.OptionString('server', 'the server to connect to'),
		# verify_cert only functions when sleekxmpp supports it
		plugin_opts.OptionBoolean('verify_cert', 'verify the ssl certificate', default=True)
	]
	req_min_version = '1.4.0'
	req_packages = {
		'sleekxmpp': has_sleekxmpp
	}
	def initialize(self):
		logger = logging.getLogger('sleekxmpp')
		logger.setLevel(logging.INFO)
		self.bot = None
		signals.server_initialized.connect(self.on_server_initialized)
		return True

	def on_server_initialized(self, server):
		self.bot = NotificationBot(
			self.config['jid'],
			self.config['password'],
			self.config['room'],
			self.config['verify_cert']
		)
		self.bot.connect(utilities.parse_server(self.config['server'], 5222))
		self.bot.process(block=False)

	def finalize(self):
		if self.bot is None:
			return
		self.bot.disconnect()
Ejemplo n.º 2
0
class Plugin(plugins.ServerPlugin):
    authors = ['Brandan Geise']
    title = 'Pushbullet Notifications'
    description = """
	A plugin that uses Pushbullet's API to send push notifications
	on new website visits and submitted credentials.
	"""
    homepage = 'https://github.com/securestate/king-phisher-plugins'
    options = [
        plugin_opts.OptionString(
            name='api_keys',
            description='Pushbullet API key, if multiple, separate with comma'
        ),
        plugin_opts.OptionString(
            name='identifier',
            description=
            'King Phisher server identifier to send in push notification header',
            default='King Phisher'),
        plugin_opts.OptionBoolean(
            name='mask',
            description='Partially mask email and campaign values',
            default=False)
    ]
    req_min_version = '1.4.0b0'
    req_packages = {'pushbullet.py': has_pushbullet}
    version = '1.2'

    def initialize(self):
        signals.server_initialized.connect(self.on_server_initialized)
        return True

    def on_server_initialized(self, server):
        signals.db_session_inserted.connect(self.on_kp_db_event,
                                            sender='visits')
        signals.db_session_inserted.connect(self.on_kp_db_event,
                                            sender='credentials')
        self.send_notification('Pushbullet notifications are now active')

    def on_kp_db_event(self, sender, targets, session):
        for event in targets:
            message = db_manager.get_row_by_id(session, db_models.Message,
                                               event.message_id)
            target_email, campaign_name = self.check_mask(message)

            if sender == 'visits':
                message = "New visit from {0} for campaign '{1}'".format(
                    target_email, campaign_name)
            elif sender == 'credentials':
                message = "New credentials received from {0} for campaign '{1}'".format(
                    target_email, campaign_name)
            else:
                return
            self.send_notification(message)

    def check_mask(self, message):
        if self.config['mask']:
            target_email = self.mask_string(message.target_email)
            campaign_name = self.mask_string(message.campaign.name)
        else:
            target_email = message.target_email
            campaign_name = message.campaign.name
        return target_email, campaign_name

    def mask_string(self, word):
        if utilities.is_valid_email_address(word):
            email_user, email_domain = word.split('@')
            safe_string = "{0}@{1}{2}{3}".format(
                email_user, email_domain[:1], ('*' * (len(email_domain) - 2)),
                email_domain[-1:])
        else:
            safe_string = "{0}{1}{2}".format(word[:1], ('*' * (len(word) - 2)),
                                             word[-1:])
        return safe_string

    def send_notification(self, message):
        api_keys = tuple(k.strip()
                         for k in self.config['api_keys'].split(', '))
        for key in api_keys:
            device = None
            if ':' in key:
                device, key = key.split(':')

            pb = pushbullet.Pushbullet(key)
            if device:
                try:
                    device = pb.get_device(device)
                except pushbullet.errors.InvalidKeyError:
                    self.logger.error(
                        "failed to get pushbullet device: {0}".format(device))

            try:
                pb.push_note(self.config['identifier'], message, device=device)
            except pushbullet.errors.PushError as error:
                self.logger.error('failed to send the pushbullet note')
Ejemplo n.º 3
0
class Plugin(plugins.ServerPlugin):
    authors = [
        'Austin DeFrancesco', 'Spencer McIntyre', 'Mike Stringer',
        'Erik Daguerre'
    ]
    classifiers = ['Plugin :: Server :: Notifications :: Alerts']
    title = 'Campaign Alerts: via Python 3 SMTPLib'
    description = """
	Send campaign alerts via the SMTP Python 3 lib. This requires that users specify
	their email through the King Phisher client to subscribe to notifications.
	"""
    homepage = 'https://github.com/securestate/king-phisher-plugins'
    version = '1.1'

    # Email accounts with 2FA, such as Gmail, will not work unless "less secure apps" are allowed
    # Reference: https://support.google.com/accounts/answer/60610255
    # Gmail and other providers require SSL on port 465, TLS will start with the activation of SSL
    options = [
        plugin_opts.OptionString(name='smtp_server',
                                 description='Location of SMTP server',
                                 default='localhost'),
        plugin_opts.OptionInteger(name='smtp_port',
                                  description='Port used for SMTP server',
                                  default=25),
        plugin_opts.OptionString(
            name='smtp_email',
            description='SMTP email address to send notifications from',
            default=''),
        plugin_opts.OptionString(
            name='smtp_username',
            description='Username to authenticate to the SMTP server with'),
        plugin_opts.OptionString(
            name='smtp_password',
            description='Password to authenticate to the SMTP server with',
            default=''),
        plugin_opts.OptionBoolean(
            name='smtp_ssl',
            description='Connect to the SMTP server with SSL',
            default=False),
        plugin_opts.OptionString(
            name='email_jinja_template',
            description='Custom email jinja template to use for alerts',
            default=''),
    ]
    req_min_version = '1.12.0b2'

    def initialize(self):
        signals.campaign_alert.connect(self.on_campaign_alert)
        signals.campaign_alert_expired.connect(self.on_campaign_alert_expired)
        template_path = self.config['email_jinja_template']
        if not template_path:
            template_path = os.path.join(
                os.path.dirname(os.path.realpath(__file__)), 'template.html')
        if not os.path.isfile(template_path):
            self.logger.warning('invalid email template: ' + template_path)
            return False
        with open(template_path, 'r') as file_:
            template_data = file_.read()
        self.render_template = templates.TemplateEnvironmentBase().from_string(
            template_data)
        return True

    def on_campaign_alert(self, table, alert_subscription, count):
        return self.send_alert(alert_subscription)

    def on_campaign_alert_expired(self, camapign, alert_subscription):
        return self.send_alert(alert_subscription)

    def get_template_vars(self, alert_subscription):
        campaign = alert_subscription.campaign
        template_vars = {
            'campaign': {
                'id': str(campaign.id),
                'name': campaign.name,
                'created': campaign.created,
                'expiration': campaign.expiration,
                'has_expired': campaign.has_expired,
                'message_count': len(campaign.messages),
                'visit_count': len(campaign.visits),
                'credential_count': len(campaign.credentials)
            },
            'time': {
                'local': datetime.datetime.now(),
                'utc': datetime.datetime.utcnow()
            }
        }
        return template_vars

    def create_message(self, alert_subscription):
        message = MIMEMultipart()
        message['Subject'] = "Campaign Event: {0}".format(
            alert_subscription.campaign.name)
        message['From'] = "<{0}>".format(self.config['smtp_email'])
        message['To'] = "<{0}>".format(alert_subscription.user.email_address)

        textual_message = MIMEMultipart('alternative')
        plaintext_part = MIMEText(
            'This message requires an HTML aware email agent to be properly viewed.\r\n\r\n',
            'plain')
        textual_message.attach(plaintext_part)

        try:
            rendered_email = self.render_template.render(
                self.get_template_vars(alert_subscription))
        except:
            self.logger.warning('failed to render the email template',
                                exc_info=True)
            return False
        html_part = MIMEText(rendered_email, 'html')
        textual_message.attach(html_part)

        message.attach(textual_message)
        encoded_email = message.as_string()
        return encoded_email

    def send_alert(self, alert_subscription):
        user = alert_subscription.user
        if not user.email_address:
            self.logger.debug(
                "user {0} has no email address specified, skipping SMTP alert".
                format(user.name))
            return False

        msg = self.create_message(alert_subscription)
        if not msg:
            return False

        if self.config['smtp_ssl']:
            SmtpClass = smtplib.SMTP_SSL
        else:
            SmtpClass = smtplib.SMTP
        try:
            server = SmtpClass(self.config['smtp_server'],
                               self.config['smtp_port'],
                               timeout=15)
            server.ehlo()
        except smtplib.SMTPException:
            self.logger.warning(
                'received an SMTPException while connecting to the SMTP server',
                exc_info=True)
            return False
        except socket.error:
            self.logger.warning(
                'received a socket.error while connecting to the SMTP server')
            return False

        if not self.config['smtp_ssl'] and 'starttls' in server.esmtp_features:
            self.logger.debug(
                'target SMTP server supports the STARTTLS extension')
            try:
                server.starttls()
                server.ehlo()
            except smtplib.SMTPException:
                self.logger.warning(
                    'received an SMTPException wile negotiating STARTTLS with SMTP server',
                    exc_info=True)
                return False

        if self.config['smtp_username']:
            try:
                server.login(self.config['smtp_username'],
                             self.config['smtp_password'])
            except smtplib.SMTPNotSupportedError:
                self.logger.debug(
                    'SMTP server does not support authentication')
            except smtplib.SMTPException as error:
                self.logger.warning(
                    "received an {0} while authenticating to the SMTP server".
                    format(error.__class__.__name__))
                server.quit()
                return False

        mail_options = ['SMTPUTF8'] if server.has_extn('SMTPUTF8') else []
        try:
            server.sendmail(self.config['smtp_email'],
                            alert_subscription.user.email_address, msg,
                            mail_options)
        except smtplib.SMTPException as error:
            self.logger.warning("received error {0} while sending mail".format(
                error.__class__.__name__))
            return False
        finally:
            server.quit()
        self.logger.debug(
            "successfully sent an email campaign alert to user: {0}".format(
                user.name))
        return True