Example #1
0
def get_scripts_to_run(tick_id=None):
    """
    The ``/scripts/get/torun`` endpoint requires authentication.
     By default, it returns all scripts that needs to be run for current tick.

    It can be reached at ``/scripts/get/torun?secret=<API_SECRET>``.

    The JSON response looks like::

        {
          "scripts_to_run" : [List of {
                                    "id" : int,
                                    "script_id" : int,
                                    "against_team_id": int,
                                    "tick_id" : int}]
        }

    :return: a JSON dictionary that contains all script that needs to be run.
    """
    cursor = mysql.cursor()

    # Get basic information about the game, like tick info and services
    if tick_id is None:
        current_tick, tick_start, seconds_to_next_tick, _ = get_current_tick(cursor)
        tick_id = current_tick

    cursor.execute("""SELECT id, script_id, against_team_id, tick_id
                      FROM script_runs
                      WHERE error is NULL AND tick_id = %s""",
                   (tick_id,))
    return json.dumps({"scripts_to_run": cursor.fetchall()})
Example #2
0
def get_services_state():
    if request.args.get('secret') != API_SECRET:
        abort(401)

    current_tick, time_left = get_current_tick()

    return jsonify(get_service_state_by_tick(current_tick))
Example #3
0
def services_get_status(team_id=0):
    """The ``/services/status/team`` endpoint requires authentication and takes an
    ``team_id`` argument. It fetches the services' status for the specified
    team for the current tick .

    The JSON response looks like::

        {
        team_id: {
                  service_id: {
                               "service_name": string,
                               "service_state": ("up",
                                                 "notfunctional",
                                                 "down",
                                                 "untested")
                              }
                 }
        }

    :param int team_id: optional tick_id
    :return: a JSON dictionary that maps teams to service states.
    """
    cursor = mysql.cursor()

    tick_id, _, _, _ = get_current_tick(cursor)

    if team_id == 0:
        team_id = "ts.team_id"

    # now get the real results
    cursor.execute(
        """SELECT ts.service_id, ts.tick_id, ts.team_id, ts.state, svcs.port, svcs.name
                      FROM curr_team_service_state ts, services svcs
                      WHERE (ts.tick_id = %s OR ts.tick_id = %s) AND ts.team_id=%s AND svcs.id = ts.service_id 
                      ORDER BY ts.tick_id, svcs.port""",
        (tick_id, (tick_id - 1), team_id))

    # build the result dict
    out = dict()
    for result in cursor.fetchall():
        nm = result["name"][slice(-10, None)]

        name_val = "{:10}".format(nm) + " status:{:4}".format(
            result["state"]) + " Port:" + str(result["port"])
        if result["tick_id"] not in out:
            out[result["tick_id"]] = list()

        out[result["tick_id"]].append(name_val)

    return json.dumps(out)
Example #4
0
def service_enable_disable(service_id):
    """The ``/service/enable`` and ``/service/disable`` endpoints requires
    authentication and expect no additional arguments. It enables or disables
    a service starting at the next tick.

    Note that this endpoint requires a POST request.

    It can be reached at
    ``/service/enable/<service_id>?secret=<API_SECRET>`` or
    ``/service/disable/<service_id>?secret=<API_SECRET>``.

    It expects the following inputs:

    - reason, the reason why the service was enabled (optional)

    The optional ``reason`` argument is any string and justifies why the the
    service was enabled or disabled.

    The JSON response is::

        {
          "id": int,
          "result": ("success", "failure")
        }

    :param int service_id: the id of the service to be enabled or disabled.
    :return: a JSON dictionary with a result status, to verify if setting the
             state was successful.
    """
    state = "enabled" if "enable" in request.path else "disabled"
    reason = request.form.get("reason", None)

    cursor = mysql.cursor()
    tick_id, _, _, _ = get_current_tick(cursor)

    cursor.execute(
        """UPDATE services set current_state = %s
                      WHERE id = %s""", (state, service_id))

    # update the service_state log
    cursor.execute(
        """INSERT INTO service_state
                             (service_id, state, reason, tick_id)
                      VALUES (%s, %s, %s, %s)""",
        (service_id, state, reason, tick_id))
    mysql.database.commit()

    return json.dumps({"id": cursor.lastrowid, "result": "success"})
