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 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 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 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(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( 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
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()