示例#1
0
	def handle_email_opened(self, query):
		# image size: 43 Bytes
		img_data = '47494638396101000100800100000000ffffff21f90401000001002c00000000'
		img_data += '010001000002024c01003b'
		img_data = binascii.a2b_hex(img_data)
		self.send_response(200)
		self.send_header('Content-Type', 'image/gif')
		self.send_header('Content-Length', str(len(img_data)))
		self.end_headers()
		self.wfile.write(img_data)

		msg_id = self.get_query('id')
		if not msg_id:
			return
		session = db_manager.Session()
		query = session.query(db_models.Message)
		query = query.filter_by(id=msg_id, opened=None)
		message = query.first()
		if message and not message.campaign.has_expired:
			message.opened = db_models.current_timestamp()
			message.opener_ip = self.get_client_ip()
			message.opener_user_agent = self.headers.get('user-agent', None)
			session.commit()
		session.close()
		signals.safe_send('email-opened', self.logger, self)
示例#2
0
	def __init__(self, timeout='30m'):
		"""
		:param timeout: The length of time in seconds for which sessions are valid.
		:type timeout: int, str
		"""
		self.logger = logging.getLogger('KingPhisher.Server.SessionManager')
		timeout = smoke_zephyr.utilities.parse_timespan(timeout)
		self.session_timeout = datetime.timedelta(seconds=timeout)
		self._sessions = {}
		self._lock = threading.Lock()

		# get valid sessions from the database
		expired = 0
		session = db_manager.Session()
		oldest = db_models.current_timestamp() - self.session_timeout
		for stored_session in session.query(db_models.AuthenticatedSession):
			if stored_session.last_seen < oldest:
				expired += 1
				continue
			auth_session = AuthenticatedSession.from_db_authenticated_session(stored_session)
			self._sessions[stored_session.id] = auth_session
		session.query(db_models.AuthenticatedSession).delete()
		session.commit()
		self.logger.info("restored {0:,} valid session{1} and skipped {2:,} expired session{3} from the database".format(
			len(self._sessions),
			('' if len(self._sessions) == 1 else 's'),
			expired,
			('' if expired == 1 else 's')
		))
示例#3
0
    def __init__(self, timeout='30m'):
        """
		:param timeout: The length of time in seconds for which sessions are valid.
		:type timeout: int, str
		"""
        self.logger = logging.getLogger('KingPhisher.Server.SessionManager')
        timeout = smoke_zephyr.utilities.parse_timespan(timeout)
        self.session_timeout = datetime.timedelta(seconds=timeout)
        self._sessions = {}
        self._lock = threading.Lock()

        # get valid sessions from the database
        expired = 0
        session = db_manager.Session()
        oldest = db_models.current_timestamp() - self.session_timeout
        for stored_session in session.query(db_models.AuthenticatedSession):
            if stored_session.last_seen < oldest:
                expired += 1
                continue
            auth_session = AuthenticatedSession.from_db_authenticated_session(
                stored_session)
            self._sessions[stored_session.id] = auth_session
        session.query(db_models.AuthenticatedSession).delete()
        session.commit()
        self.logger.info(
            "restored {0:,} valid session{1} and skipped {2:,} expired session{3} from the database"
            .format(len(self._sessions),
                    ('' if len(self._sessions) == 1 else 's'), expired,
                    ('' if expired == 1 else 's')))
示例#4
0
    def handle_email_opened(self, query):
        # image size: 43 Bytes
        img_data = '47494638396101000100800100000000ffffff21f90401000001002c00000000'
        img_data += '010001000002024c01003b'
        img_data = binascii.a2b_hex(img_data)
        self.send_response(200)
        self.send_header('Content-Type', 'image/gif')
        self.send_header('Content-Length', str(len(img_data)))
        self.end_headers()
        self.wfile.write(img_data)

        msg_id = self.get_query('id')
        if not msg_id:
            return
        session = db_manager.Session()
        query = session.query(db_models.Message)
        query = query.filter_by(id=msg_id, opened=None)
        message = query.first()
        if message and not message.campaign.has_expired:
            message.opened = db_models.current_timestamp()
            message.opener_ip = self.get_client_ip()
            message.opener_user_agent = self.headers.get('user-agent', None)
            session.commit()
        session.close()
        signals.safe_send('email-opened', self.logger, self)
示例#5
0
    def __init__(self, user):
        """
		:param user: The unique identifier for the authenticated user.
		"""
        self.user = user
        self.created = db_models.current_timestamp()
        self.last_seen = self.created
        self._event_socket = None
