def test_is_valid_ip_address(self): valid_ips = ['127.0.0.1', '10.0.0.1', '200.100.0.1', 'fe80::1', '::1'] invalid_ips = ['localhost', 'www.google.com', ''] for address in valid_ips: self.assertTrue(utilities.is_valid_ip_address(address)) for address in invalid_ips: self.assertFalse(utilities.is_valid_ip_address(address))
def test_is_valid_ip_address(self): valid_ips = [ '127.0.0.1', '10.0.0.1', '200.100.0.1', 'fe80::1', '::1' ] invalid_ips = [ 'localhost', 'www.google.com', '' ] for address in valid_ips: self.assertTrue(utilities.is_valid_ip_address(address)) for address in invalid_ips: self.assertFalse(utilities.is_valid_ip_address(address))
def main(): parser = argparse.ArgumentParser( description='King Phisher SPF Check Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server') parser.add_argument('target_email', help='the email address that messages are from') arguments = parser.parse_args() utilities.configure_stream_logger(arguments.loglvl, arguments.logger) server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not utilities.is_valid_ip_address(server_ip): color.print_error('the smtp server ip address specified is invalid') return if not '@' in target_email: target_email = utilities.random_string_lower_numeric( 8) + '@' + target_email color.print_status( 'target email appears to be just a domain, changed to: ' + target_email) if not utilities.is_valid_email_address(target_email): color.print_error('the email address specified is invalid') return spf_sender, spf_domain = target_email.split('@') spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender) try: result = spf_test.check_host() except spf.SPFPermError as error: color.print_error('check_host failed with error: permerror') color.print_error('error reason: ' + error.message) return except spf.SPFTempError as error: color.print_error('check_host failed with error: temperror') color.print_error('error reason: ' + error.message) return if not result: color.print_status('no spf policy was found for the specified domain') return color.print_good("spf policy result: {0}".format(result)) color.print_status('top level spf records found:') for rid in range(len(spf_test.spf_records)): record = spf.record_unparse(spf_test.spf_records[rid]) color.print_status(" #{0} {1: <10} {2}".format( rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
def main(): parser = argparse.ArgumentParser(description='King Phisher SPF Check Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server') parser.add_argument('target_email', help='the email address that messages are from') arguments = parser.parse_args() utilities.configure_stream_logger(arguments.loglvl, arguments.logger) server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not utilities.is_valid_ip_address(server_ip): color.print_error('the smtp server ip address specified is invalid') return if not '@' in target_email: target_email = utilities.random_string_lower_numeric(8) + '@' + target_email color.print_status('target email appears to be just a domain, changed to: ' + target_email) if not utilities.is_valid_email_address(target_email): color.print_error('the email address specified is invalid') return spf_sender, spf_domain = target_email.split('@') spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender) try: result = spf_test.check_host() except spf.SPFPermError as error: color.print_error('check_host failed with error: permerror') color.print_error('error reason: ' + error.message) return except spf.SPFTempError as error: color.print_error('check_host failed with error: temperror') color.print_error('error reason: ' + error.message) return if not result: color.print_status('no spf policy was found for the specified domain') return color.print_good("spf policy result: {0}".format(result)) color.print_status('top level spf records found:') for rid in range(len(spf_test.spf_records)): record = spf.record_unparse(spf_test.spf_records[rid]) color.print_status(" #{0} {1: <10} {2}".format(rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
def main(): parser = argparse.ArgumentParser(description='King Phisher SPF Check Utility', conflict_handler='resolve') parser.add_argument('-v', '--version', action='version', version=parser.prog + ' Version: ' + version.version) parser.add_argument('-L', '--log', dest='loglvl', action='store', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='CRITICAL', help='set the logging level') parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server') parser.add_argument('target_email', help='the email address that messages are from') arguments = parser.parse_args() logging.getLogger('').setLevel(logging.DEBUG) console_log_handler = logging.StreamHandler() console_log_handler.setLevel(getattr(logging, arguments.loglvl)) console_log_handler.setFormatter(logging.Formatter("%(levelname)-8s %(message)s")) logging.getLogger('').addHandler(console_log_handler) server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not utilities.is_valid_ip_address(server_ip): color.print_error('the smtp server ip address specified is invalid') return if not utilities.is_valid_email_address(target_email): color.print_error('the email address specified is invalid') return spf_sender, spf_domain = target_email.split('@') spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender) try: result = spf_test.check_host() except spf.SPFPermError: color.print_error('check_host failed with error: permerror') return except spf.SPFTempError: color.print_error('check_host failed with error: temperror') return if not result: color.print_status('no spf policy was found for the specified domain') return color.print_good("spf policy result: {0}".format(result)) color.print_status('top level spf records found:') for rid in range(len(spf_test.spf_records)): record = spf.record_unparse(spf_test.spf_records[rid]) color.print_status(" #{0} {1: <10} {2}".format(rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
def main(): parser = argparse.ArgumentParser(description='King Phisher SPF Check Utility', conflict_handler='resolve') parser.add_argument('-v', '--version', action='version', version=parser.prog + ' Version: ' + version.version) parser.add_argument('-L', '--log', dest='loglvl', action='store', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='CRITICAL', help='set the logging level') parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server') parser.add_argument('target_email', help='the email address that messages are from') arguments = parser.parse_args() logging.getLogger('').setLevel(logging.DEBUG) console_log_handler = logging.StreamHandler() console_log_handler.setLevel(getattr(logging, arguments.loglvl)) console_log_handler.setFormatter(logging.Formatter("%(levelname)-8s %(message)s")) logging.getLogger('').addHandler(console_log_handler) server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not utilities.is_valid_ip_address(server_ip): print('[-] the smtp server ip address specified is invalid') return if not utilities.is_valid_email_address(target_email): print('[-] the email address specified is invalid') return spf_sender, spf_domain = target_email.split('@') spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender) try: result = spf_test.check_host() except spf.SPFPermError: print('[-] check_host failed with error: permerror') return except spf.SPFTempError: print('[-] check_host failed with error: temperror') return if not result: print('[*] no spf policy was found for the specified domain') return print("[+] spf policy result: {0}".format(result)) print('[*] top level spf records found:') for rid in range(len(spf_test.spf_records)): record = spf.record_unparse(spf_test.spf_records[rid]) print("[*] #{0} {1: <10} {2}".format(rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
def guess_smtp_server_address(host, forward_host=None): """ Guess the IP address of the SMTP server that will be connected to given the SMTP host information and an optional SSH forwarding host. If a hostname is in use it will be resolved to an IP address, either IPv4 or IPv6 and in that order. If a hostname resolves to multiple IP addresses, None will be returned. This function is intended to guess the SMTP servers IP address given the client configuration so it can be used for SPF record checks. :param str host: The SMTP server that is being connected to. :param str forward_host: An optional host that is being used to tunnel the connection. :return: The IP address of the SMTP server. :rtype: None, :py:class:`ipaddress.IPv4Address`, :py:class:`ipaddress.IPv6Address` """ host = host.rsplit(':', 1)[0] if utilities.is_valid_ip_address(host): ip = ipaddress.ip_address(host) if not ip.is_loopback: return ip else: info = None for family in (socket.AF_INET, socket.AF_INET6): try: info = socket.getaddrinfo(host, 1, family) except socket.gaierror: continue info = set(list([r[4][0] for r in info])) if len(info) != 1: return break if info: ip = ipaddress.ip_address(info.pop()) if not ip.is_loopback: return ip if forward_host: return guess_smtp_server_address(forward_host) return
def get_client_ip(self): """ Intelligently get the IP address of the HTTP client, optionally accounting for proxies that may be in use. :return: The clients IP address :rtype: str """ address = self.client_address[0] cookie_name = self.config.get_if_exists('server.client_ip_cookie') if not cookie_name: return address cookie_value = self.headers.get(cookie_name, '') if not cookie_value: return address if cookie_value.startswith('['): # cookie_value looks like an IPv6 address cookie_value = cookie_value.split(']:', 1)[0] else: # treat cookie_value ad an IPv4 address cookie_value = cookie_value.split(':', 1)[0] if utilities.is_valid_ip_address(cookie_value): address = cookie_value return address
def server_connect(self): server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) username = self.config['server_username'] password = self.config['server_password'] if server[0] == 'localhost' or (utilities.is_valid_ip_address(server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_port = self.config['server_remote_port'] self.logger.info("connecting to local king-phisher instance") else: local_port = self._create_ssh_forwarder(server, username, password) if not local_port: return self.rpc = client_rpc.KingPhisherRPCClient(('localhost', local_port), username=username, password=password, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: self.rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) connection_failed = True try: assert self.rpc('client/initialize') server_version_info = self.rpc('version') assert server_version_info != None except AdvancedHTTPServerRPCError as err: if err.status == 401: self.logger.warning('failed to authenticate to the remote king phisher service') gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server responded that the credentials are invalid.') else: self.logger.warning('failed to connect to the remote rpc server with http status: ' + str(err.status)) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server responded with HTTP status: ' + str(err.status)) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except Exception as error: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False finally: if connection_failed: self.rpc = None self.server_disconnect() return server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info("successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return self.emit('server-connected') return
def signal_login_dialog_response(self, dialog, response, glade_dialog): server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' if response == Gtk.ResponseType.CANCEL or response == Gtk.ResponseType.DELETE_EVENT: dialog.destroy() self.emit('exit') return True glade_dialog.objects_save_to_config() server = utilities.server_parse(self.config['server'], 22) username = self.config['server_username'] password = self.config['server_password'] if server[0] == 'localhost' or (utilities.is_valid_ip_address( server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_port = self.config['server_remote_port'] self.logger.info("connecting to local king-phisher instance") else: local_port = self._create_ssh_forwarder(server, username, password) if not local_port: return self.rpc = KingPhisherRPCClient( ('localhost', local_port), username=username, password=password, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: self.rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) connection_failed = True try: assert self.rpc('client/initialize') server_version_info = self.rpc('version') assert server_version_info != None except AdvancedHTTPServerRPCError as err: if err.status == 401: self.logger.warning( 'failed to authenticate to the remote king phisher service' ) gui_utilities.show_dialog_error( title_rpc_error, self, 'The server responded that the credentials are invalid.') else: self.logger.warning( 'failed to connect to the remote rpc server with http status: ' + str(err.status)) gui_utilities.show_dialog_error( title_rpc_error, self, 'The server responded with HTTP status: ' + str(err.status)) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, self) except Exception as error: self.logger.warning('failed to connect to the remote rpc service') gui_utilities.show_dialog_error( title_rpc_error, self, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False finally: if connection_failed: self.rpc = None self.server_disconnect() return server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) self.server_local_port = local_port error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', self, error_text) self.server_disconnect() return dialog.destroy() self.emit('server-connected') return
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if server[0] == 'localhost' or (utilities.is_valid_ip_address( server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) connection_failed = True try: server_version_info = rpc('version') assert server_version_info is not None except AdvancedHTTPServerRPCError as error: self.logger.warning( 'failed to connect to the remote rpc service with http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format( str(error.status))) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False if connection_failed: self.server_disconnect() return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.server_disconnect() return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') self.rpc = rpc self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if server[0] == 'localhost' or (utilities.is_valid_ip_address(server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient(local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) connection_failed = True try: server_version_info = rpc('version') assert server_version_info is not None except AdvancedHTTPServerRPCError as error: self.logger.warning('failed to connect to the remote rpc service with http status: ' + str(error.status)) gui_utilities.show_dialog_error(title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format(str(error.status))) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning('failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False if connection_failed: self.server_disconnect() return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format( server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1] ) ) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning('failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.server_disconnect() return False, login_reason rpc.username = username self.logger.debug('successfully authenticated to the remote king phisher service') self.rpc = rpc self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS