Esempio n. 1
0
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
			))
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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)
Esempio n. 5
0
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)
Esempio n. 6
0
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
			))
Esempio n. 7
0
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
Esempio n. 8
0
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
Esempio n. 9
0
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()
Esempio n. 10
0
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([])
Esempio n. 11
0
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)
Esempio n. 12
0
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))
Esempio n. 13
0
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')
Esempio n. 15
0
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')
Esempio n. 17
0
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()
Esempio n. 18
0
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
Esempio n. 19
0
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
			))
Esempio n. 20
0
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()
Esempio n. 21
0
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))
Esempio n. 22
0
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([])
Esempio n. 23
0
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