示例#6
0
	def handle_page_visit(self):
		if not self.message_id:
			return
		if self.message_id == self.config.get('server.secret_id'):
			return
		if not self.campaign_id:
			return
		client_ip = self.get_client_ip()

		session = db_manager.Session()
		campaign = db_manager.get_row_by_id(session, db_models.Campaign, self.campaign_id)
		if campaign.has_expired:
			self.logger.info("ignoring page visit for expired campaign id: {0} from IP address: {1}".format(self.campaign_id, client_ip))
			session.close()
			return
		self.logger.info("handling a page visit for campaign id: {0} from IP address: {1}".format(self.campaign_id, client_ip))
		message = db_manager.get_row_by_id(session, db_models.Message, self.message_id)

		if message.opened is None and self.config.get_if_exists('server.set_message_opened_on_visit', True):
			message.opened = db_models.current_timestamp()
			message.opener_ip = self.get_client_ip()
			message.opener_user_agent = self.headers.get('user-agent', None)

		set_new_visit = True
		visit_id = make_uid()
		if self.visit_id:
			set_new_visit = False
			query = session.query(db_models.LandingPage)
			query = query.filter_by(campaign_id=self.campaign_id, hostname=self.vhost, page=self.request_path[1:])
			if query.count():
				visit = db_manager.get_row_by_id(session, db_models.Visit, self.visit_id)
				if visit.message_id == self.message_id:
					visit_id = self.visit_id
					visit.visit_count += 1
				else:
					set_new_visit = True

		if set_new_visit:
			kp_cookie_name = self.config.get('server.cookie_name')
			cookie = "{0}={1}; Path=/; HttpOnly".format(kp_cookie_name, visit_id)
			self.send_header('Set-Cookie', cookie)
			visit = db_models.Visit(id=visit_id, campaign_id=self.campaign_id, message_id=self.message_id)
			visit.visitor_ip = client_ip
			visit.visitor_details = self.headers.get('user-agent', '')
			session.add(visit)
			visit_count = len(campaign.visits)
			if visit_count > 0 and ((visit_count in [1, 10, 25]) or ((visit_count % 50) == 0)):
				alert_text = "{0} visits reached for campaign: {{campaign_name}}".format(visit_count)
				self.server.job_manager.job_run(self.issue_alert, (alert_text, self.campaign_id))

		self._handle_page_visit_creds(session, visit_id)
		trained = self.get_query('trained')
		if isinstance(trained, str) and trained.lower() in ['1', 'true', 'yes']:
			message.trained = True
		session.commit()
		session.close()
示例#7
0
	def __init__(self, user):
		"""
		:param user: The user object of the authenticated user.
		:type user: :py:class:`~king_phisher.server.database.models.User`
		"""
		self.user = user.id
		self.user_is_admin = user.is_admin
		self.created = db_models.current_timestamp()
		self.last_seen = self.created
		self._event_socket = None
示例#8
0
    def __init__(self, user):
        """
		:param user: The user object of the authenticated user.
		:type user: :py:class:`~king_phisher.server.database.models.User`
		"""
        self.user = user.id
        self.user_is_admin = user.is_admin
        self.created = db_models.current_timestamp()
        self.last_seen = self.created
        self._event_socket = None
示例#9
0
	def rpc_test_login(self, username, password, otp=None):
		session = db_manager.Session()
		user = session.query(db_models.User).filter_by(name=username).first()
		if not user:
			user = db_models.User(name=username)
		user.last_login = db_models.current_timestamp()
		session.add(user)
		session.commit()
		session_id = self.server.session_manager.put(user)
		session.close()
		return True, constants.ConnectionErrorReason.SUCCESS, session_id
示例#10
0
	def rpc_test_login(self, username, password, otp=None):
		session = db_manager.Session()
		user = session.query(db_models.User).filter_by(name=username).first()
		if not user:
			user = db_models.User(name=username)
		user.last_login = db_models.current_timestamp()
		session.add(user)
		session.commit()
		session_id = self.server.session_manager.put(user)
		session.close()
		return True, constants.ConnectionErrorReason.SUCCESS, session_id
示例#11
0
	def clean(self):
		"""Remove sessions which have expired."""
		should_lock = not self._lock.locked()
		if should_lock:
			self._lock.acquire()
		oldest = db_models.current_timestamp() - self.session_timeout
		remove = []
		for session_id, session in self._sessions.items():
			if session.last_seen < oldest:
				remove.append(session_id)
		for session_id in remove:
			del self._sessions[session_id]
		if should_lock:
			self._lock.release()
		return
示例#12
0
 def clean(self):
     """Remove sessions which have expired."""
     should_lock = not self._lock.locked()
     if should_lock:
         self._lock.acquire()
     oldest = db_models.current_timestamp() - self.session_timeout
     remove = []
     for session_id, session in self._sessions.items():
         if session.last_seen < oldest:
             remove.append(session_id)
     for session_id in remove:
         del self._sessions[session_id]
     if should_lock:
         self._lock.release()
     return
