Exemplo n.º 1
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)
Exemplo n.º 2
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
Exemplo n.º 3
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
Exemplo n.º 4
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)
Exemplo n.º 5
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
Exemplo n.º 6
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()
Exemplo n.º 7
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
Exemplo n.º 8
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()