Example #5
0
def services_get_history_status(history_cnt=10):
    """The ``/services/history/statius`` endpoint requires authentication.
    It fetches the services' status for the last 10 ticks and summarizes them in a json object.

    The JSON response looks like::

        {
        service_info: {
                  team_id: [ status1, status2, status3 ... ]

                 }
        }

    :return: a JSON dictionary that maps teams to service states.
    """
    cursor = mysql.cursor()

    tick_id, _, _, _ = get_current_tick(cursor)
    lower_tick_id = tick_id - history_cnt
    print("LOWER TICK ID {}".format(lower_tick_id))
    sql = """ SELECT ts.service_id, ts.tick_id, ts.team_id, ts.state, svcs.port, svcs.name
              FROM curr_team_service_state ts, services svcs
              WHERE (ts.tick_id >= %s ) AND svcs.id = ts.service_id 
              ORDER BY svcs.port, ts.tick_id"""
    print(sql % (lower_tick_id))
    # now get the real results
    cursor.execute(sql, (lower_tick_id, ))

    # build the result dict
    out = dict()
    for result in cursor.fetchall():
        nm = "{}:{}".format(result["name"], result["port"])
        nm = nm[slice(-15, None)]
        if nm not in out:
            out[nm] = dict()

        team_id = "team{:5}".format(result["team_id"])
        if team_id not in out[nm]:
            out[nm][team_id] = ""

        if result["state"] == "up":
            out[nm][team_id] += "____ "
        else:
            status = result["state"][slice(-4, None)]
            out[nm][team_id] += "{:4} ".format(status)

    return json.dumps(out)
Example #6
0
def game_get_info():
    """The ``/game/info`` endpoint requires authentication and expects no
    other arguments.

    It can be reached at ``/game/info?secret=<API_SECRET>``.

    It is used to retrieve the information about the game, like team and service
    information.

    The JSON response looks like::

        {
          "services": [List of {"service_id": int,
                                "service_name": string,
                                "port": int,
                                "flag_id_description": string,
                                "description": string,
                                "state": ("enabled", "disabled")}],
          "teams": [List of {"team_id": int,
                             "team_name": string,
                             "url": string,
                             "country": 2-digit country code according
                                        to ISO-3166-1, ZZ for unknown}]
        }

    :return: a JSON dictionary with a list of all teams and a list of all
             services, including auxiliary information.

    """
    cursor = mysql.cursor()
    cursor.execute("""SELECT id as team_id, name as team_name,
                             url, country FROM teams""")
    teams = cursor.fetchall()

    _, tick_start, _, _ = get_current_tick(cursor)
    cursor.execute("""SELECT id as service_id, name as service_name,
                             port, flag_id_description, description,
                             current_state as state
                      FROM services""")
    services = cursor.fetchall()

    return json.dumps({"teams": teams, "services": services})
Example #7
0
def current_tick_num():
    """The ``/game/tick/`` endpoint requires authentication and expects no
    other arguments.

    It can be reached at ``/game/tick?secret=<API_SECRET>`` or at
    ``/game/tick?secret=<API_SECRET>``.

    It is used to retrieve the information about the current tick.

    The JSON response looks like::
    {"created_on": "2015-11-30 17:01:42",
     "approximate_seconds_left": 0,
     "tick_id": 47}

    :return: a JSON dictionary with information about the current tick.
    """
    cursor = mysql.cursor()
    tick_id, created_on, seconds_left, ends_on = get_current_tick(cursor)
    return json.dumps({
        "tick_id": tick_id,
        "created_on": str(created_on),
        "approximate_seconds_left": seconds_left,
        "ends_on": str(ends_on)
    })