示例#13
0
    def issue_alert(self, campaign_id, table, count):
        """
		Send a campaign alert for the specified table.

		:param int campaign_id: The campaign subscribers to send the alert to.
		:param str table: The type of event to use as the sender when it is forwarded.
		:param int count: The number associated with the event alert.
		"""
        session = db_manager.Session()
        campaign = db_manager.get_row_by_id(session, db_models.Campaign,
                                            campaign_id)
        now = db_models.current_timestamp()
        alert_subscriptions = tuple(
            subscription for subscription in campaign.alert_subscriptions
            if not subscription.has_expired)
        if not alert_subscriptions:
            self.server.logger.debug(
                "no active alert subscriptions are present for campaign id: {0} ({1})"
                .format(campaign.id, campaign.name))
            session.close()
            return
        if not signals.campaign_alert.receivers:
            self.server.logger.warning(
                'users are subscribed to campaign alerts, and no signal handlers are connected'
            )
            session.close()
            return
        if not signals.campaign_alert.has_receivers_for(table):
            self.server.logger.info(
                'users are subscribed to campaign alerts, and no signal handlers are connected for sender: '
                + table)
            session.close()
            return

        for subscription in alert_subscriptions:
            results = signals.send_safe('campaign-alert',
                                        self.server.logger,
                                        table,
                                        alert_subscription=subscription,
                                        count=count)
            if any((result for (_, result) in results)):
                continue
            self.server.logger.warning(
                "user {0} is subscribed to campaign alerts, and no signal handlers succeeded to send an alert"
                .format(subscription.user.name))
        session.close()
        return
示例#14
0
    def _maintenance(self, interval):
        """
		Execute periodic maintenance related tasks.

		:param int interval: The interval of time (in seconds) at which this method is being executed.
		"""
        self.logger.debug('running periodic maintenance tasks')
        now = db_models.current_timestamp()
        session = db_manager.Session()
        campaigns = session.query(db_models.Campaign).filter(
            db_models.Campaign.expiration != None).filter(
                db_models.Campaign.expiration < now).filter(
                    db_models.Campaign.expiration >= now -
                    datetime.timedelta(seconds=interval))
        for campaign in campaigns:
            signals.send_safe('campaign-expired', self.logger, campaign)
            _send_safe_campaign_alerts(campaign, 'campaign-alert-expired',
                                       campaign)
        session.close()
示例#15
0
	def _maintenance(self, interval):
		"""
		Execute periodic maintenance related tasks.

		:param int interval: The interval of time (in seconds) at which this method is being executed.
		"""
		self.logger.debug('running periodic maintenance tasks')
		now = db_models.current_timestamp()
		session = db_manager.Session()
		campaigns = session.query(db_models.Campaign).filter(
			db_models.Campaign.expiration != None
		).filter(
			db_models.Campaign.expiration < now
		).filter(
			db_models.Campaign.expiration >= now - datetime.timedelta(seconds=interval)
		)
		for campaign in campaigns:
			signals.send_safe('campaign-expired', self.logger, campaign)
			_send_safe_campaign_alerts(campaign, 'campaign-alert-expired', campaign)
		session.close()
示例#16
0
def rpc_login(handler, session, username, password, otp=None):
	logger = logging.getLogger('KingPhisher.Server.Authentication')
	if not ipaddress.ip_address(handler.client_address[0]).is_loopback:
		logger.warning("failed login request from {0} for user {1}, (invalid source address)".format(handler.client_address[0], username))
		raise ValueError('invalid source address for login')
	fail_default = (False, ConnectionErrorReason.ERROR_INVALID_CREDENTIALS, None)
	fail_otp = (False, ConnectionErrorReason.ERROR_INVALID_OTP, None)

	if not (username and password):
		logger.warning("failed login request from {0} for user {1}, (missing username or password)".format(handler.client_address[0], username))
		return fail_default
	if not handler.server.forked_authenticator.authenticate(username, password):
		logger.warning("failed login request from {0} for user {1}, (authentication failed)".format(handler.client_address[0], username))
		return fail_default

	user = session.query(db_models.User).filter_by(name=username).first()
	if not user:
		logger.info('creating new user object with name: ' + username)
		user = db_models.User(name=username)
	elif user.has_expired:
		logger.warning("failed login request from {0} for user {1}, (user has expired)".format(handler.client_address[0], username))
		return fail_default
	elif user.otp_secret:
		if otp is None:
			logger.debug("failed login request from {0} for user {1}, (missing otp)".format(handler.client_address[0], username))
			return fail_otp
		if not (isinstance(otp, str) and len(otp) == 6 and otp.isdigit()):
			logger.warning("failed login request from {0} for user {1}, (invalid otp)".format(handler.client_address[0], username))
			return fail_otp
		totp = pyotp.TOTP(user.otp_secret)
		now = datetime.datetime.now()
		if otp not in (totp.at(now + datetime.timedelta(seconds=offset)) for offset in (0, -30, 30)):
			logger.warning("failed login request from {0} for user {1}, (invalid otp)".format(handler.client_address[0], username))
			return fail_otp
	user.last_login = db_models.current_timestamp()
	session.add(user)
	session.commit()
	session_id = handler.server.session_manager.put(user.id)
	logger.info("successful login request from {0} for user {1}".format(handler.client_address[0], username))
	signals.send_safe('rpc-user-logged-in', logger, handler, session=session_id, name=username)
	return True, ConnectionErrorReason.SUCCESS, session_id
