def __init__(self, work_dir, config, key='server.key', cert='server.crt', **kwargs): """ Main class which runs Beeswarm in Honeypot mode. :param work_dir: Working directory (usually the current working directory) :param config: Beeswarm configuration dictionary, None if no configuration was supplied. :param key: Key file used for SSL enabled capabilities :param cert: Cert file used for SSL enabled capabilities """ if config is None or not os.path.isdir(os.path.join(work_dir, 'data')): Honeypot.prepare_environment(work_dir) self.work_dir = work_dir self.config = config self.key = os.path.join(work_dir, key) self.cert = os.path.join(work_dir, cert) self._servers = [] self._server_greenlets = [] self.honeypot_id = self.config['general']['id'] Session.honeypot_id = self.honeypot_id # write ZMQ keys to files - as expected by pyzmq extract_keys(work_dir, config) if not (os.path.isfile(os.path.join(work_dir, 'server.key'))): cert_info = config['certificate_info'] if cert_info['common_name']: cert_info['common_name'] = cert_info['common_name'] else: cert_info['common_name'] = get_most_likely_ip() cert, priv_key = create_self_signed_cert(cert_info['country'], cert_info['state'], cert_info['organization'], cert_info['locality'], cert_info['organization_unit'], cert_info['common_name']) cert_path = os.path.join(work_dir, 'server.crt') key_path = os.path.join(work_dir, 'server.key') with open(cert_path, 'w') as certfile: certfile.write(cert) with open(key_path, 'w') as keyfile: keyfile.write(priv_key) send_zmq_push(SocketNames.SERVER_RELAY.value, '{0} {1} {2}'.format(Messages.KEY.value, self.honeypot_id, priv_key)) send_zmq_push(SocketNames.SERVER_RELAY.value, '{0} {1} {2}'.format(Messages.CERT.value, self.honeypot_id, cert)) if self.config['general']['fetch_ip']: try: url = 'http://api.externalip.net/ip' req = requests.get(url) self.honeypot_ip = req.text logger.info('Fetched {0} as external ip for Honeypot.'.format(self.honeypot_ip)) except (Timeout, ConnectionError) as e: logger.warning('Could not fetch public ip: {0}'.format(e)) else: self.honeypot_ip = '' # spawning time checker if self.config['timecheck']['enabled']: Greenlet.spawn(self.check_time)
def incoming_server_comms(self, server_public, client_public, client_secret): context = beeswarm.shared.zmq_context # data (commands) received from server receiving_socket = context.socket(zmq.SUB) # setup receiving tcp socket receiving_socket.curve_secretkey = client_secret receiving_socket.curve_publickey = client_public receiving_socket.curve_serverkey = server_public receiving_socket.setsockopt(zmq.RECONNECT_IVL, 2000) # messages to this specific drone receiving_socket.setsockopt(zmq.SUBSCRIBE, self.id) # broadcasts to all drones receiving_socket.setsockopt(zmq.SUBSCRIBE, Messages.IP) logger.debug( 'Trying to connect receiving socket to server on {0}'.format(self.config['beeswarm_server']['zmq_command_url'])) receiving_socket.connect(self.config['beeswarm_server']['zmq_command_url']) gevent.spawn(self.monitor_worker, receiving_socket.get_monitor_socket(), 'incomming socket ({0}).' .format(self.config['beeswarm_server']['zmq_url'])) poller = zmq.Poller() poller.register(receiving_socket, zmq.POLLIN) while True: # .recv() gives no context switch - why not? using poller with timeout instead socks = dict(poller.poll(1)) # hmm, do we need to sleep here (0.1) works, gevnet.sleep() does not work gevent.sleep(0.1) if receiving_socket in socks and socks[receiving_socket] == zmq.POLLIN: message = receiving_socket.recv() # expected format for drone commands are: # DRONE_ID COMMAND OPTIONAL_DATA # DRONE_ID and COMMAND must not contain spaces drone_id, command, data = message.split(' ', 2) logger.debug('Received {0} command.'.format(command)) assert (drone_id == self.id) # if we receive a configuration we restart the drone if command == Messages.CONFIG: send_zmq_push('inproc://serverRelay', '{0}'.format(Messages.PING)) self.config_received.set() config = json.loads(data) with open('beeswarmcfg.json', 'w') as local_config: local_config.write(json.dumps(config, indent=4)) self.stop() self._start_drone() elif command == Messages.DRONE_DELETE: self._handle_delete() else: self.internal_server_relay.send('{0} {1}'.format(command, data)) logger.warn('Command listener exiting.')
def monitor_worker(self, monitor_socket, log_name): monitor_socket.linger = 0 poller = zmq.Poller() poller.register(monitor_socket, zmq.POLLIN) while True: socks = poller.poll(0) if len(socks) > 0: data = recv_monitor_message(monitor_socket) event = data['event'] value = data['value'] if event == zmq.EVENT_CONNECTED: logger.info('Connected to {0}'.format(log_name)) send_zmq_push('ipc://serverRelay', '{0} {1}'.format(Messages.PING, self.id)) elif event == zmq.EVENT_DISCONNECTED: logger.warning('Disconnected from {0}, will reconnect in {1} seconds.'.format(log_name, 5)) gevent.sleep()
def monitor_worker(self, monitor_socket, log_name): monitor_socket.linger = 0 poller = zmq.Poller() poller.register(monitor_socket, zmq.POLLIN) while True: socks = poller.poll(1) gevent.sleep(0.1) if len(socks) > 0: data = recv_monitor_message(monitor_socket) event = data['event'] value = data['value'] if event == zmq.EVENT_CONNECTED: logger.info('Connected to {0}'.format(log_name)) if 'outgoing' in log_name: send_zmq_push('inproc://serverRelay', '{0}'.format(Messages.PING)) own_ip = gevent.socket.gethostbyname(socket.gethostname()) send_zmq_push('inproc://serverRelay', '{0} {1}'.format(Messages.IP, own_ip)) send_zmq_push('inproc://serverRelay', '{0}'.format(Messages.DRONE_CONFIG)) elif 'incomming': pass else: assert False elif event == zmq.EVENT_DISCONNECTED: logger.warning('Disconnected from {0}, will reconnect in {1} seconds.'.format(log_name, 5)) gevent.sleep()
def monitor_worker(self, monitor_socket, log_name): monitor_socket.linger = 0 poller = zmq.Poller() poller.register(monitor_socket, zmq.POLLIN) while True: socks = poller.poll(1) gevent.sleep(0.1) if len(socks) > 0: data = recv_monitor_message(monitor_socket) event = data['event'] if event == zmq.EVENT_CONNECTED: logger.info('Connected to {0}'.format(log_name)) # always ask for config to avoid race condition. send_zmq_push(SocketNames.SERVER_RELAY.value, '{0}'.format(Messages.DRONE_WANT_CONFIG.value)) if 'outgoing' in log_name: send_zmq_push(SocketNames.SERVER_RELAY.value, '{0}'.format(Messages.PING.value)) own_ip = get_most_likely_ip() send_zmq_push(SocketNames.SERVER_RELAY.value, '{0} {1}'.format(Messages.IP.value, own_ip)) elif 'incomming': pass else: assert False elif event == zmq.EVENT_DISCONNECTED: logger.warning('Disconnected from {0}, will reconnect in {1} seconds.'.format(log_name, 5)) gevent.sleep()
def monitor_worker(self, monitor_socket, log_name): monitor_socket.linger = 0 poller = zmq.Poller() poller.register(monitor_socket, zmq.POLLIN) while True: socks = poller.poll(1) gevent.sleep(0.1) if len(socks) > 0: data = recv_monitor_message(monitor_socket) event = data['event'] value = data['value'] if event == zmq.EVENT_CONNECTED: logger.info('Connected to {0}'.format(log_name)) if 'outgoing' in log_name: send_zmq_push('inproc://serverRelay', '{0}'.format(Messages.PING)) own_ip = gevent.socket.gethostbyname( socket.gethostname()) send_zmq_push('inproc://serverRelay', '{0} {1}'.format(Messages.IP, own_ip)) send_zmq_push('inproc://serverRelay', '{0}'.format(Messages.DRONE_CONFIG)) elif 'incomming': pass else: assert False elif event == zmq.EVENT_DISCONNECTED: logger.warning( 'Disconnected from {0}, will reconnect in {1} seconds.' .format(log_name, 5)) gevent.sleep()
def __init__(self, work_dir, config, key='server.key', cert='server.crt', **kwargs): """ Main class which runs Beeswarm in Honeypot mode. :param work_dir: Working directory (usually the current working directory) :param config: Beeswarm configuration dictionary, None if no configuration was supplied. :param key: Key file used for SSL enabled capabilities :param cert: Cert file used for SSL enabled capabilities """ if fs.__version__ != '0.5.4': os.exit('the python fs package must be verison 0.5.4') if config is None or not os.path.isdir(os.path.join(work_dir, 'data')): Honeypot.prepare_environment(work_dir) self.work_dir = work_dir self.config = config self.key = os.path.join(work_dir, key) self.cert = os.path.join(work_dir, cert) self._servers = [] self._server_greenlets = [] self.honeypot_id = self.config['general']['id'] Session.honeypot_id = self.honeypot_id # write ZMQ keys to files - as expected by pyzmq extract_keys(work_dir, config) if not (os.path.isfile(os.path.join(work_dir, 'server.key'))): cert_info = config['certificate_info'] if cert_info['common_name']: cert_info['common_name'] = cert_info['common_name'] else: cert_info['common_name'] = get_most_likely_ip() cert, priv_key = create_self_signed_cert( cert_info['country'], cert_info['state'], cert_info['organization'], cert_info['locality'], cert_info['organization_unit'], cert_info['common_name']) cert_path = os.path.join(work_dir, 'server.crt') key_path = os.path.join(work_dir, 'server.key') with open(cert_path, 'w') as certfile: certfile.write(cert) with open(key_path, 'w') as keyfile: keyfile.write(priv_key) send_zmq_push( SocketNames.SERVER_RELAY.value, '{0} {1} {2}'.format(Messages.KEY.value, self.honeypot_id, priv_key)) send_zmq_push( SocketNames.SERVER_RELAY.value, '{0} {1} {2}'.format(Messages.CERT.value, self.honeypot_id, cert)) if self.config['general']['fetch_ip']: try: url = 'http://api.externalip.net/ip' req = requests.get(url) self.honeypot_ip = req.text logger.info('Fetched {0} as external ip for Honeypot.'.format( self.honeypot_ip)) except (Timeout, ConnectionError) as e: logger.warning('Could not fetch public ip: {0}'.format(e)) else: self.honeypot_ip = '' # spawning time checker if self.config['timecheck']['enabled']: Greenlet.spawn(self.check_time)
def __init__(self, work_dir, config, key='server.key', cert='server.crt', curses_screen=None, **kwargs): """ Main class which runs Beeswarm in Honeypot mode. :param work_dir: Working directory (usually the current working directory) :param config: Beeswarm configuration dictionary, None if no configuration was supplied. :param key: Key file used for SSL enabled capabilities :param cert: Cert file used for SSL enabled capabilities :param curses_screen: Contains a curses screen object, if UI is enabled. Default is None. """ if config is None or not os.path.isdir(os.path.join(work_dir, 'data')): Honeypot.prepare_environment(work_dir) with open('beeswarmcfg.json', 'r') as config_file: config = json.load(config_file, object_hook=asciify) self.work_dir = work_dir self.config = config self.key = key self.cert = cert self.curses_screen = curses_screen # TODO: pass honeypot otherwise Session.honeypot_id = self.config['general']['id'] self.id = self.config['general']['id'] # write ZMQ keys to files - as expected by pyzmq extract_keys(work_dir, config) if not (os.path.isfile(os.path.join(work_dir, 'server.key'))): cert_info = config['certificate_info'] #TODO: IF NOT COMMON_NAME: Use own ip address... cert, priv_key = create_self_signed_cert(cert_info['country'], cert_info['state'], cert_info['organization'], cert_info['locality'], cert_info['organization_unit'], cert_info['common_name']) cert_path = os.path.join(work_dir, 'server.crt') key_path = os.path.join(work_dir, 'server.key') with open(cert_path, 'w') as certfile: certfile.write(cert) with open(key_path, 'w') as keyfile: keyfile.write(priv_key) send_zmq_push('ipc://serverRelay', '{0} {1} {2}'.format(Messages.KEY, self.id, keyfile)) send_zmq_push('ipc://serverRelay', '{0} {1} {2}'.format(Messages.CERT, self.id, cert)) if self.config['general']['fetch_ip']: try: url = 'http://api.externalip.net/ip' req = requests.get(url) self.honeypot_ip = req.text logger.info('Fetched {0} as external ip for Honeypot.'.format(self.honeypot_ip)) except (Timeout, ConnectionError) as e: logger.warning('Could not fetch public ip: {0}'.format(e)) else: self.honeypot_ip = '' self.status = { 'mode': 'Honeypot', 'ip_address': self.honeypot_ip, 'honeypot_id': self.config['general']['id'], 'total_sessions': 0, 'active_sessions': 0, 'enabled_capabilities': [], 'managment_url': '' } # will contain BaitUser objects self.users = self.create_users() # inject authentication mechanism Session.authenticator = Authenticator(self.users) # spawning time checker if self.config['timecheck']['enabled']: Greenlet.spawn(self.checktime) # show curses UI if self.curses_screen is not None: self.uihandler = HoneypotUIHandler(self.status, self.curses_screen) Greenlet.spawn(self.show_status_ui)
def incoming_server_comms(self, server_public, client_public, client_secret): context = beeswarm.shared.zmq_context # data (commands) received from server server_receiving_socket = context.socket(zmq.SUB) # setup receiving tcp socket server_receiving_socket.curve_secretkey = client_secret server_receiving_socket.curve_publickey = client_public server_receiving_socket.curve_serverkey = server_public server_receiving_socket.setsockopt(zmq.RECONNECT_IVL, 2000) # only subscribe to messages to this specific drone server_receiving_socket.setsockopt(zmq.SUBSCRIBE, str(self.id)) # data from local socket local_receiving_socket = context.socket(zmq.PULL) if self.local_pull_socket: local_receiving_socket.bind('ipc://{0}'.format(self.local_pull_socket)) logger.debug( 'Trying to connect receiving socket to server on {0}'.format( self.config['beeswarm_server']['zmq_command_url'])) outgoing_proxy = context.socket(zmq.PUSH) outgoing_proxy.connect(SocketNames.SERVER_RELAY.value) server_receiving_socket.connect(self.config['beeswarm_server']['zmq_command_url']) gevent.spawn(self.monitor_worker, server_receiving_socket.get_monitor_socket(), 'incomming socket ({0}).' .format(self.config['beeswarm_server']['zmq_command_url'])) poller = zmq.Poller() poller.register(server_receiving_socket, zmq.POLLIN) while True: # .recv() gives no context switch - why not? using poller with timeout instead socks = dict(poller.poll(1)) # hmm, do we need to sleep here (0.1) works, gevnet.sleep() does not work gevent.sleep(0.1) if server_receiving_socket in socks and socks[server_receiving_socket] == zmq.POLLIN: message = server_receiving_socket.recv() # expected format for drone commands are: # DRONE_ID COMMAND OPTIONAL_DATA # DRONE_ID and COMMAND must not contain spaces drone_id, command, data = message.split(' ', 2) logger.debug('Received {0} command.'.format(command)) assert (drone_id == str(self.id)) # if we receive a configuration we restart the drone if command == Messages.CONFIG.value: send_zmq_push(SocketNames.SERVER_RELAY.value, '{0}'.format(Messages.PING.value)) config = json.loads(data, object_hook=asciify) if self.config != config or not self.config_received.isSet(): logger.debug('Setting config.') self.config = config with open(self.config_file, 'w') as local_config: local_config.write(json.dumps(config, indent=4)) self.stop() self._start_drone() self.config_received.set() elif command == Messages.DRONE_DELETE.value: self._handle_delete() else: # Messages we cannot handles goes back to server (and pings). send_zmq_push(SocketNames.SERVER_RELAY.value, '{0} {1}'.format(command, data)) elif local_receiving_socket in socks and socks[local_receiving_socket] == zmq.POLLIN: data = local_receiving_socket.recv() outgoing_proxy.send('{0} {1}'.format(self.id, data)) logger.warn('Command listener exiting.')
def incoming_server_comms(self, server_public, client_public, client_secret): context = beeswarm.shared.zmq_context # data (commands) received from server receiving_socket = context.socket(zmq.SUB) # setup receiving tcp socket receiving_socket.curve_secretkey = client_secret receiving_socket.curve_publickey = client_public receiving_socket.curve_serverkey = server_public receiving_socket.setsockopt(zmq.RECONNECT_IVL, 2000) # messages to this specific drone receiving_socket.setsockopt(zmq.SUBSCRIBE, self.id) # broadcasts to all drones receiving_socket.setsockopt(zmq.SUBSCRIBE, Messages.IP) logger.debug( 'Trying to connect receiving socket to server on {0}'.format( self.config['beeswarm_server']['zmq_command_url'])) receiving_socket.connect( self.config['beeswarm_server']['zmq_command_url']) gevent.spawn( self.monitor_worker, receiving_socket.get_monitor_socket(), 'incomming socket ({0}).'.format( self.config['beeswarm_server']['zmq_url'])) poller = zmq.Poller() poller.register(receiving_socket, zmq.POLLIN) while True: # .recv() gives no context switch - why not? using poller with timeout instead socks = dict(poller.poll(1)) # hmm, do we need to sleep here (0.1) works, gevnet.sleep() does not work gevent.sleep(0.1) if receiving_socket in socks and socks[ receiving_socket] == zmq.POLLIN: message = receiving_socket.recv() # expected format for drone commands are: # DRONE_ID COMMAND OPTIONAL_DATA # DRONE_ID and COMMAND must not contain spaces drone_id, command, data = message.split(' ', 2) logger.debug('Received {0} command.'.format(command)) assert (drone_id == self.id) # if we receive a configuration we restart the drone if command == Messages.CONFIG: send_zmq_push('inproc://serverRelay', '{0}'.format(Messages.PING)) self.config_received.set() config = json.loads(data) with open('beeswarmcfg.json', 'w') as local_config: local_config.write(json.dumps(config, indent=4)) self.stop() self._start_drone() elif command == Messages.DRONE_DELETE: self._handle_delete() else: self.internal_server_relay.send('{0} {1}'.format( command, data)) logger.warn('Command listener exiting.')
def configure_drone(id): db_session = database_setup.get_session() drone = db_session.query(Drone).filter(Drone.id == id).one() if drone.discriminator == 'honeypot': if drone.configuration is not None: config_obj = DictWrapper(json.loads(drone.configuration)) else: # virgin drone config_obj = None form = NewHoneypotConfigForm(obj=config_obj) if not form.validate_on_submit(): return render_template('create-honeypot.html', form=form, mode_name='Honeypot', user=current_user) else: server_zmq_command_url = 'tcp://{0}:{1}'.format(config['network']['zmq_host'], config['network']['zmq_command_port']) server_zmq_url = 'tcp://{0}:{1}'.format(config['network']['zmq_host'], config['network']['zmq_port']) # TODO: Check if key pair exists result = send_zmq_request('ipc://configCommands', '{0} {1}'.format(Messages.GEN_ZMQ_KEYS, str(drone.id))) zmq_public = result['public_key'] zmq_private = result['private_key'] drone_config = { 'general': { 'name': form.general__name.data, 'mode': 'honeypot', 'id': drone.id, 'ip': '192.168.1.1', 'fetch_ip': False }, 'beeswarm_server': { 'enabled': True, 'zmq_url' : server_zmq_url, 'zmq_server_public': config['network']['zmq_server_public_key'], 'zmq_own_public': zmq_public, 'zmq_own_private': zmq_private, 'zmq_command_url': server_zmq_command_url, }, 'log_syslog': { 'enabled': False, 'socket': '/dev/log' }, 'certificate_info': { 'common_name': form.certificate_info__common_name.data, 'country': form.certificate_info__country.data, 'state': form.certificate_info__state.data, 'locality': form.certificate_info__locality.data, 'organization': form.certificate_info__organization.data, 'organization_unit': form.certificate_info__organization_unit.data }, 'capabilities': { 'ftp': { 'enabled': form.capabilities__ftp__enabled.data, 'port': form.capabilities__ftp__port.data, 'max_attempts': form.capabilities__ftp__max_attempts.data, 'banner': form.capabilities__ftp__banner.data, 'syst_type': form.capabilities__ftp__syst_type.data }, 'telnet': { 'enabled': form.capabilities__telnet__enabled.data, 'port': form.capabilities__telnet__port.data, 'max_attempts': form.capabilities__telnet__max_attempts.data }, 'pop3': { 'enabled': form.capabilities__pop3__enabled.data, 'port': form.capabilities__pop3__port.data, 'max_attempts': form.capabilities__pop3__max_attempts.data, }, 'pop3s': { 'enabled': form.capabilities__pop3s__enabled.data, 'port': form.capabilities__pop3s__port.data, 'max_attempts': form.capabilities__pop3s__max_attempts.data, }, 'ssh': { 'enabled': form.capabilities__ssh__enabled.data, 'port': form.capabilities__ssh__port.data, }, 'http': { 'enabled': form.capabilities__http__enabled.data, 'port': form.capabilities__http__port.data, 'banner': form.capabilities__http__banner.data }, 'https': { 'enabled': form.capabilities__https__enabled.data, 'port': form.capabilities__https__port.data, 'banner': form.capabilities__https__banner.data }, 'smtp': { 'enabled': form.capabilities__smtp__enabled.data, 'port': form.capabilities__smtp__port.data, 'banner': form.capabilities__smtp__banner.data }, 'vnc': { 'enabled': form.capabilities__vnc__enabled.data, 'port': form.capabilities__vnc__port.data } }, 'users': {}, 'timecheck': { 'enabled': True, 'poll': 5, 'ntp_pool': 'pool.ntp.org' }, } config_json = json.dumps(drone_config, indent=4) drone.name = form.general__name.data drone.configuration = config_json db_session.add(drone) db_session.commit() # everything good, push config to drone if it is listening send_zmq_push('ipc://droneCommandReceiver', '{0} {1} {2}'.format(drone.id, Messages.CONFIG, config_json)) return render_template('finish-config.html', drone_id=drone.id, user=current_user) elif drone.discriminator == 'client': form = NewClientConfigForm() if not form.validate_on_submit(): return render_template('create-client.html', form=form, mode_name='Honeypot', user=current_user) else: server_zmq_url = 'tcp://{0}:{1}'.format(config['network']['zmq_host'], config['network']['zmq_port']) server_zmq_command_url = 'tcp://{0}:{1}'.format(config['network']['zmq_host'], config['network']['zmq_command_port']) # TODO: Check if key pair exists result = send_zmq_request('ipc://configCommands', '{0} {1}'.format(Messages.GEN_ZMQ_KEYS, str(drone.id))) zmq_public = result['public_key'] zmq_private = result['private_key'] drone_config = { 'general': { 'mode': 'client', 'id': drone.id, 'honeypot_id': None }, 'public_ip': { 'fetch_ip': True }, 'bait_sessions': { 'http': { 'enabled': form.http_enabled.data, 'server': form.http_server.data, 'port': form.http_port.data, 'timing': { 'active_range': form.http_active_range.data, 'sleep_interval': form.http_sleep_interval.data, 'activation_probability': form.http_activation_probability.data }, 'username': form.http_login.data, 'password': form.http_password.data }, 'ftp': { 'enabled': form.ftp_enabled.data, 'server': form.ftp_server.data, 'port': form.ftp_port.data, 'timing': { 'active_range': form.ftp_active_range.data, 'sleep_interval': form.ftp_sleep_interval.data, 'activation_probability': form.ftp_activation_probability.data }, 'username': form.ftp_login.data, 'password': form.ftp_password.data }, 'https': { 'enabled': form.https_enabled.data, 'server': form.https_server.data, 'port': form.https_port.data, 'timing': { 'active_range': form.https_active_range.data, 'sleep_interval': form.https_sleep_interval.data, 'activation_probability': form.https_activation_probability.data }, 'username': form.https_login.data, 'password': form.https_password.data }, 'pop3': { 'enabled': form.pop3_enabled.data, 'server': form.pop3_server.data, 'port': form.pop3_port.data, 'timing': { 'active_range': form.pop3_active_range.data, 'sleep_interval': form.pop3_sleep_interval.data, 'activation_probability': form.pop3_activation_probability.data }, 'username': form.pop3_login.data, 'password': form.pop3_password.data }, 'ssh': { 'enabled': form.ssh_enabled.data, 'server': form.ssh_server.data, 'port': form.ssh_port.data, 'timing': { 'active_range': form.ssh_active_range.data, 'sleep_interval': form.ssh_sleep_interval.data, 'activation_probability': form.ssh_activation_probability.data }, 'username': form.ssh_login.data, 'password': form.ssh_password.data }, 'pop3s': { 'enabled': form.pop3s_enabled.data, 'server': form.pop3s_server.data, 'port': form.pop3s_port.data, 'timing': { 'active_range': form.pop3s_active_range.data, 'sleep_interval': form.pop3s_sleep_interval.data, 'activation_probability': form.pop3s_activation_probability.data }, 'username': form.pop3s_login.data, 'password': form.pop3s_password.data }, 'smtp': { 'enabled': form.smtp_enabled.data, 'server': form.smtp_server.data, 'port': form.smtp_port.data, 'timing': { 'active_range': form.smtp_active_range.data, 'sleep_interval': form.smtp_sleep_interval.data, 'activation_probability': form.smtp_activation_probability.data }, 'username': form.smtp_login.data, 'local_hostname': form.smtp_local_hostname.data, 'password': form.smtp_password.data }, 'vnc': { 'enabled': form.vnc_enabled.data, 'server': form.vnc_server.data, 'port': form.vnc_port.data, 'timing': { 'active_range': form.vnc_active_range.data, 'sleep_interval': form.vnc_sleep_interval.data, 'activation_probability': form.vnc_activation_probability.data }, 'username': form.vnc_login.data, 'password': form.vnc_password.data }, 'telnet': { 'enabled': form.telnet_enabled.data, 'server': form.telnet_server.data, 'port': form.telnet_port.data, 'timing': { 'active_range': form.telnet_active_range.data, 'sleep_interval': form.telnet_sleep_interval.data, 'activation_probability': form.telnet_activation_probability.data }, 'username': form.telnet_login.data, 'password': form.telnet_password.data } }, 'beeswarm_server': { 'enabled': True, 'zmq_url' : server_zmq_url, 'zmq_server_public': config['network']['zmq_server_public_key'], 'zmq_own_public': zmq_public, 'zmq_own_private': zmq_private, 'zmq_command_url': server_zmq_command_url, }, } config_json = json.dumps(drone_config, indent=4) drone.configuration = config_json db_session.add(drone) db_session.commit() # everything good, push config to drone if it is listening send_zmq_push('ipc://droneCommandReceiver', '{0} {1} {2}'.format(drone.id, Messages.CONFIG, config_json)) return render_template('finish-config.html', drone_id=drone.id, user=current_user) elif drone.discriminator is None: return render_template('drone_mode.html', drone_id=drone.id, user=current_user) else: assert(drone is None) abort(404, 'Drone with that id could not be found.')
def __init__(self, work_dir, config, key='server.key', cert='server.crt', **kwargs): """ Main class which runs Beeswarm in Honeypot mode. :param work_dir: Working directory (usually the current working directory) :param config: Beeswarm configuration dictionary, None if no configuration was supplied. :param key: Key file used for SSL enabled capabilities :param cert: Cert file used for SSL enabled capabilities """ if config is None or not os.path.isdir(os.path.join(work_dir, 'data')): Honeypot.prepare_environment(work_dir) with open('beeswarmcfg.json', 'r') as config_file: config = json.load(config_file, object_hook=asciify) self.work_dir = work_dir self.config = config self.key = key self.cert = cert self._servers = [] self._server_greenlets = [] # will contain Session objects self._sessions = {} self._session_consumer = None # TODO: pass honeypot otherwise Session.honeypot_id = self.config['general']['id'] self.id = self.config['general']['id'] # write ZMQ keys to files - as expected by pyzmq extract_keys(work_dir, config) if not (os.path.isfile(os.path.join(work_dir, 'server.key'))): cert_info = config['certificate_info'] if cert_info['common_name']: cert_info['common_name'] = cert_info['common_name'] else: cert_info['common_name'] = get_most_likely_ip() cert, priv_key = create_self_signed_cert( cert_info['country'], cert_info['state'], cert_info['organization'], cert_info['locality'], cert_info['organization_unit'], cert_info['common_name']) cert_path = os.path.join(work_dir, 'server.crt') key_path = os.path.join(work_dir, 'server.key') with open(cert_path, 'w') as certfile: certfile.write(cert) with open(key_path, 'w') as keyfile: keyfile.write(priv_key) send_zmq_push('inproc://serverRelay', '{0} {1} {2}'.format(Messages.KEY, self.id, keyfile)) send_zmq_push('inproc://serverRelay', '{0} {1} {2}'.format(Messages.CERT, self.id, cert)) if self.config['general']['fetch_ip']: try: url = 'http://api.externalip.net/ip' req = requests.get(url) self.honeypot_ip = req.text logger.info('Fetched {0} as external ip for Honeypot.'.format( self.honeypot_ip)) except (Timeout, ConnectionError) as e: logger.warning('Could not fetch public ip: {0}'.format(e)) else: self.honeypot_ip = '' # spawning time checker if self.config['timecheck']['enabled']: Greenlet.spawn(self.checktime)