Example #8
0
def current_state():
    """
    state_id is
    :return:
    """

    if request.args.get('secret') != API_SECRET:
        abort(401)

    # from sqlalchemy.ext.serializer import loads, dumps

    event = Event.query.order_by(Event.id.desc()).first()
    current_tick, seconds_to_next_tick = get_current_tick()
    # is 0,1337 when there is no tick for current event yet
    # is None, 1337 ??

    if current_tick is None:
        print("Warning: There is no current tick. Game not started yet?")
        return jsonify({
            'state_id': 0,
            'state_expire': 1337,
            'game_id': 0,
        })

    result = {
        'state_id': current_tick.id,
        'state_expire': seconds_to_next_tick,
        'game_id': event.id,
        # 'services':  [object_as_dict(u) for u in ],
        # 'scripts': list(Script.query.filter_by(event=event)),
        # 'run_scripts': [{'team_id': tsrs.attending_team.id, 'run_list': json.loads(tsrs.json_list_of_scripts_to_run) } for tsrs in TeamScriptsRunStatus.query.filter_by(tick=current_tick)]
    }

    services = []
    for service in Challenge.query.filter_by(type="ad", event=event):
        services.append({
            'service_id': service.id,
            'service_name': service.name,  # ??? TODO
            # 'type': str(service.type), # NEW
            'port': service.port,
        })
    result['services'] = services

    scripts = []
    for script in Script.query.filter_by(event=event):
        scripts.append({
            'script_id': script.id,
            'is_bundle': 0,
            'type': str(script.type).split(".")[-1],
            'script_name': script.name,
            'service_id': script.challenge.id,
        })
    result['scripts'] = scripts

    run_scripts = []
    for run_script in TeamScriptsRunStatus.query.filter_by(tick=current_tick):
        run_scripts.append({
            'team_id':
            run_script.attending_team.id,
            'run_list':
            json.loads(run_script.json_list_of_scripts_to_run),
        })
    result['run_scripts'] = run_scripts

    return jsonify(result)
Example #9
0
def script_new():
    """The ``/script/new`` endpoint requires authentication.
    It add a script to the database, and initializes its state.

    Note that this endpoint requires a POST request.

    It can be reached at
    ``/script/new?secret=<API_SECRET>``.

    It requires the following inputs:

    - name, an optional name of the script.
    - upload_id, upload which has the payload.
    - filename, the name of the file
    - type, the type of the script, currently exploit, benign, getflag, or
            setflag.
    - state, enabled, disabled. Defaults to "enabled"
    - service_id

    The JSON response looks like::

        {
          "id" : int,
          "result": ("success", "failure")
        }

    :return: a JSON dictionary containing status information.
    """
    upload_id = request.form.get("upload_id")
    filename = request.form.get("filename")
    type_ = request.form.get("type")
    state = request.form.get("state", "enabled")
    service_id = request.form.get("service_id")

    if state not in ("enabled", "disabled"):
        abort(400)

    cursor = mysql.cursor()

    # get the team_id from the uploads
    cursor.execute("""SELECT team_id
                          FROM uploads WHERE id = %s LIMIT 1""",
                   (upload_id,))
    result = cursor.fetchone()
    team_id = result["team_id"]


    # add the script
    cursor.execute("""INSERT INTO scripts (type, team_id, service_id,
                                           upload_id, filename, current_state)
                      VALUES (%s, %s, %s, %s, %s, %s)""",
                   (type_, team_id, service_id, upload_id,
                    filename, state))

    script_id = cursor.lastrowid

    # set it in the script state log
    tick_id, _, _, _ = get_current_tick(cursor)
    cursor.execute("""INSERT INTO script_state (script_id, state, reason, tick_id)
                      VALUES (%s, %s, %s, %s)""",
                   (script_id, state, "initial state", tick_id))
    mysql.database.commit()

    return json.dumps({"result": "success",
                       "id": script_id})
Example #10
0
def game_get_state():
    """The ``/game/state`` endpoint requires authentication and expects no
    other arguments.

    It can be reached at ``/game/state?secret=<API_SECRET>``.

    It is used to retrieve the current state of the game.

    The JSON response looks like::

        {
          "state_id": int,
          "game_id": int,
          "services": [List of {"service_id": int,
                                "service_name": string,
                                "port": int}],
          "scripts": [List of {"script_id": int,
                               "upload_id": int,
                               "type": ("exploit", "benign", "getflag",
                                        "setflag"),
                               "script_name": string,
                               "service_id": int}]
          "run_scripts": [{"team_id": int (team_id to run scripts against),
                           "run_list": [Ordered list of int script_ids]}],
          "state_expire": int (approximate remaining seconds in this tick),
        }

    :return: a JSON dictionary providing information on the current state.
    """
    cursor = mysql.cursor()

    # Get basic information about the game, like tick info and services
    to_return = {}
    current_tick, tick_start, seconds_to_next_tick, _ = get_current_tick(
        cursor)
    to_return["state_id"] = current_tick
    to_return["state_expire"] = seconds_to_next_tick

    cursor.execute("SELECT id FROM game LIMIT 1")
    game_cursor = cursor.fetchone()
    if game_cursor is None:
        to_return["num"] = "621"
        to_return["msg"] = "No game is currently running..."
        return json.dumps(to_return)

    to_return["game_id"] = game_cursor["id"]

    cursor.execute("""SELECT services.id AS service_id,
                             services.name as service_name,
                             services.port as port,
                             current_state as state
                      FROM services""")
    to_return["services"] = cursor.fetchall()

    # Determine which scripts exists and which should be run
    cursor.execute(
        """SELECT id AS script_id, upload_id, filename AS script_name,
                             type, service_id,
                             current_state as state
                      FROM scripts""")
    to_return["scripts"] = cursor.fetchall()

    cursor.execute(
        """SELECT team_id, json_list_of_scripts_to_run AS json_list
                      FROM team_scripts_run_status
                      WHERE team_scripts_run_status.tick_id = %s""",
        (current_tick, ))
    run_scripts = []
    for team_scripts_to_run in cursor.fetchall():
        team_id = team_scripts_to_run["team_id"]
        run_list = json.loads(team_scripts_to_run["json_list"])
        run_scripts.append({"team_id": team_id, "run_list": run_list})

    to_return["run_scripts"] = run_scripts
    return json.dumps(to_return)