示例#17
0
def rpc_login(handler, session, username, password, otp=None):
	logger = logging.getLogger('KingPhisher.Server.Authentication')
	if not ipaddress.ip_address(handler.client_address[0]).is_loopback:
		logger.warning("failed login request from {0} for user {1}, (invalid source address)".format(handler.client_address[0], username))
		raise ValueError('invalid source address for login')
	fail_default = (False, ConnectionErrorReason.ERROR_INVALID_CREDENTIALS, None)
	fail_otp = (False, ConnectionErrorReason.ERROR_INVALID_OTP, None)

	if not (username and password):
		logger.warning("failed login request from {0} for user {1}, (missing username or password)".format(handler.client_address[0], username))
		return fail_default
	if not handler.server.forked_authenticator.authenticate(username, password):
		logger.warning("failed login request from {0} for user {1}, (authentication failed)".format(handler.client_address[0], username))
		return fail_default

	user = session.query(db_models.User).filter_by(name=username).first()
	if not user:
		logger.info('creating new user object with name: ' + username)
		user = db_models.User(name=username)
	elif user.has_expired:
		logger.warning("failed login request from {0} for user {1}, (user has expired)".format(handler.client_address[0], username))
		return fail_default
	elif user.otp_secret:
		if otp is None:
			logger.debug("failed login request from {0} for user {1}, (missing otp)".format(handler.client_address[0], username))
			return fail_otp
		if not (isinstance(otp, str) and len(otp) == 6 and otp.isdigit()):
			logger.warning("failed login request from {0} for user {1}, (invalid otp)".format(handler.client_address[0], username))
			return fail_otp
		totp = pyotp.TOTP(user.otp_secret)
		now = datetime.datetime.now()
		if otp not in (totp.at(now + datetime.timedelta(seconds=offset)) for offset in (0, -30, 30)):
			logger.warning("failed login request from {0} for user {1}, (invalid otp)".format(handler.client_address[0], username))
			return fail_otp
	user.last_login = db_models.current_timestamp()
	session.add(user)
	session.commit()
	session_id = handler.server.session_manager.put(user)
	logger.info("successful login request from {0} for user {1}".format(handler.client_address[0], username))
	signals.send_safe('rpc-user-logged-in', logger, handler, session=session_id, name=username)
	return True, ConnectionErrorReason.SUCCESS, session_id
示例#18
0
	def handle_email_opened(self, query):
		# image size: 43 Bytes
		img_data = '47494638396101000100800100000000ffffff21f90401000001002c00000000'
		img_data += '010001000002024c01003b'
		img_data = binascii.a2b_hex(img_data)
		self.send_response(200)
		self.send_header('Content-Type', 'image/gif')
		self.send_header('Content-Length', str(len(img_data)))
		self.end_headers()
		self.wfile.write(img_data)

		msg_id = self.get_query('id')
		if not msg_id:
			return
		session = db_manager.Session()
		query = session.query(db_models.Message)
		query = query.filter_by(id=msg_id, opened=None)
		message = query.first()
		if message:
			message.opened = db_models.current_timestamp()
			session.commit()
		session.close()
示例#19
0
    def handle_email_opened(self, query):
        # image size: 43 Bytes
        img_data = '47494638396101000100800100000000ffffff21f90401000001002c00000000'
        img_data += '010001000002024c01003b'
        img_data = binascii.a2b_hex(img_data)
        self.send_response(200)
        self.send_header('Content-Type', 'image/gif')
        self.send_header('Content-Length', str(len(img_data)))
        self.end_headers()
        self.wfile.write(img_data)

        msg_id = self.get_query('id')
        if not msg_id:
            return
        session = db_manager.Session()
        query = session.query(db_models.Message)
        query = query.filter_by(id=msg_id, opened=None)
        message = query.first()
        if message:
            message.opened = db_models.current_timestamp()
            session.commit()
        session.close()
示例#20
0
    def handle_email_opened(self, query):
        # image size: 43 Bytes
        img_data = "47494638396101000100800100000000ffffff21f90401000001002c00000000"
        img_data += "010001000002024c01003b"
        img_data = binascii.a2b_hex(img_data)
        self.send_response(200)
        self.send_header("Content-Type", "image/gif")
        self.send_header("Content-Length", str(len(img_data)))
        self.end_headers()
        self.wfile.write(img_data)

        msg_id = self.get_query("id")
        if not msg_id:
            return
        session = db_manager.Session()
        query = session.query(db_models.Message)
        query = query.filter_by(id=msg_id, opened=None)
        message = query.first()
        if message and not message.campaign.has_expired:
            message.opened = db_models.current_timestamp()
            message.opener_ip = self.get_client_ip()
            message.opener_user_agent = self.headers.get("user-agent", None)
            session.commit()
        session.close()
