RU EN

Как попасть на RuCTF

Дружественные соревнования

В настоящий момент нам известны два региональных соревнования, победителей которых мы считаем достойными того, чтобы принять участие в финале RuCTF:

Если вы хотите, чтобы ваше соревнование оказалось в этом списке:

Мы всегда рады видеть новые лица на нашем мероприятии, поэтому существует масса возможностей приехать в Екатеринбург для того, чтобы принять участие в крупнейшем российском студенческом CTF.

Приглашение в финал получают команды:

  • показавшие отличные результаты в нашем отборочном этапе;
  • одержавшие победу на одном из дружественных соревнований.
  • Помимо команд, получивших приглашение в финал, на игровой площадке также резервируется место для одной сборной гостевой команды, которая формируется из участников отдельных команд, не получивших приглашений. В её состав могут войти участники только тех команд, которые никогда ранее не принимали участие в финале RuCTF. От каждой такой команды в гостевую команду мы можем принять не более 3-х человек.

    И наконец, если ваша команда не получила приглашение в финал и не попала в состав гостевой команды, вы можете приехать на игру в качестве наблюдателей или докладчиков. Этот статус не позволяет непосредственно участвовать в игре, но дает возможность наблюдать за ее ходом и изучить работу жюри во время соревнований, а также посетить конференцию. Независимыми наблюдателями могут быть представители не только какого-либо университета, но и коммерческих фирм, государственных учреждений и других организаций.

    Важно! В каком бы качестве вы не собирались посетить финал, вам необходимо уведомить команду организаторов о своих намерениях не позднее, чем за 2 недели до мероприятия. Если вы этого не сделаете, вам не достанется бэйджика, и вы просто не сможете попасть в университет :(.

    Отборочный этап RuCTF

    В этом году роль отборочного этапа RuCTF выполняют международные соревнования RuCTFE 2014.

    Прохождение в финал

    Данные правила могут измениться в любой момент до начала финала. Не забудьте прочитать их еще раз за неделю до финала.

    По итогам отборочного этапа в финал RuCTF проходят 10 лучших российских команд, на момент проведения финала RuCTF состоящих полностью из студентов или магистрантов того вуза, который был указан при регистрации команды.

    Команды, получившие приглашение в финал, должны предоставить организаторам сканы документов подтверждающих статус всех участников. Организаторы оставляют за собой право проверить оригиналы документов непосредственно перед финалом в г. Екатеринбурге.

    Получившая приглашение команда выходит в финал в составе не более 7 человек и не менее 4 человек. Этот состав должен являться подмножеством состава, участвовавшего в отборочном этапе.

    Финал RuCTF

    В начале игры команды получают идентичные серверы с предустановленным набором уязвимых сервисов. Задача участников — найти уязвимости, закрыть их у себя и воспользоваться ими для получения приватной информации (флагов) у соперников. За процессом игры непрерывно следит проверяющая система жюри, регулярно помещая новые флаги на серверы команд. Кроме того, система принимает от команд флаги, захваченные у соперников.

    Очень непросто формализовать набор правил, по которым проводится CTF, поэтому этот раздел может поменяться в любой момент до начала игры. Не забудьте перед игрой прочитать его еще раз, на всякий случай :).

    Определения

    Команда

    Группа людей во главе с капитаном. Размер любой команды за исключением сборной гостевой не должен превышать 7 человек.

    Сервис

    Уязвимое приложение, специально подготовленное командой разработчиков для игры.

    Флаг

    Строка, удовлетворяющая регулярному выражению: /^\w{31}=$/. Время жизни флага ограничено, и старые флаги не влияют на начисление очков.

    Проверяющая система

    Автоматическая система, которая заносит в сервисы флаги, проверяет работоспособность сервисов и начисляет очки. Начисленные очки наряду с состоянием сервисов отображаются в скорборде.

    Игровой раунд

    Промежуток времени, за который проверяющая система заносит в сервисы новые флаги, проверяет наличие старых флагов, и начисляет очки за защиту. Все раунды длятся равное количество времени, от 5 до 15 минут в зависимости от игры.

    Жюри

    Группа людей, ответственная за проведение игры. Жюри делает все возможное для того, чтобы игра получилась качественной, честной, и доставила участникам удовольствие. Тем не менее, жюри может наказать или дисквалифицировать команду за нарушение правил, а также может принимать решения в критических ситуациях, не описанных в данных правилах. Команды должны быть готовы отнестись к таким решениям с пониманием. Также жюри определяет победителя. По большей части, это решение основывается на скорборде.

    Командам разрешено

    • Делать все, что заблагорассудится, внутри своего сегмента сети. Скорее всего, команды захотят изменить конфигурацию своего сервера и закрыть уязвимости в своих сервисах;
    • Атаковать другие команды в пределах игровой сети. Неожиданно, да?

    Командам запрещено

    • Атаковать системы организаторов;
    • Фильтровать трафик от других команд;
    • Генерировать большой объем трафика, представляющий угрозу стабильности систем организаторов или других команд.

    Ход игры

    Игра начинается с выдачи участникам игрового образа с предустановленным набором уязвимых сервисов. В течение первого часа после выдачи игрового образа сегменты сети закрыты, и командам следует сконцентрироваться на администрировании своего игрового сервера и анализе уязвимостей. По истечение этого часа сеть открывается, и в течение 8 часов команды могут эксплуатировать уязвимости с целью получения флагов у других команд.

    Начисление баллов

    Ключевыми понятиями в начислении очков являются понятия SLA и FlagPoints. Эти величины индивидуальны для каждого сервиса каждой команды. В каждый момент времени очки команды вычисляются как сумма произведения SLA сервиса на FlagPoints сервиса для всех сервисов.

    SLA(team, service) — это доля от прошедшего игрового времени, в течение которой данный сервис у данной команды был в состоянии UP. Например, если сервис ни разу за прошедшее игровое время не опускался, SLA будет равен 1. Если прошло 4 часа игры, и сервис работал первый час, а потом опустился на 3 часа, SLA будет равен 0.25. В начале игры SLA всех сервисов у всех команд равен 1.

    FlagPoints(team, service) — это неотрицательное число, которое коррелирует с тем, насколько хорошо команда понимает данный сервис. Если команда умеет эксплуатировать уязвимости в этом сервисе, и закрыла их у себя, ее FlagPoints будет расти. Если она не умеет эксплуатировать уязвимости в этом сервисе и не озаботилась их закрытием, ее FlagPoints будет стремительно приближаться к нулю. Если она закрыла уязвимости, но не научилась их эксплуатировать, ее FlagPoints не будет меняться.

    В начале игры значение FlagPoints всех сервисов у всех команд одинаково. В течение игры сумма всех FlagPoints является константой.

    Стоимость флага — это то, сколько очков будет перераспределено между жертвой и атакующими. Стоимость флага равна количеству играющих команд.

    FlagPoints(team, service) уменьшается на стоимость флага за каждый флаг, который был украден у этой команды с этого сервиса, до тех пор, пока не достигнет нуля. FlagPoints увеличивается за каждый флаг, который был украден у другой команды с этого сервиса с ненулевым FlagPoints, при условии, что на момент сдачи флага этот сервис у атакующей команды находится в состоянии UP.

    Если один и тот же флаг был украден несколькими командами, каждая из этих команд получит равную долю от стоимости флага. Начисление и снятие очков за украденный флаг происходит в момент истечения времени жизни флага.

    К счастью, весь этот сложный текст можно лаконично изложить в виде псевдокода:

    def on_game_start(team):
        team.sla = [1] * number_of_services
        team.flagpoints = [BAZILLION] * number_of_services
    
    def on_flag_post(attacker, flag):
        if attacker.service_states[flag.service] == 'UP':
            flag.attackers.append(attacker)
    
    def on_flag_end_of_life(flag):
        team = flag.owner
        service = flag.service
        if team.flagpoints[service] == 0:
            return
        flag_score = min(number_of_teams, team.flagpoints[service])
        team.flagpoints[service] -= flag_score
        flag_score /= len(flag.attackers)
        for attacker in flag.attackers:
            attacker.flagpoints[service] += flag_score
    
    def get_score(team):
        return sum(map(lambda x: x[0] * x[1], zip(team.sla, team.flagpoints)))
    

    Скорборд

    Помимо текущих результатов, скорборд отображает SLA, FlagPoints и статус каждого сервиса у каждой команды. Статусы бывают такими:

    • UP означает, что сервис доступен по сети, отвечает на запросы и ведет себя так, как того ожидает проверяющая система.
    • MUMBLE означает, что сервис доступен по сети, но ведет себя не так, как того ожидает проверяющая система. Например, если HTTP сервер не отвечает на запросы.
    • CORRUPT означает, что сервис доступен по сети, но не может отдать один из предыдущих флагов.
    • DOWN означает, что сервис недоступен по сети.

    Сеть финала RuCTF

    В случае изменение сетевой топологии, командам об этом будет сообщено дополнительно.

    Схема сети