Example #11
0
def main():
    event = Event.query.order_by(Event.id.desc()).first()
    while not game_ad_running():
        event = Event.query.order_by(Event.id.desc()).first()

        logger.info(
            "AD Game is not running. Gamebot will start at {} (UTC) (System time (UTC) now is {})"
            .format(str(event.attack_defense_start), str(datetime.now())))
        sleep(10)

    current_tick, seconds_left = get_current_tick()
    if current_tick != None:
        # Gibt schon einen Tick, dann erstelle nicht direkt noch einen
        logger.info("We must be picking up from the last run. Sleep for",
                    seconds_left, "until the next tick.")
        sleep(seconds_left)

    while True:
        event = Event.query.order_by(Event.id.desc()).first()

        if not game_ad_running():
            logger.info("Game ended at {}".format(str(datetime.now())))
            break

        # Create a new tick
        time_to_sleep = random.uniform(TICK_TIME_IN_SECONDS - 30,
                                       TICK_TIME_IN_SECONDS + 30)

        tick = Tick()
        tick.time_to_change = datetime.now() + timedelta(seconds=time_to_sleep)
        tick.event = event
        db_session.add(tick)
        db_session.commit()
        # db_session.remove()

        num_benign_scripts = random.randint(
            max(1, NUMBER_OF_BENIGN_SCRIPTS - 1), NUMBER_OF_BENIGN_SCRIPTS + 1)

        # Decide what scripts to run against each team

        for attending_team in AttendingTeam.query.filter_by(event=event):
            list_of_scripts_to_execute = get_list_of_scripts_to_run(
                Challenge.query.filter_by(type='ad', event=event),
                num_benign_scripts)
            tsrs = TeamScriptsRunStatus()
            tsrs.attending_team = attending_team
            tsrs.tick = tick
            tsrs.json_list_of_scripts_to_run = json.dumps(
                list_of_scripts_to_execute, ensure_ascii=False)

            db_session.add(tsrs)
            db_session.commit()
        # db_session.remove()

        # Sleep for the amount of time until the next tick
        time_diff_to_sleep = tick.time_to_change - datetime.now()
        seconds_to_sleep = time_diff_to_sleep.seconds + (
            time_diff_to_sleep.microseconds / 1E6)

        if time_diff_to_sleep.total_seconds() < 0:
            logger.debug(
                "Time left is negative: {}".format(time_diff_to_sleep))
            seconds_to_sleep = 0

        logger.info("Sleeping for {}".format(seconds_to_sleep))
        sleep(seconds_to_sleep)
        logger.info("Awake")