示例#21
0
	def get(self, session_id, update_timestamp=True):
		"""
		Look up an :py:class:`.AuthenticatedSession` instance from it's unique
		identifier and optionally update the last seen timestamp. If the session
		is not found or has expired, None will be returned.

		:param str session_id: The unique identifier of the session to retrieve.
		:param bool update_timestamp: Whether or not to update the last seen timestamp for the session.
		:return: The session if it exists and is active.
		:rtype: :py:class:`.AuthenticatedSession`
		"""
		if session_id is None:
			return None
		now = db_models.current_timestamp()
		with self._lock:
			session = self._sessions.get(session_id)
			if session is None:
				return None
			if session.last_seen < now - self.session_timeout:
				del self._sessions[session_id]
				return None
			if update_timestamp:
				session.last_seen = now
		return session
示例#22
0
    def get(self, session_id, update_timestamp=True):
        """
		Look up an :py:class:`.AuthenticatedSession` instance from it's unique
		identifier and optionally update the last seen timestamp. If the session
		is not found or has expired, None will be returned.

		:param str session_id: The unique identifier of the session to retrieve.
		:param bool update_timestamp: Whether or not to update the last seen timestamp for the session.
		:return: The session if it exists and is active.
		:rtype: :py:class:`.AuthenticatedSession`
		"""
        if session_id is None:
            return None
        now = db_models.current_timestamp()
        with self._lock:
            session = self._sessions.get(session_id)
            if session is None:
                return None
            if session.last_seen < now - self.session_timeout:
                del self._sessions[session_id]
                return None
            if update_timestamp:
                session.last_seen = now
        return session
示例#23
0
	def handle_page_visit(self):
		if not self.message_id:
			return
		if self.message_id == self.config.get('server.secret_id'):
			return
		if not self.campaign_id:
			return
		client_ip = self.get_client_ip()

		session = db_manager.Session()
		campaign = db_manager.get_row_by_id(session, db_models.Campaign, self.campaign_id)
		if campaign.has_expired:
			self.logger.info("ignoring page visit for expired campaign id: {0} from IP address: {1}".format(self.campaign_id, client_ip))
			session.close()
			return
		self.logger.info("handling a page visit for campaign id: {0} from IP address: {1}".format(self.campaign_id, client_ip))
		message = db_manager.get_row_by_id(session, db_models.Message, self.message_id)

		if message.opened is None and self.config.get('server.set_message_opened_on_visit'):
			message.opened = db_models.current_timestamp()
			message.opener_ip = self.get_client_ip()
			message.opener_user_agent = self.headers.get('user-agent', None)

		query = session.query(db_models.LandingPage)
		query = query.filter_by(campaign_id=self.campaign_id, hostname=self.vhost, page=self.request_path[1:])
		landing_page = query.first()

		set_new_visit = True
		visit_id = None
		if self.visit_id:
			visit_id = self.visit_id
			set_new_visit = False
			if landing_page:
				visit = db_manager.get_row_by_id(session, db_models.Visit, self.visit_id)
				if visit.message_id == self.message_id:
					visit.count += 1
					visit.last_seen = db_models.current_timestamp()
					session.commit()
				else:
					set_new_visit = True
					visit_id = None

		if visit_id is None:
			visit_id = utilities.make_visit_uid()

		if landing_page and set_new_visit:
			kp_cookie_name = self.config.get('server.cookie_name')
			cookie = "{0}={1}; Path=/; HttpOnly".format(kp_cookie_name, visit_id)
			self.send_header('Set-Cookie', cookie)
			visit = db_models.Visit(id=visit_id, campaign_id=self.campaign_id, message_id=self.message_id)
			visit.ip = client_ip
			visit.first_landing_page_id = landing_page.id
			visit.user_agent = self.headers.get('user-agent', '')
			session.add(visit)
			session.commit()
			self.logger.debug("visit id: {0} created for message id: {1}".format(visit_id, self.message_id))
			visit_count = len(campaign.visits)
			if visit_count > 0 and ((visit_count in (1, 10, 25)) or ((visit_count % 50) == 0)):
				self.server.job_manager.job_run(self.issue_alert, (self.campaign_id, 'visits', visit_count))
			signals.send_safe('visit-received', self.logger, self)

		self._handle_page_visit_creds(session, visit_id)
		trained = self.get_query('trained')
		if isinstance(trained, str) and trained.lower() in ['1', 'true', 'yes']:
			message.trained = True
			session.commit()
		session.close()
