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.logger, arguments.loglvl) server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not ipaddress.is_valid(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.SPFParseError as error: color.print_error('check_host failed with error: permerror (parsing failed)') color.print_error('error reason: ' + error.message) return 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:') match = spf_test.match for record_id, record in enumerate(spf_test.records.values(), 1): color.print_status(" #{0} {1: <10} {2}".format( record_id, ('(matched)' if match.record == record else ''), record.domain )) for directive_id, directive in enumerate(record.directives, 1): color.print_status(" #{0}.{1} {2: <10} {3}".format( record_id, directive_id, ('(matched)' if match.record == record and match.directive == directive else ''), directive ))
def main(): parser = argparse.ArgumentParser( description='King Phisher Signing-Key Generation Utility', conflict_handler='resolve') utilities.argp_add_args(parser) subparsers = parser.add_subparsers(dest='subcommand') subparsers.required = True parser_display = subparsers.add_parser('display') parser_display.set_defaults(action=action_display) parser_display.add_argument('file', default=os.getenv('KING_PHISHER_DEV_KEY'), nargs='?', help='the key file to display') parser_generate = subparsers.add_parser('generate') parser_generate.set_defaults(action=action_generate) parser_generate.add_argument('id', help='this key\'s identifier') parser_generate.add_argument('file', type=argparse.FileType('w'), help='the destination to write the key to') arguments = parser.parse_args() find.init_data_path() arguments.action(arguments)
def main(): parser = argparse.ArgumentParser(description='King Phisher Interactive Database Console', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', type=argparse.FileType('r'), help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = yaml.load(arguments.server_config) database_connection_url = server_config['server']['database'] else: raise RuntimeError('no database connection was specified') engine = manager.init_database(database_connection_url) session = manager.Session() rpc_session = aaa.AuthenticatedSession(user=getpass.getuser()) console = code.InteractiveConsole(dict( engine=engine, graphql=graphql, graphql_query=graphql_query, manager=manager, models=models, pprint=pprint.pprint, rpc_session=rpc_session, session=session )) console.interact('starting interactive database console') if os.path.isdir(os.path.dirname(history_file)): readline.write_history_file(history_file)
def main(): parser = argparse.ArgumentParser( description='King Phisher Signing-Key Generation Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('id', help='this key\'s identifier') parser.add_argument('file', type=argparse.FileType('w'), help='the destination to write the PEM file to') arguments = parser.parse_args() curve = ecdsa.NIST521p color.print_status('generating a new ecdsa singing key') signing_key = ecdsa.SigningKey.generate(curve=curve) verifying_key = signing_key.get_verifying_key() signing_key = binascii.b2a_base64( signing_key.to_string()).decode('utf-8').strip() verifying_key = binascii.b2a_base64( verifying_key.to_string()).decode('utf-8').strip() print('public key information for inclusion in security.json:') key_info = { 'id': arguments.id, 'verifying-key': { 'data': verifying_key, 'type': curve.openssl_name } } print(serializers.JSON.dumps(key_info)) key_info['signing-key'] = {'data': signing_key, 'type': curve.openssl_name} serializers.JSON.dump(key_info, arguments.file)
def main(): parser = argparse.ArgumentParser(description='King Phisher Interactive Database Console', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = configuration.ex_load_config(arguments.server_config) database_connection_url = server_config.get('server.database') else: raise RuntimeError('no database connection was specified') engine = manager.init_database(database_connection_url) session = manager.Session() rpc_session = aaa.AuthenticatedSession(user=getpass.getuser()) console = code.InteractiveConsole(dict( engine=engine, graphql_query=graphql_query, manager=manager, models=models, pprint=pprint.pprint, rpc_session=rpc_session, session=session )) console.interact('starting interactive database console') if os.path.isdir(os.path.dirname(history_file)): readline.write_history_file(history_file)
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') parser.add_argument('--dns-timeout', dest='dns_timeout', default=spf.DEFAULT_DNS_TIMEOUT, type=int, help='the timeout for dns queries') arguments = parser.parse_args() server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not ipaddress.is_valid(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, sender=spf_sender, timeout=arguments.dns_timeout) try: result = spf_test.check_host() except spf.SPFParseError as error: color.print_error('check_host failed with error: permerror (parsing failed)') color.print_error('error reason: ' + error.message) return 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:') match = spf_test.match for record_id, record in enumerate(spf_test.records.values(), 1): color.print_status(" #{0} {1: <10} {2}".format( record_id, ('(matched)' if match.record == record else ''), record.domain )) for directive_id, directive in enumerate(record.directives, 1): color.print_status(" #{0}.{1: <2} {2: <10} {3}".format( record_id, directive_id, ('(matched)' if match.record == record and match.directive == directive else ''), directive ))
def main(): parser = argparse.ArgumentParser(description='King Phisher Server', conflict_handler='resolve') utilities.argp_add_args(parser) startup.argp_add_server(parser) arguments = parser.parse_args() # basic runtime checks if sys.version_info < (3, 4): color.print_error('the Python version is too old (minimum required is 3.4)') return 0 console_log_handler = utilities.configure_stream_logger(arguments.logger, arguments.loglvl) del parser if os.getuid(): color.print_error('the server must be started as root, configure the') color.print_error('\'server.setuid_username\' option in the config file to drop privileges') return os.EX_NOPERM # configure environment variables and load the config find.init_data_path('server') config = configuration.ex_load_config(arguments.config_file) if arguments.verify_config: color.print_good('configuration verification passed') color.print_good('all required settings are present') return os.EX_OK if config.has_option('server.data_path'): find.data_path_append(config.get('server.data_path')) if arguments.update_geoip_db: color.print_status('downloading a new geoip database') try: size = geoip.download_geolite2_city_db(config.get('server.geoip.database')) except errors.KingPhisherResourceError as error: color.print_error(error.message) return os.EX_UNAVAILABLE color.print_good("download complete, file size: {0}".format(strutils.bytes2human(size))) return os.EX_OK # setup logging based on the configuration if config.has_section('logging'): log_file = _ex_config_logging(arguments, config, console_log_handler) logger.debug("king phisher version: {0} python version: {1}.{2}.{3}".format(version.version, sys.version_info[0], sys.version_info[1], sys.version_info[2])) # initialize the plugin manager try: plugin_manager = plugins.ServerPluginManager(config) except errors.KingPhisherError as error: if isinstance(error, errors.KingPhisherPluginError): color.print_error("plugin error: {0} ({1})".format(error.plugin_name, error.message)) else: color.print_error(error.message) return os.EX_SOFTWARE status_code = build_and_run(arguments, config, plugin_manager, log_file) plugin_manager.shutdown() logging.shutdown() return status_code
def main(): parser = argparse.ArgumentParser(description='King Phisher TOTP Enrollment Utility', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', type=argparse.FileType('r'), help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') parser.add_argument('--otp', dest='otp_secret', help='a specific otp secret') parser.add_argument('user', help='the user to mange') parser.add_argument('action', choices=('remove', 'set', 'show'), help='the action to preform') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() utilities.configure_stream_logger(arguments.loglvl, arguments.logger) if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = yaml.load(arguments.server_config) database_connection_url = server_config['server']['database'] else: raise RuntimeError('no database connection was specified') manager.init_database(database_connection_url) session = manager.Session() user = session.query(models.User).filter_by(id=arguments.user).first() if not user: color.print_error("invalid user id: {0}".format(arguments.user)) return for case in utilities.switch(arguments.action): if case('remove'): user.otp_secret = None break if case('set'): if user.otp_secret: color.print_error("the specified user already has an otp secret set") return if arguments.otp_secret: new_otp = arguments.otp_secret else: new_otp = pyotp.random_base32() if len(new_otp) != 16: color.print_error("invalid otp secret length, must be 16") return user.otp_secret = new_otp break if user.otp_secret: color.print_status("user: {0} otp: {1}".format(user.id, user.otp_secret)) totp = pyotp.TOTP(user.otp_secret) uri = totp.provisioning_uri(user.id + '@king-phisher') + '&issuer=King%20Phisher' color.print_status("provisioning uri: {0}".format(uri)) else: color.print_status("user: {0} otp: N/A".format(user.id)) session.commit()
def main(): parser = argparse.ArgumentParser(description='King Phisher Client GUI', conflict_handler='resolve') utilities.argp_add_args(parser, default_root='KingPhisher') startup.argp_add_client(parser) arguments = parser.parse_args() # basic runtime checks if sys.version_info < (3, 4): color.print_error('the Python version is too old (minimum required is 3.4)') return 0 if Gtk.check_version(3, 14, 0): color.print_error('the GTK+ version is too old (minimum required is 3.14)') return 0 if sys.platform.startswith('linux') and not os.environ.get('DISPLAY'): color.print_error('no display was detected, this must be run with an interactive X session') return 0 config_file = arguments.config_file use_plugins = arguments.use_plugins use_style = arguments.use_style del arguments, parser logger = logging.getLogger('KingPhisher.Client.CLI') if sys.platform.startswith('linux') and not os.getuid(): logger.warning('it is not necessary to run the king phisher client as root') find.init_data_path('client') if not gui_utilities.which_glade(): color.print_error('unable to locate the glade ui data file') return 0 logger.debug("king phisher version: {0} python version: {1}.{2}.{3}".format(version.version, sys.version_info[0], sys.version_info[1], sys.version_info[2])) logger.debug("client running in process: {0} main tid: 0x{1:x}".format(os.getpid(), threading.current_thread().ident)) start_time = time.time() logger.debug('using ui data from glade file: ' + gui_utilities.which_glade()) try: app = application.KingPhisherClientApplication(config_file=config_file, use_plugins=use_plugins, use_style=use_style) except Exception as error: logger.critical("initialization error: {0} ({1})".format(error.__class__.__name__, getattr(error, 'message', 'n/a'))) color.print_error('failed to initialize the King Phisher client') return 0 logger.debug("client loaded in {0:.2f} seconds".format(time.time() - start_time)) GObject.threads_init() return app.run([])
def main(): parser = argparse.ArgumentParser( description='King Phisher Interactive Database Console', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = configuration.ex_load_config(arguments.server_config) database_connection_url = server_config.get('server.database') else: raise RuntimeError('no database connection was specified') engine = manager.init_database(database_connection_url) session = manager.Session() username = getpass.getuser() user = session.query(models.User).filter_by(name=username).first() if user is None: print("[-] no user {0} found in the database".format(username)) return rpc_session = aaa.AuthenticatedSession(user=user) console = code.InteractiveConsole( dict(engine=engine, graphql_query=graphql_query, manager=manager, models=models, pprint=pprint.pprint, rpc_session=rpc_session, session=session)) console.interact('starting interactive database console') if os.path.isdir(os.path.dirname(history_file)): readline.write_history_file(history_file)
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 Signing-Key Generation Utility', conflict_handler='resolve') utilities.argp_add_args(parser) subparsers = parser.add_subparsers(dest='subcommand') subparsers.required = True parser_display = subparsers.add_parser('display') parser_display.set_defaults(action=action_display) parser_display.add_argument('file', default=os.getenv('KING_PHISHER_DEV_KEY'), nargs='?', help='the key file to display') parser_generate = subparsers.add_parser('generate') parser_generate.set_defaults(action=action_generate) parser_generate.add_argument('id', help='this key\'s identifier') parser_generate.add_argument('file', type=argparse.FileType('w'), help='the destination to write the key to') arguments = parser.parse_args() find.init_data_path() arguments.action(arguments)
def main(): parser = argparse.ArgumentParser(description='King Phisher SMTP Debug Server', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('-f', '--foreground', dest='foreground', action='store_true', default=False, help='run in foreground (do not fork)') parser.add_argument('-a', '--address', dest='address', default='127.0.0.1', help='address to listen on') parser.add_argument('-p', '--port', dest='port', type=int, default=2525, help='port to listen on') arguments = parser.parse_args() del parser if (not arguments.foreground) and os.fork(): return bind_address = (arguments.address, arguments.port) server = smtp_server.BaseSMTPServer(bind_address) color.print_status("smtp server listening on {0}:{1}".format(bind_address[0], bind_address[1])) try: server.serve_forever() except KeyboardInterrupt: color.print_status('keyboard interrupt caught, now exiting')
def main(): parser = argparse.ArgumentParser(description='King Phisher SMTP Debug Server', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('-f', '--foreground', dest='foreground', action='store_true', default=False, help='run in foreground (do not fork)') parser.add_argument('-a', '--address', dest='address', default='127.0.0.1', help='address to listen on') parser.add_argument('-p', '--port', dest='port', type=int, default=2525, help='port to listen on') arguments = parser.parse_args() del parser utilities.configure_stream_logger(arguments.logger, arguments.loglvl) if (not arguments.foreground) and os.fork(): return bind_address = (arguments.address, arguments.port) server = smtp_server.BaseSMTPServer(bind_address) color.print_status("smtp server listening on {0}:{1}".format(bind_address[0], bind_address[1])) try: server.serve_forever() except KeyboardInterrupt: color.print_status('keyboard interrupt caught, now exiting')
def main(): parser = argparse.ArgumentParser(description='King Phisher Interactive Database Console', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', type=argparse.FileType('r'), help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') arguments = parser.parse_args() utilities.configure_stream_logger(arguments.loglvl, arguments.logger) if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = yaml.load(arguments.server_config) database_connection_url = server_config['server']['database'] else: raise RuntimeError('no database connection was specified') engine = manager.init_database(database_connection_url) session = manager.Session() console = code.InteractiveConsole(dict(engine=engine, manager=manager, models=models, session=session)) console.interact('starting interactive database console')
def main(): parser = argparse.ArgumentParser( conflict_handler='resolve', description=PARSER_DESCRIPTION, epilog=PARSER_EPILOG, formatter_class=argparse.RawTextHelpFormatter) utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') parser.add_argument('--force', dest='force', action='store_true', default=False, help='create the user if necessary') parser.add_argument('--otp', dest='otp_secret', help='a specific otp secret') if has_qrcode: parser.add_argument('--qrcode', dest='qrcode_filename', help='generate a qrcode image file') parser.add_argument('user', help='the user to mange') parser.add_argument('action', choices=('remove', 'set', 'show'), help='the action to preform') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = configuration.ex_load_config(arguments.server_config) database_connection_url = server_config.get('server.database') else: raise RuntimeError('no database connection was specified') manager.init_database(database_connection_url) session = manager.Session() user = session.query(models.User).filter_by(name=arguments.user).first() if not user: if not arguments.force: color.print_error("invalid user id: {0}".format(arguments.user)) return user = models.User(name=arguments.user) session.add(user) color.print_status('the specified user was created') for case in utilities.switch(arguments.action): if case('remove'): user.otp_secret = None break if case('set'): if user.otp_secret: color.print_error( "the specified user already has an otp secret set") return if arguments.otp_secret: new_otp = arguments.otp_secret else: new_otp = pyotp.random_base32() if len(new_otp) != 16: color.print_error("invalid otp secret length, must be 16") return user.otp_secret = new_otp break if user.otp_secret: color.print_status("user: {0} otp: {1}".format(user.name, user.otp_secret)) totp = pyotp.TOTP(user.otp_secret) uri = totp.provisioning_uri(user.name + '@king-phisher') + '&issuer=King%20Phisher' color.print_status("provisioning uri: {0}".format(uri)) if has_qrcode and arguments.qrcode_filename: img = qrcode.make(uri) img.save(arguments.qrcode_filename) color.print_status("wrote qrcode image to: " + arguments.qrcode_filename) else: color.print_status("user: {0} otp: N/A".format(user.id)) session.commit()
def main(): parser = argparse.ArgumentParser( description='King Phisher Certbot Wrapper Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('--certbot', dest='certbot_bin', help='the path to the certbot binary to use') parser.add_argument('--json-output', dest='json_file', help='update a json formatted file with the details') parser.add_argument('--restart-service', action='store_true', default=False, help='attempt to restart the king-phisher service') parser.add_argument('server_config', help='the server configuration file') parser.add_argument('hostnames', nargs='+', help='the host names to request certificates for') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() server_config = configuration.ex_load_config( arguments.server_config).get('server') web_root = server_config['web_root'] if os.getuid(): color.print_error('this tool must be run as root') return os.EX_NOPERM certbot_bin = arguments.certbot_bin or smoke_zephyr.utilities.which( 'certbot') if certbot_bin is None: color.print_error( 'could not identify the path to the certbot binary, make sure that it is' ) color.print_error( 'installed and see: https://certbot.eff.org/ for more details') return os.EX_UNAVAILABLE if not os.access(certbot_bin, os.R_OK | os.X_OK): color.print_error( 'found insufficient permissions on the certbot binary') return os.EX_NOPERM logger = logging.getLogger('KingPhisher.Tool.CLI.CertbotWrapper') logger.info('using certbot binary at: ' + certbot_bin) logger.debug('getting server binding information') if server_config.get('addresses'): address = server_config['addresses'][0] else: address = server_config['address'] address['ssl'] = bool(server_config.get('ssl_cert')) logger.debug( "checking that the king phisher server is running on: {host}:{port} (ssl={ssl})" .format(**address)) try: rpc = advancedhttpserver.RPCClient((address['host'], address['port']), use_ssl=address['ssl']) version = rpc('version') except (advancedhttpserver.RPCError, socket.error): logger.error('received an rpc error while checking the version', exc_info=True) color.print_error( 'failed to verify that the king phisher server is running') return os.EX_UNAVAILABLE logger.info('connected to server version: ' + version['version']) vhost_directories = server_config['vhost_directories'] if len(arguments.hostnames) > 1 and not vhost_directories: color.print_error( 'vhost_directories must be true to specify multiple hostnames') return os.EX_CONFIG for hostname in arguments.hostnames: if vhost_directories: directory = os.path.join(web_root, hostname) else: directory = web_root if os.path.split(os.path.abspath(directory))[-1] != hostname: color.print_error( 'when the vhost_directories option is not set, the web_root option' ) color.print_error('must be: ' + os.path.join(web_root, hostname)) return os.EX_CONFIG if not os.path.exists(directory): os.mkdir(directory, mode=0o775) logger.info('created directory for host at: ' + directory) certbot_args = (certbot_bin, 'certonly', '--webroot', '-w', directory, '-d', hostname) logger.info('running certbot command: ' + ' '.join(certbot_args)) proc_h = subprocess.Popen(certbot_args, shell=False) status = proc_h.wait() if status != os.EX_OK: color.print_error('certbot exited with exit status: ' + str(status)) break color.print_good('certbot exited with a successful status code') timestamp = datetime.datetime.utcnow().isoformat() + '+00:00' if not os.path.isdir(os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname)): logger.warning('failed to find the new hostname in: ' + LETS_ENCRYPT_LIVE_PATH) continue details = { 'created': timestamp, 'host': hostname, 'ssl_cert': os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname, 'fullchain.pem'), 'ssl_key': os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname, 'privkey.pem') } if arguments.json_file: existing_data = [] if os.path.isfile(arguments.json_file): with open(arguments.json_file, 'r') as file_h: existing_data = serializers.JSON.load(file_h) if not isinstance(existing_data, list): color.print_status( 'the existing json data must be a list to add the new data' ) existing_data.append(details) with open(arguments.json_file, 'w') as file_h: serializers.JSON.dump(existing_data, file_h) else: color.print_status( 'copy the following lines into the server configuration file under' ) color.print_status( 'the \'ssl_hosts:\' section to use the certificates with king phisher' ) print(' # created: ' + details['created']) print(' - host: ' + details['host']) print(' ssl_cert: ' + details['ssl_cert']) print(' ssl_key: ' + details['ssl_key']) if arguments.hostnames and arguments.json_file and arguments.restart_service: systemctl_bin = smoke_zephyr.utilities.which('systemctl') if systemctl_bin is None: color.print_error( 'could not restart the king-phisher service (could not find systemctl)' ) return os.EX_OK proc_h = subprocess.Popen([systemctl_bin, 'restart', 'king-phisher'], shell=False) if proc_h.wait() != 0: color.print_error( 'failed to restart the king-phisher service via systemctl') return os.EX_SOFTWARE color.print_status('restarted the king-phisher service via systemctl') return os.EX_OK
def main(): parser = argparse.ArgumentParser( conflict_handler='resolve', description=PARSER_DESCRIPTION, epilog=PARSER_EPILOG, formatter_class=argparse.RawTextHelpFormatter ) 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') parser.add_argument('--dns-timeout', dest='dns_timeout', default=spf.DEFAULT_DNS_TIMEOUT, metavar='TIMEOUT', type=int, help='the timeout for dns queries') arguments = parser.parse_args() server_ip = arguments.smtp_server_ip target_email = arguments.target_email if not ipaddress.is_valid(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, sender=spf_sender, timeout=arguments.dns_timeout) try: result = spf_test.check_host() except spf.SPFParseError as error: color.print_error('check_host failed with error: permerror (parsing failed)') color.print_error('error reason: ' + error.message) return 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:') match = spf_test.match for record_id, record in enumerate(spf_test.records.values(), 1): color.print_status(" #{0} {1: <10} {2}".format( record_id, ('(matched)' if match.record == record else ''), record.domain )) for directive_id, directive in enumerate(record.directives, 1): color.print_status(" #{0}.{1: <2} {2: <10} {3}".format( record_id, directive_id, ('(matched)' if match.record == record and match.directive == directive else ''), directive ))
def main(): parser = argparse.ArgumentParser(description='King Phisher TOTP Enrollment Utility', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') parser.add_argument('--force', dest='force', action='store_true', default=False, help='create the user if necessary') parser.add_argument('--otp', dest='otp_secret', help='a specific otp secret') if has_qrcode: parser.add_argument('--qrcode', dest='qrcode_filename', help='generate a qrcode image file') parser.add_argument('user', help='the user to mange') parser.add_argument('action', choices=('remove', 'set', 'show'), help='the action to preform') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = configuration.ex_load_config(arguments.server_config) database_connection_url = server_config.get('server.database') else: raise RuntimeError('no database connection was specified') manager.init_database(database_connection_url) session = manager.Session() user = session.query(models.User).filter_by(name=arguments.user).first() if not user: if not arguments.force: color.print_error("invalid user id: {0}".format(arguments.user)) return user = models.User(name=arguments.user) session.add(user) color.print_status('the specified user was created') for case in utilities.switch(arguments.action): if case('remove'): user.otp_secret = None break if case('set'): if user.otp_secret: color.print_error("the specified user already has an otp secret set") return if arguments.otp_secret: new_otp = arguments.otp_secret else: new_otp = pyotp.random_base32() if len(new_otp) != 16: color.print_error("invalid otp secret length, must be 16") return user.otp_secret = new_otp break if user.otp_secret: color.print_status("user: {0} otp: {1}".format(user.name, user.otp_secret)) totp = pyotp.TOTP(user.otp_secret) uri = totp.provisioning_uri(user.name + '@king-phisher') + '&issuer=King%20Phisher' color.print_status("provisioning uri: {0}".format(uri)) if has_qrcode and arguments.qrcode_filename: img = qrcode.make(uri) img.save(arguments.qrcode_filename) color.print_status("wrote qrcode image to: " + arguments.qrcode_filename) else: color.print_status("user: {0} otp: N/A".format(user.id)) session.commit()
def main(): parser = argparse.ArgumentParser(description='King Phisher Certbot Wrapper Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('--certbot', dest='certbot_bin', help='the path to the certbot binary to use') parser.add_argument('server_config', type=argparse.FileType('r'), help='the server configuration file') parser.add_argument('hostnames', nargs='+', help='the host names to request certificates for') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() server_config = yaml.load(arguments.server_config) web_root = server_config['server']['web_root'] if os.getuid(): color.print_error('this tool must be ran as root') return os.EX_NOPERM certbot_bin = arguments.certbot_bin or smoke_zephyr.utilities.which('certbot') if certbot_bin is None: color.print_error('could not identify the path to the certbot binary, make sure that it is') color.print_error('installed and see: https://certbot.eff.org/ for more details') return os.EX_NOTFOUND if not os.access(certbot_bin, os.R_OK | os.X_OK): color.print_error('found insufficient permissions on the certbot binary') return os.EX_NOPERM logger = logging.getLogger('KingPhisher.Tool.CLI.CertbotWrapper') logger.info('using certbot binary at: ' + certbot_bin) logger.debug('getting server binding information') if server_config['server'].get('addresses'): address = server_config['server']['addresses'][0] else: address = server_config['server']['address'] address['ssl'] = bool(server_config['server'].get('ssl_cert')) logger.debug("checking that the king phisher server is running on: {host}:{port} (ssl={ssl})".format(**address)) try: rpc = advancedhttpserver.RPCClient((address['host'], address['port']), use_ssl=address['ssl']) version = rpc('version') except (advancedhttpserver.RPCError, socket.error): logger.error('received an rpc error while checking the version', exc_info=True) color.print_error('failed to verify that the king phisher server is running') return os.EX_UNAVAILABLE logger.info('connected to server version: ' + version['version']) vhost_directories = server_config['server']['vhost_directories'] if len(arguments.hostnames) > 1 and not vhost_directories: color.print_error('vhost_directories must be true to specify multiple hostnames') return os.EX_CONFIG for hostname in arguments.hostnames: if vhost_directories: directory = os.path.join(web_root, hostname) else: directory = web_root if os.path.split(os.path.abspath(directory))[-1] != hostname: color.print_error('when the vhost_directories option is not set, the web_root option') color.print_error('must be: ' + os.path.join(web_root, hostname)) return os.EX_CONFIG if not os.path.exists(directory): os.mkdir(directory, mode=0o775) logger.info('created directory for host at: ' + directory) certbot_args = (certbot_bin, 'certonly', '--webroot', '-w', directory, '-d', hostname) logger.info('running certbot command: ' + ' '.join(certbot_args)) proc_h = subprocess.Popen(certbot_args, shell=False) status = proc_h.wait() if status != os.EX_OK: color.print_error('certbot exited with exit status: ' + int(status)) break color.print_good('certbot exited with successful status code') if not os.path.isdir(os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname)): logger.warning('failed to find the new hostname in: ' + LETS_ENCRYPT_LIVE_PATH) continue color.print_status('copy the following lines into the server configuration file under') color.print_status('the \'ssl_hosts:\' section to use the certificates with king phisher') print(" - host: {0}".format(hostname)) print(" ssl_cert: /etc/letsencrypt/live/{0}/fullchain.pem".format(hostname)) print(" ssl_key: /etc/letsencrypt/live/{0}/privkey.pem".format(hostname))
def main(): parser = argparse.ArgumentParser(prog='KingPhisher', description='King Phisher Client GUI', conflict_handler='resolve') utilities.argp_add_args(parser, default_root='KingPhisher') startup.argp_add_client(parser) arguments = parser.parse_args() # basic runtime checks if sys.version_info < (3, 4): color.print_error( 'the Python version is too old (minimum required is 3.4)') return 0 if Gtk.check_version(3, 14, 0): color.print_error( 'the GTK+ version is too old (minimum required is 3.14)') return 0 if sys.platform.startswith('linux') and not os.environ.get('DISPLAY'): color.print_error( 'no display was detected, this must be run with an interactive X session' ) return 0 config_file = arguments.config_file use_plugins = arguments.use_plugins use_style = arguments.use_style del arguments, parser logger = logging.getLogger('KingPhisher.Client.CLI') if sys.platform.startswith('linux') and not os.getuid(): logger.warning( 'it is not necessary to run the king phisher client as root') find.init_data_path('client') if not gui_utilities.which_glade(): color.print_error('unable to locate the glade ui data file') return 0 logger.debug( "king phisher version: {0} python version: {1}.{2}.{3}".format( version.version, sys.version_info[0], sys.version_info[1], sys.version_info[2])) logger.debug("client running in process: {0} main tid: 0x{1:x}".format( os.getpid(), threading.current_thread().ident)) start_time = time.time() logger.debug('using ui data from glade file: ' + gui_utilities.which_glade()) try: app = application.KingPhisherClientApplication(config_file=config_file, use_plugins=use_plugins, use_style=use_style) except Exception as error: logger.critical("initialization error: {0} ({1})".format( error.__class__.__name__, getattr(error, 'message', 'n/a'))) color.print_error('failed to initialize the King Phisher client') return 0 logger.debug("client loaded in {0:.2f} seconds".format(time.time() - start_time)) GObject.threads_init() return app.run([])
def main(): parser = argparse.ArgumentParser( conflict_handler='resolve', description=PARSER_DESCRIPTION, epilog=PARSER_EPILOG, formatter_class=argparse.RawTextHelpFormatter ) utilities.argp_add_args(parser) parser.add_argument('--certbot', dest='certbot_bin', help='the path to the certbot binary to use') parser.add_argument('--json-output', dest='json_file', help='update a json formatted file with the details') parser.add_argument('--restart-service', action='store_true', default=False, help='attempt to restart the king-phisher service') parser.add_argument('server_config', help='the server configuration file') parser.add_argument('hostnames', nargs='+', help='the host names to request certificates for') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() server_config = configuration.ex_load_config(arguments.server_config).get('server') web_root = server_config['web_root'] if os.getuid(): color.print_error('this tool must be run as root') return os.EX_NOPERM certbot_bin = arguments.certbot_bin or smoke_zephyr.utilities.which('certbot') if certbot_bin is None: color.print_error('could not identify the path to the certbot binary, make sure that it is') color.print_error('installed and see: https://certbot.eff.org/ for more details') return os.EX_UNAVAILABLE if not os.access(certbot_bin, os.R_OK | os.X_OK): color.print_error('found insufficient permissions on the certbot binary') return os.EX_NOPERM logger = logging.getLogger('KingPhisher.Tool.CLI.CertbotWrapper') logger.info('using certbot binary at: ' + certbot_bin) logger.debug('getting server binding information') if server_config.get('addresses'): address = server_config['addresses'][0] else: address = server_config['address'] address['ssl'] = bool(server_config.get('ssl_cert')) logger.debug("checking that the king phisher server is running on: {host}:{port} (ssl={ssl})".format(**address)) try: rpc = advancedhttpserver.RPCClient((address['host'], address['port']), use_ssl=address['ssl']) version = rpc('version') except (advancedhttpserver.RPCError, socket.error): logger.error('received an rpc error while checking the version', exc_info=True) color.print_error('failed to verify that the king phisher server is running') return os.EX_UNAVAILABLE logger.info('connected to server version: ' + version['version']) vhost_directories = server_config['vhost_directories'] if len(arguments.hostnames) > 1 and not vhost_directories: color.print_error('vhost_directories must be true to specify multiple hostnames') return os.EX_CONFIG for hostname in arguments.hostnames: if vhost_directories: directory = os.path.join(web_root, hostname) else: directory = web_root if os.path.split(os.path.abspath(directory))[-1] != hostname: color.print_error('when the vhost_directories option is not set, the web_root option') color.print_error('must be: ' + os.path.join(web_root, hostname)) return os.EX_CONFIG if not os.path.exists(directory): os.mkdir(directory, mode=0o775) logger.info('created directory for host at: ' + directory) certbot_args = (certbot_bin, 'certonly', '--webroot', '-w', directory, '-d', hostname) logger.info('running certbot command: ' + ' '.join(certbot_args)) proc_h = subprocess.Popen(certbot_args, shell=False) status = proc_h.wait() if status != os.EX_OK: color.print_error('certbot exited with exit status: ' + str(status)) break color.print_good('certbot exited with a successful status code') timestamp = datetime.datetime.utcnow().isoformat() + '+00:00' if not os.path.isdir(os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname)): logger.warning('failed to find the new hostname in: ' + LETS_ENCRYPT_LIVE_PATH) continue details = { 'created': timestamp, 'host': hostname, 'ssl_cert': os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname, 'fullchain.pem'), 'ssl_key': os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname, 'privkey.pem') } if arguments.json_file: existing_data = [] if os.path.isfile(arguments.json_file): with open(arguments.json_file, 'r') as file_h: existing_data = serializers.JSON.load(file_h) if not isinstance(existing_data, list): color.print_status('the existing json data must be a list to add the new data') existing_data.append(details) with open(arguments.json_file, 'w') as file_h: serializers.JSON.dump(existing_data, file_h) else: color.print_status('copy the following lines into the server configuration file under') color.print_status('the \'ssl_hosts:\' section to use the certificates with king phisher') print(' # created: ' + details['created']) print(' - host: ' + details['host']) print(' ssl_cert: ' + details['ssl_cert']) print(' ssl_key: ' + details['ssl_key']) if arguments.hostnames and arguments.json_file and arguments.restart_service: systemctl_bin = smoke_zephyr.utilities.which('systemctl') if systemctl_bin is None: color.print_error('could not restart the king-phisher service (could not find systemctl)') return os.EX_OK proc_h = subprocess.Popen([systemctl_bin, 'restart', 'king-phisher'], shell=False) if proc_h.wait() != 0: color.print_error('failed to restart the king-phisher service via systemctl') return os.EX_SOFTWARE color.print_status('restarted the king-phisher service via systemctl') return os.EX_OK