Example #12
0
def service_set_state(service_id, team_id):
    """The ``/service/state`` endpoint requires authentication and expects
    the ``team_id`` and ``service_id`` as additional arguments. It sets the
    the state for a specific service for a specific team.

    Note that this endpoint requires a POST request.

    It can be reached at
    ``/service/state/set/<service_id>/team/<team_id>?secret=<API_SECRET>``.

    It expects the following inputs:

    - state, the state the service is in.
    - reason, the reason why the state was changed.

    The ``state`` argument must conform to the following notion:

    - up, which means the service is up
    - notfunctional, which means it is up but not functional
    - down, which means it is down (refusing connections)

    The ``reason`` argument is any string and can be a return value of a
    verification script.

    The JSON response is::

        {
          "id": int,
          "result": ("success", "failure")
        }

    :param int team_id: the ID of the team to be updated.
    :param int service_id: the ID of the service to be updated.
    :return: a JSON dictionary with a result status, to verify if setting the
             state was successful.
    """
    state = request.form.get("state")
    reason = request.form.get("reason")

    # Allow old numerical-style status and convert to enum
    if state not in ("up", "notfunctional", "down"):
        old_code = int(state)
        if old_code not in (0, 1, 2):
            abort(400)
        state = ["down", "notfunctional", "up"][int(state)]

    if state not in ("up", "notfunctional", "down"):
        abort(400)

    cursor = mysql.cursor()
    tick_id, _, _, _ = get_current_tick(cursor)

    # check that the service is enabled, otherwise state is untested
    cursor.execute(
        """SELECT current_state
                         FROM services
                      WHERE id = %s LIMIT 1""", (service_id, ))
    result = cursor.fetchone()
    if result["current_state"] != 'enabled':
        state = "untested"

    # get the new state for the current state table
    cursor.execute(
        """SELECT state
                         FROM curr_team_service_state
                      WHERE tick_id = %s and team_id = %s and service_id = %s LIMIT 1""",
        (tick_id, team_id, service_id))
    result = cursor.fetchone()
    new_state = state
    if result:
        # the new state for the current table will be down if it was down at all that tick
        if result["state"] == "down" or state == "down":
            new_state = "down"
        elif result["state"] == "notfunctional" or state == "notfunctional":
            new_state = "notfunctional"
        elif result["state"] == "up" or state == "up":
            new_state = "up"

    # add to the log
    cursor.execute(
        """INSERT INTO team_service_state
                             (team_id, service_id, state, reason, tick_id)
                      VALUES (%s, %s, %s, %s, %s)""",
        (team_id, service_id, state, reason, tick_id))

    # update the current state
    cursor.execute(
        """INSERT INTO curr_team_service_state
                          (tick_id, team_id, service_id, state)
                      VALUES(%s, %s, %s, %s)
                      ON DUPLICATE KEY UPDATE state=%s""",
        (tick_id, team_id, service_id, new_state, new_state))

    mysql.database.commit()

    return json.dumps({"id": cursor.lastrowid, "result": "success"})
Example #13
0
def services_get_states(tick_id=None):
    """The ``/services/states`` endpoint requires authentication and takes an
    optional ``tick_id`` argument. It fetches the services' states for all
    teams for the current tick if no ``tick_id`` is provided, or for the
    specified ``tick_id`` otherwise.

    It can be reached at ``/services/states?secret=<API_SECRET>``.

    It can also be reached at
    ``/services/states/tick/<tick_id>?secret=<API_SECRET>``.

    The JSON response looks like::

        {
        team_id: {
                  service_id: {
                               "service_name": string,
                               "service_state": ("up",
                                                 "notfunctional",
                                                 "down",
                                                 "untested")
                              }
                 }
        }

    :param int tick_id: optional tick_id
    :return: a JSON dictionary that maps teams to service states.
    """
    cursor = mysql.cursor()
    if tick_id is None:
        tick_id, _, _, _ = get_current_tick(cursor)
        if tick_id > 0:
            tick_id -= 1

    cursor.execute(
        """SELECT id, name FROM services WHERE current_state = 'enabled' """)
    services = dict()
    for result in cursor.fetchall():
        services[result["id"]] = result["name"]

    # start building the dict
    # we do this here since the table of service states might not have results if things weren't going well
    # in which case services are untested
    teams = dict()
    cursor.execute("""SELECT id from teams""")
    for result in cursor.fetchall():
        team_id = result["id"]
        teams[team_id] = dict()
        for service_id, name in services.items():
            teams[team_id][service_id] = {
                "service_name": name,
                "service_state": "untested"
            }

    # now get the real results
    cursor.execute(
        """SELECT ts.team_id, ts.service_id, ts.state, s.name
                          FROM curr_team_service_state as ts
                      JOIN services as s ON s.id = ts.service_id
                      WHERE tick_id = %s AND s.current_state = 'enabled' """,
        (tick_id, ))

    # build the result dict
    for result in cursor.fetchall():
        team_id = result["team_id"]
        service_name = result["name"]
        service_id = result["service_id"]
        state = result["state"]

        service_dict = dict()
        service_dict["service_name"] = service_name
        service_dict["service_state"] = state

        teams[team_id][service_id] = service_dict

    return json.dumps({"service_states": teams})