示例#24
0
    def handle_page_visit(self):
        if not self.message_id:
            return
        if self.message_id == self.config.get('server.secret_id'):
            return
        if not self.campaign_id:
            return
        client_ip = self.get_client_ip()

        session = db_manager.Session()
        campaign = db_manager.get_row_by_id(session, db_models.Campaign,
                                            self.campaign_id)
        if campaign.has_expired:
            self.logger.info(
                "ignoring page visit for expired campaign id: {0} from IP address: {1}"
                .format(self.campaign_id, client_ip))
            session.close()
            return
        self.logger.info(
            "handling a page visit for campaign id: {0} from IP address: {1}".
            format(self.campaign_id, client_ip))
        message = db_manager.get_row_by_id(session, db_models.Message,
                                           self.message_id)

        if message.opened is None and self.config.get_if_exists(
                'server.set_message_opened_on_visit', True):
            message.opened = db_models.current_timestamp()
            message.opener_ip = self.get_client_ip()
            message.opener_user_agent = self.headers.get('user-agent', None)

        set_new_visit = True
        visit_id = None
        if self.visit_id:
            visit_id = self.visit_id
            set_new_visit = False
            query = session.query(db_models.LandingPage)
            query = query.filter_by(campaign_id=self.campaign_id,
                                    hostname=self.vhost,
                                    page=self.request_path[1:])
            if query.count():
                visit = db_manager.get_row_by_id(session, db_models.Visit,
                                                 self.visit_id)
                if visit.message_id == self.message_id:
                    visit.visit_count += 1
                    visit.last_visit = db_models.current_timestamp()
                else:
                    set_new_visit = True
                    visit_id = None

        if visit_id is None:
            visit_id = make_uid()

        if set_new_visit:
            kp_cookie_name = self.config.get('server.cookie_name')
            cookie = "{0}={1}; Path=/; HttpOnly".format(
                kp_cookie_name, visit_id)
            self.send_header('Set-Cookie', cookie)
            visit = db_models.Visit(id=visit_id,
                                    campaign_id=self.campaign_id,
                                    message_id=self.message_id)
            visit.visitor_ip = client_ip
            visit.visitor_details = self.headers.get('user-agent', '')
            session.add(visit)
            visit_count = len(campaign.visits)
            if visit_count > 0 and ((visit_count in (1, 10, 25)) or
                                    ((visit_count % 50) == 0)):
                alert_text = "{0} visits reached for campaign: {{campaign_name}}".format(
                    visit_count)
                self.server.job_manager.job_run(self.issue_alert,
                                                (alert_text, self.campaign_id))
            signals.safe_send('visit-received', self.logger, self)

        if visit_id is None:
            self.logger.error('the visit id has not been set')
            raise RuntimeError('the visit id has not been set')
        self._handle_page_visit_creds(session, visit_id)
        trained = self.get_query('trained')
        if isinstance(trained,
                      str) and trained.lower() in ['1', 'true', 'yes']:
            message.trained = True
        session.commit()
        session.close()
示例#25
0
    def handle_page_visit(self):
        if not self.message_id:
            return
        if self.message_id == self.config.get('server.secret_id'):
            return
        if not self.campaign_id:
            return
        self.logger.info(
            "handling a page visit for campaign id: {0} from IP address: {1}".
            format(self.campaign_id, self.client_address[0]))
        message_id = self.message_id
        campaign_id = self.campaign_id
        session = db_manager.Session()
        campaign = db_manager.get_row_by_id(session, db_models.Campaign,
                                            self.campaign_id)
        message = db_manager.get_row_by_id(session, db_models.Message,
                                           self.message_id)

        if message.opened == None and self.config.get_if_exists(
                'server.set_message_opened_on_visit', True):
            message.opened = db_models.current_timestamp()

        set_new_visit = True
        if self.visit_id:
            set_new_visit = False
            visit_id = self.visit_id
            query = session.query(db_models.LandingPage)
            query = query.filter_by(campaign_id=self.campaign_id,
                                    hostname=self.vhost,
                                    page=self.request_path[1:])
            if query.count():
                visit = db_manager.get_row_by_id(session, db_models.Visit,
                                                 visit_id)
                if visit.message_id == message_id:
                    visit.visit_count += 1
                else:
                    set_new_visit = True

        if set_new_visit:
            visit_id = make_uid()
            kp_cookie_name = self.config.get('server.cookie_name')
            cookie = "{0}={1}; Path=/; HttpOnly".format(
                kp_cookie_name, visit_id)
            self.send_header('Set-Cookie', cookie)
            visit = db_models.Visit(id=visit_id,
                                    campaign_id=campaign_id,
                                    message_id=message_id)
            visit.visitor_ip = self.client_address[0]
            visit.visitor_details = self.headers.get('user-agent', '')
            session.add(visit)
            visit_count = len(campaign.visits)
            if visit_count > 0 and ((visit_count in [1, 10, 25]) or
                                    ((visit_count % 50) == 0)):
                alert_text = "{0} vists reached for campaign: {{campaign_name}}".format(
                    visit_count)
                self.server.job_manager.job_run(self.issue_alert,
                                                (alert_text, campaign_id))

        username = None
        for pname in ['username', 'user', 'u']:
            username = (self.get_query_parameter(pname)
                        or self.get_query_parameter(pname.title())
                        or self.get_query_parameter(pname.upper()))
            if username:
                break
        if username:
            password = None
            for pname in ['password', 'pass', 'p']:
                password = (self.get_query_parameter(pname)
                            or self.get_query_parameter(pname.title())
                            or self.get_query_parameter(pname.upper()))
                if password:
                    break
            password = (password or '')
            cred_count = 0
            query = session.query(db_models.Credential)
            query = query.filter_by(message_id=message_id,
                                    username=username,
                                    password=password)
            if query.count() == 0:
                cred = db_models.Credential(campaign_id=campaign_id,
                                            message_id=message_id,
                                            visit_id=visit_id)
                cred.username = username
                cred.password = password
                session.add(cred)
                cred_count = len(campaign.credentials)
            if cred_count > 0 and ((cred_count in [1, 5, 10]) or
                                   ((cred_count % 25) == 0)):
                alert_text = "{0} credentials submitted for campaign: {{campaign_name}}".format(
                    cred_count)
                self.server.job_manager.job_run(self.issue_alert,
                                                (alert_text, campaign_id))

        trained = self.get_query_parameter('trained')
        if isinstance(trained,
                      str) and trained.lower() in ['1', 'true', 'yes']:
            message.trained = True
        session.commit()
        session.close()
