def setUp(self): self.password = '******' app.ensure_admin_password(True, password=self.password) app.app.config['WTF_CSRF_ENABLED'] = False self.work_dir = tempfile.mkdtemp() beeswarm.shared.zmq_context = zmq.Context() fd, self.db_file = tempfile.mkstemp() os.close(fd) connection_string = 'sqlite:///{0}'.format(self.db_file) os.remove(self.db_file) database.setup_db(connection_string) self.config_actor = ConfigActor( os.path.join(os.path.dirname(__file__), 'beeswarmcfg.json.test'), self.work_dir) self.config_actor.start() # seed database with test data session = database.get_session() session.add_all([Client(), Honeypot()]) session.commit() # startup session database self.database_actor = DatabaseActor(999, delay_seconds=2) self.database_actor.start() self.app = app.app.test_client() app.connect_sockets()
def test_matching_quick_succession(self): """ Tests that attack sessions coming in quick succession are classified correctly. This test relates to issue #218 """ honeypot_id = 1 honeypot = Honeypot(id=honeypot_id) db_session = database_setup.get_session() db_session.add(honeypot) db_session.commit() drone_data_socket = beeswarm.shared.zmq_context.socket(zmq.PUB) drone_data_socket.bind(SocketNames.DRONE_DATA.value) # startup session database database_actor = DatabaseActor(999, delay_seconds=2) database_actor.start() gevent.sleep(1) for x in xrange(0, 100): honeypot_session = HoneypotSession(source_ip='192.168.100.22', source_port=52311, protocol='pop3', users={}, destination_port=110) honeypot_session.add_auth_attempt('plaintext', True, username='******', password='******') honeypot_session.honeypot_id = honeypot_id drone_data_socket.send('{0} {1} {2}'.format( Messages.SESSION_HONEYPOT.value, honeypot_id, json.dumps(honeypot_session.to_dict(), default=json_default, ensure_ascii=False))) gevent.sleep(1) database_actor_request_socket = beeswarm.shared.zmq_context.socket( zmq.REQ) database_actor_request_socket.connect( SocketNames.DATABASE_REQUESTS.value) sessions = send_zmq_request_socket( database_actor_request_socket, '{0}'.format(Messages.GET_SESSIONS_ALL.value)) for session in sessions: self.assertEqual(session['classification'], 'Bruteforce') self.assertEqual(len(sessions), 100)
def __init__(self, work_dir, config, **kwargs): """ Main class for the Web-Interface. It takes care of setting up the database, managing the users, etc. :param work_dir: The working directory (usually the current working directory). :param config_arg: Beeswarm configuration dictionary, None if not configuration was supplied. """ customize = kwargs['customize'] reset_password = kwargs['reset_password'] if 'clear_db' in kwargs: clear_sessions = kwargs['clear_db'] else: clear_sessions = True if 'server_hostname' in kwargs: server_hostname = kwargs['server_hostname'] else: server_hostname = None max_sessions = kwargs['max_sessions'] start_webui = kwargs['start_webui'] self.work_dir = work_dir self.config_file = os.path.join(work_dir, 'beeswarmcfg.json') if config is None: self.prepare_environment(work_dir, customize, server_hostname=server_hostname) with open(os.path.join(work_dir, self.config_file), 'r') as config_file: self.config = json.load(config_file, object_hook=asciify) else: self.config = config # list of all self-running (actor) objects that receive or send # messages on one or more zmq queues self.actors = [] self.greenlets = [] proxy_greenlet = gevent.spawn(self.message_proxy, work_dir) self.greenlets.append(proxy_greenlet) config_actor = ConfigActor(self.config_file, work_dir) config_actor.start() self.actors.append(config_actor) self.greenlets.append(config_actor) # make path in sqlite connection string absolute connection_string = self.config['sql']['connection_string'] if connection_string.startswith('sqlite:///'): _, relative_path = os.path.split(connection_string) connection_string = 'sqlite:///{0}'.format( os.path.join(self.work_dir, relative_path)) database_setup.setup_db(connection_string) database_actor = DatabaseActor(max_sessions, clear_sessions) database_actor.start() self.actors.append(database_actor) self.greenlets.append(database_actor) for g in self.greenlets: g.link_exception(self.on_exception) gevent.sleep() self.started = False if start_webui: from beeswarm.server.webapp import app self.app = app.app self.app.config['CERT_PATH'] = self.config['ssl']['certpath'] app.ensure_admin_password(reset_password) else: self.app = None
def populate_bait(self, honeypot_first): honeypot_id = 1 client_id = 2 honeypot = Honeypot(id=honeypot_id) client = Client(id=client_id) db_session = database_setup.get_session() db_session.add(honeypot) db_session.add(client) db_session.commit() drone_data_socket = beeswarm.shared.zmq_context.socket(zmq.PUB) drone_data_socket.bind(SocketNames.DRONE_DATA.value) config_file = tempfile.mkstemp()[1] os.remove(config_file) # persistence actor needs to communicate with on config REQ/REP socket config_actor = ConfigActor(config_file, '') config_actor.start() # startup session database database_actor = DatabaseActor(999, delay_seconds=2) database_actor.start() gevent.sleep(1) BaitSession.client_id = client_id honeypot_session = HoneypotSession(source_ip='192.168.100.22', source_port=52311, protocol='pop3', users={}, destination_port=110) honeypot_session.add_auth_attempt('plaintext', True, username='******', password='******') honeypot_session.honeypot_id = honeypot_id bait_session = BaitSession('pop3', '1234', 110, honeypot_id) bait_session.add_auth_attempt('plaintext', True, username='******', password='******') bait_session.honeypot_id = honeypot_id bait_session.did_connect = bait_session.did_login = bait_session.alldone = bait_session.did_complete = True if honeypot_first: drone_data_socket.send('{0} {1} {2}'.format( Messages.SESSION_HONEYPOT.value, honeypot_id, json.dumps(honeypot_session.to_dict(), default=json_default, ensure_ascii=False))) drone_data_socket.send('{0} {1} {2}'.format( Messages.SESSION_CLIENT.value, client_id, json.dumps(bait_session.to_dict(), default=json_default, ensure_ascii=False))) else: drone_data_socket.send('{0} {1} {2}'.format( Messages.SESSION_CLIENT.value, client_id, json.dumps(bait_session.to_dict(), default=json_default, ensure_ascii=False))) drone_data_socket.send('{0} {1} {2}'.format( Messages.SESSION_HONEYPOT.value, honeypot_id, json.dumps(honeypot_session.to_dict(), default=json_default, ensure_ascii=False))) # some time for the session actor to work gevent.sleep(2) config_actor.stop() database_actor.stop() if os.path.isfile(config_file): os.remove(config_file)