Example #14
0
def service_new():
    """The ``/service/new`` endpoint requires
    authentication. It adds a service to the database and initializes its state.

    Note that this endpoint requires a POST request.

    It can be reached at
    ``/service/new?secret=<API_SECRET>``.

    It requires the following inputs:

    - name, the name of the service.
    - upload_id, upload which has the payload.
    - description, the description of the service.
    - authors, optional
    - flag_id_description, description of the flag_id
    - state, enabled, disabled. Defaults to "enabled"

    The JSON response looks like::

        {
          "id" : int,
          "result": ("success", "failure")
        }

    :return: a JSON dictionary containing status information.
    """
    name = request.form.get("name")
    upload_id = request.form.get("upload_id")
    description = request.form.get("description")
    authors = request.form.get("authors", None)
    flag_id_description = request.form.get("flag_id_description")
    state = request.form.get("state", "enabled")

    if state not in ("enabled", "disabled"):
        abort(400)

    cursor = mysql.cursor()

    # get the team_id from the uploads
    cursor.execute(
        """SELECT team_id
                          FROM uploads WHERE id = %s LIMIT 1""", (upload_id, ))
    result = cursor.fetchone()
    team_id = result["team_id"]

    cursor.execute(
        """INSERT INTO services (name, upload_id, description, authors,
                                           flag_id_description, team_id, current_state)
                      VALUES (%s, %s, %s, %s, %s, %s, %s)""",
        (name, upload_id, description, authors, flag_id_description, team_id,
         state))
    service_id = cursor.lastrowid

    # set the state in the log
    tick_id, _, _, _ = get_current_tick(cursor)
    cursor.execute(
        """INSERT INTO service_state (service_id, state, reason, tick_id)
                      VALUES (%s, %s, %s, %s)""",
        (service_id, state, "initial state", tick_id))

    # set the port number to service_id + 10000
    cursor.execute(
        """UPDATE services SET port = %s
                      WHERE id = %s""", (service_id + 10000, service_id))

    mysql.database.commit()

    return json.dumps({"result": "success", "id": service_id})
Example #15
0
def get_wasexploited(tick_id=None):
    """The ``/flags/wasexploited/tick/`` endpoints requires
    authentication and expect no additional arguments.
    It fetches all the flags captured and lost by all the teams
    in the given tick.

    It can be reached at
    ``/flags/wasexploited/tick/<tick_id>?secret=<API_SECRET>``
    ``/flags/wasexploited?secret=<API_SECRET>``

    The JSON response is::

        {
        team_id: {
                  service_id: {
                               "service_name": string,
                               "service_state": ("exploited",
                                                 "notexploited")
                              }
                 }
        }

    :param int tick_id: The target tick id for which the flags
           information is needed.
    :return: a JSON dictionary for each team with flag information.
    """

    cursor = mysql.cursor()
    if tick_id is None:
        tick_id, _, _, _ = get_current_tick(cursor)

    cursor.execute("""SELECT id, name FROM services WHERE current_state = 'enabled' """)
    services = dict()
    for result in cursor.fetchall():
        services[result["id"]] = result["name"]

    # start building the dict
    # we do this here since the table of service states might not have results if things weren't going well
    # in which case services are untested
    teams = dict()
    cursor.execute("""SELECT id from teams""")
    for result in cursor.fetchall():
        team_id = result["id"]
        teams[team_id] = dict()
        for service_id, name in services.items():
            teams[team_id][service_id] = {"service_name": name, "service_state": "notexploited"}

    # Perform the main query
    cursor = mysql.cursor()
    cursor.execute("""SELECT DISTINCT fl.team_id as against_team_id, fs.service_id as service_id
                      FROM flag_submissions as fs, flags as fl
                      WHERE fs.tick_id = %s
                        AND fs.result = 'correct'
                        AND fs.flag_id = fl.id""", (tick_id,))

    for result in cursor.fetchall():
        against_team_id = result["against_team_id"]
        service_id = result["service_id"]
        teams[against_team_id][service_id]["service_state"] = "exploited"

    return json.dumps(teams)
Example #16
0
def get_tick_duration():
    _, seconds_to_next_tick = get_current_tick()
    return json.dumps(seconds_to_next_tick)