示例#26
0
	def handle_page_visit(self):
		if not self.message_id:
			return
		if self.message_id == self.config.get('server.secret_id'):
			return
		if not self.campaign_id:
			return
		client_ip = self.get_client_ip()
		headers = []

		campaign = db_manager.get_row_by_id(self._session, db_models.Campaign, self.campaign_id)
		if campaign.has_expired:
			self.logger.info("ignoring page visit for expired campaign id: {0} from IP address: {1}".format(self.campaign_id, client_ip))
			return
		self.logger.info("handling a page visit for campaign id: {0} from IP address: {1}".format(self.campaign_id, client_ip))
		message = db_manager.get_row_by_id(self._session, db_models.Message, self.message_id)

		if message.opened is None and self.config.get('server.set_message_opened_on_visit'):
			message.opened = db_models.current_timestamp()
			message.opener_ip = self.get_client_ip()
			message.opener_user_agent = self.headers.get('user-agent', None)

		query = self._session.query(db_models.LandingPage)
		query = query.filter_by(campaign_id=self.campaign_id, hostname=self.vhost, page=self.request_path[1:])
		landing_page = query.first()

		set_new_visit = True
		visit_id = None
		if self.visit_id:
			visit_id = self.visit_id
			set_new_visit = False
			if landing_page:
				visit = db_manager.get_row_by_id(self._session, db_models.Visit, self.visit_id)
				if visit.message_id == self.message_id:
					visit.count += 1
					visit.last_seen = db_models.current_timestamp()
					self._session.commit()
				else:
					set_new_visit = True
					visit_id = None

		if visit_id is None:
			visit_id = utilities.make_visit_uid()

		if landing_page and set_new_visit:
			kp_cookie_name = self.config.get('server.cookie_name')
			cookie = "{0}={1}; Path=/; HttpOnly".format(kp_cookie_name, visit_id)
			headers.append(('Set-Cookie', cookie))
			visit = db_models.Visit(id=visit_id, campaign_id=self.campaign_id, message_id=self.message_id)
			visit.ip = client_ip
			visit.first_landing_page_id = landing_page.id
			visit.user_agent = self.headers.get('user-agent', '')
			self._session.add(visit)
			self._session.commit()
			self.logger.debug("visit id: {0} created for message id: {1}".format(visit_id, self.message_id))
			visit_count = len(campaign.visits)
			if visit_count > 0 and ((visit_count in (1, 10, 25)) or ((visit_count % 50) == 0)):
				self.server.job_manager.job_run(self.issue_alert, (self.campaign_id, 'visits', visit_count))
			signals.send_safe('visit-received', self.logger, self)

		self._handle_page_visit_creds(campaign, visit_id)
		trained = self.get_query('trained')
		if isinstance(trained, str) and trained.lower() in ['1', 'true', 'yes']:
			message.trained = True
			self._session.commit()
		return headers
示例#27
0
	def handle_deaddrop_visit(self, query):
		self.send_response(200)
		self.end_headers()

		data = self.get_query('token')
		if not data:
			self.logger.warning('dead drop request received with no \'token\' parameter')
			return
		try:
			data = base64.b64decode(data)
		except (binascii.Error, TypeError):
			self.logger.error('dead drop request received with invalid \'token\' data')
			return
		data = xor.xor_decode(data)
		try:
			data = json.loads(data)
		except ValueError:
			self.logger.error('dead drop request received with invalid \'token\' data')
			return

		deaddrop_id = data.get('deaddrop_id')
		if deaddrop_id is None:
			self.logger.error('dead drop request received with no \'deaddrop_id\' key')
			return
		elif deaddrop_id == self.config.get('server.secret_id'):
			# this allows us to test the logic to this point at least
			self.logger.debug('dead drop request received with the test id')
			return

		self.semaphore_acquire()
		deployment = db_manager.get_row_by_id(self._session, db_models.DeaddropDeployment, deaddrop_id)
		if not deployment:
			self.semaphore_release()
			self.logger.error('dead drop request received for an unknown campaign')
			return
		if deployment.campaign.has_expired:
			self.semaphore_release()
			self.logger.info('dead drop request received for an expired campaign')
			return

		local_username = data.get('local_username')
		local_hostname = data.get('local_hostname')
		if local_username is None or local_hostname is None:
			self.semaphore_release()
			self.logger.error('dead drop request received with missing data')
			return
		local_ip_addresses = data.get('local_ip_addresses')
		if isinstance(local_ip_addresses, (list, tuple)):
			local_ip_addresses = ' '.join(local_ip_addresses)

		query = self._session.query(db_models.DeaddropConnection)
		query = query.filter_by(deployment_id=deployment.id, local_username=local_username, local_hostname=local_hostname)
		connection = query.first()
		if connection:
			connection.count += 1
			connection.last_seen = db_models.current_timestamp()
			new_connection = False
		else:
			connection = db_models.DeaddropConnection(campaign_id=deployment.campaign_id, deployment_id=deployment.id)
			connection.ip = self.get_client_ip()
			connection.local_username = local_username
			connection.local_hostname = local_hostname
			connection.local_ip_addresses = local_ip_addresses
			self._session.add(connection)
			new_connection = True
		self._session.commit()

		query = self._session.query(db_models.DeaddropConnection)
		query = query.filter_by(campaign_id=deployment.campaign_id)
		visit_count = query.count()
		self.semaphore_release()
		if new_connection and visit_count > 0 and ((visit_count in [1, 3, 5]) or ((visit_count % 10) == 0)):
			self.server.job_manager.job_run(self.issue_alert, (deployment.campaign_id, 'deaddrop_connections', visit_count))
		return
示例#28
0
	def handle_deaddrop_visit(self, query):
		self.send_response(200)
		self.end_headers()

		data = self.get_query('token')
		if not data:
			self.logger.warning('dead drop request received with no \'token\' parameter')
			return
		try:
			data = base64.b64decode(data)
		except (binascii.Error, TypeError):
			self.logger.error('dead drop request received with invalid \'token\' data')
			return
		data = xor.xor_decode(data)
		try:
			data = json.loads(data)
		except ValueError:
			self.logger.error('dead drop request received with invalid \'token\' data')
			return

		self.semaphore_acquire()
		session = db_manager.Session()
		deployment = db_manager.get_row_by_id(session, db_models.DeaddropDeployment, data.get('deaddrop_id'))
		if not deployment:
			session.close()
			self.semaphore_release()
			self.logger.error('dead drop request received for an unknown campaign')
			return
		if deployment.campaign.has_expired:
			session.close()
			self.semaphore_release()
			self.logger.info('dead drop request received for an expired campaign')
			return

		local_username = data.get('local_username')
		local_hostname = data.get('local_hostname')
		if local_username is None or local_hostname is None:
			session.close()
			self.semaphore_release()
			self.logger.error('dead drop request received with missing data')
			return
		local_ip_addresses = data.get('local_ip_addresses')
		if isinstance(local_ip_addresses, (list, tuple)):
			local_ip_addresses = ' '.join(local_ip_addresses)

		query = session.query(db_models.DeaddropConnection)
		query = query.filter_by(deployment_id=deployment.id, local_username=local_username, local_hostname=local_hostname)
		connection = query.first()
		if connection:
			connection.count += 1
			connection.last_seen = db_models.current_timestamp()
			new_connection = False
		else:
			connection = db_models.DeaddropConnection(campaign_id=deployment.campaign_id, deployment_id=deployment.id)
			connection.ip = self.get_client_ip()
			connection.local_username = local_username
			connection.local_hostname = local_hostname
			connection.local_ip_addresses = local_ip_addresses
			session.add(connection)
			new_connection = True
		session.commit()

		query = session.query(db_models.DeaddropConnection)
		query = query.filter_by(campaign_id=deployment.campaign_id)
		visit_count = query.count()
		session.close()
		self.semaphore_release()
		if new_connection and visit_count > 0 and ((visit_count in [1, 3, 5]) or ((visit_count % 10) == 0)):
			self.server.job_manager.job_run(self.issue_alert, (deployment.campaign_id, 'deaddrop_connections', visit_count))
		return