featured for Секретное задание на олимпиаде

Секретное задание на олимпиаде

Jan 23, 2021

Вчера закончился первый этап Всеукраинской олимпиады по программированию 2021 и пришло время раскрыть тайну секретного задания от E-Olymp.

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

Такого рода задания достаточно популярны, они называются “захват флага” (capture the flag) и направлены на изучение и получение опыта машинной защиты и кибербезопасности. Существуют целые соревнования, в которых участникам предлагается найти все уязвимые места в системе в кратчайшие сроки.

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

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

Внимание! Такого рода задания не будут доступны во время следующих этапов олимпиады, поэтому не ищите задания во время олимпиады, а сфокусируйтесь на решении задач. Более того, действия связанные с поиском уязвимых мест во время этапа олимпиады могут быть расценены, как попытка вмешательства в работу системы, за что вы можете быть дисквалифицированы. Я размещу еще, как минимум, одно задание такого рода, но оно будет доступно только в дни, когда не проходят этапы олимпиады. Подпишитесь на нашу страницу в Facebook и телеграмм канал олимпиады, чтобы узнать когда будет доступно следующее задание.


По сценарию, в нашем задании один из разработчиков создал API (см. пояснения ниже) с помощью которого организаторы олимпиады могут давать участникам специальную отметку в виде короны. Эта отметка отображается в рейтинге справа от имени участника.

Crown

Для того, чтобы не забыть ссылку на API разработчик решил записать его в исходном коде сайта stats.uoi2021.org как комментарий. Разработчик решил, что поскольку ссылка записана как комментарий, никто из пользователей ее не увидит.

API должен использоваться только организаторами олимпиады, но разработчик забыл добавить проверку на то, или пользователь является организатором. Таким образом, разработчик создал уязвимый, не защищеный API, который может быть использован хакерами.

API (application programming interface) - это интерфейс для взаимодействия между программами, то есть способ для одной программы выполнить какое-то действие в другой.

Вам скорее всего известно понятие GUI (графический интерфейс пользователя). Когда вы запускаете программу, вы видите перед собой окно с кнопками, полями ввода, картинками, текстом и тд. Этот интерфейс создан для того, чтобы людям было удобно взаимодействовать с программой. Такой интерфейс удобный для людей, но не удобный для других программ. Для того, чтобы программы могли взаимодействовать между собой необходимо создать API.

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


Чтобы использовать уязвимость, для начала нам необходимо найти ссылку на API.

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

Для того, чтобы просмотреть исходный код страницы, откройте ее в браузере, сделайте правый клик в любом месте на странице и выберите “Просмотреть исходный код” (View Page Source). После этого вы увидите HTML код документа и комментарии в нем.

Если перейти на страницу https://stats.uoi2021.org и посмотреть ее исходный код, можно найти следующее сообщение:

...
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <!-- Возак Кус завжди забуває важливі API посилання, тому записав їх тут. Секретне посилання: https://api.e-olymp.com/uoi/crown (НІКОМУ НЕ ДАВАТИ!!!!) -->
    <div id="root"></div>
...

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

HTTP клиент это программа, которая может делать запросы к серверу, используя HTTP протокол. Например, ваш браузер является HTTP клиентом.

Также во всех языках программирования есть библиотеки, реализующие HTTP клиент. Например, в языке программирования Python эту функцию выполняет библиотека requests.

Теперь мы можем сделать запрос по этой ссылке и узнать больше информации о ней. Для начала можно попробовать использовать браузер. Если мы откроем ссылку https://api.e-olymp.com/uoi/crown в браузере, мы увидим следующее сообщение:

Only POST method is allowed, if you are using curl make sure to add `-X POST` to the request.

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

Итак, открыв ссылку, мы увидели сообщение об ошибке. Это сообщение содержит фразу “Только метод POST разрешен”. Если вы не знакомы с протоколом HTTP, вам придется поискать информацию о нем в сети интернет. Попробуйте поискать по словам “HTTP POST” или “method POST”. Например, можно найти информацию о HTTP протоколе на странице Википедии.

Для выполнения задания вам нужно знать, что протокол HTTP - это сетевой протокол. С помощью HTTP протокола вы можете сделать запрос к ресурсам, размещенным на HTTP сервере, используя один из HTTP методов.

HTTP протокол является самым популярным в мире, он используется сетью Интернет для обмена данными между веб-сервером и браузером. Очень часто он используется для передачи HTML, CSS и JavaScript файлов, которые используются для того, чтобы показать содержание сайтов, хотя сам HTTP протокол может быть использован для любых данных.

Браузер по умолчанию делает GET запрос к URL который вы вводите в строку адреса. Есть множество способов сделать POST запрос, скорее всего вы найдете следующие методы:

  • Сделать запрос с помощью приложения из командной строки (CLI), например curl.
  • Сделать запрос с помощью библиотеки языка программирования. Введите название языка программирования в поисковый запрос, чтобы получить больше примеров.
  • Сделать запрос с помощью графического приложения, например Postman или веб приложения, например https://reqbin.com/.

Все эти методы подходят и вы можете использовать любой из них. Протокол HTTP очень распространен и имеет достаточно строгий стандарт.

curl способ

Сообщение об ошибке упоминает програму curl, поэтому попробуем использовать ее. Curl это программа с интерфейсом командной строки (cli или command-line interface) и один из самых распространенных HTTP клиентов. Она установлена по умолчанию почти во всех версиях Linux. Для Windows ее придется устанавливать отдельно.

Если у вас возникают трудности с использованием curl, ниже приведен пример с использованием Python.

Откройте терминал (интерфейс командной строки) и попробуйте выполнить:

curl https://api.e-olymp.com/uoi/crown

Эта команда делает запрос к https://api.e-olymp.com/uoi/crown используя метод GET. Вы должны увидеть такое же сообщение, что и раньше:

Only POST method is allowed, if you are using curl make sure to add `-X POST` to the request.

В сообщении написано, что необходимо добавить флаг -X. Согласно документации к curl этот флаг позволяет выбрать HTTP метод. Именно то, что нам надо! Попробуем добавить флаг -X POST, как указано в сообщении.

curl https://api.e-olymp.com/uoi/crown -X POST

Мы получим другое сообщение:

Payload (request body) has to be a valid JSON object (https://uk.wikipedia.org/wiki/JSON). If you are using curl add `-d '{}'` options. During parsing an error occurred: EOF.

Похоже метод запроса правильный, но мы получили другое сообщение об ошибке. В нем написано, что “содержание запроса” должно содержать правильный JSON объект. Там также есть ссылка на википедию, где есть больше информации о JSON формате.

Теперь в сообщении написано, что нужно использовать флаг -d. Согласно документации этот флаг позволяет указать содержание запроса. Таким образом флаг -d '{}' добавит к запросу содержание {}, что в формате JSON означает “пустой” объект.

curl https://api.e-olymp.com/uoi/crown -X POST -d '{}'

Новое сообщение от системы:

Request must contain a valid participant_id. Make sure this participant is registered in UOI and has at least 500 points. You must find participant_id and pass it in request body like so: {"participant_id": "...not a very secret value which can be found when inspecting requests..."}

Похоже необходимо указать participant_id, в сообщении. Попробуем использовать пример из сообщения об ошибке.

curl https://api.e-olymp.com/uoi/crown -X POST -d '{"participant_id": "...not a very secret value which can be found when inspecting requests..."}'

Опять та же ошибка:

Request must contain a valid participant_id. Make sure this participant is registered in UOI and has at least 500 points. You must find participant_id and pass it in request body like so: {"participant_id": "...not a very secret value which can be found when inspecting requests..."}

Что же, теперь нам надо найти корректное значение для идентификатора участника (participant_id). Смотрите секцию “Как найти participant_id” ниже, чтобы узнать как это сделать.

Когда мы получили наш participant_id, попробуем подставить его вместо строки “… not a very secret value which can be found when inspecting requests …”.

$ curl https://api.e-olymp.com/uoi/crown -X POST -d '{"participant_id": "00000000-0000-0000-000-00000000000"}'

В ответ мы получим сообщение:

C0ngr4tz! Y0u h4ve c0mpleted the t4sk! The crown 1s y0ur5!

Поздравляю! Вы выполнили задание, корона ваша!

Python способ

Многие из участников выбрали именно этот метод, потому что многие знакомы с языком программирования python и имеют настроенный интерпритатор на своем компьютере.

В интернете достаточно просто найти примеры того, как сделать POST запрос с помощью python. Код, который вы найдете, будет выглядеть примерно так:

import requests

resp = requests.post(url="https://api.e-olymp.com/uoi/crown")
print(resp.content)

Чтобы он работал, вам понадобится установить библиотеку requests. Функция requests.post выполняет HTTP запрос, используя метод POST, и возвращает ответ от сервера. В ответе от сервера нас интересует поле content, то есть содержание.

Если вы выполните программу, приведенную выше, вы получите такое сообщение.

b"Payload (request body) has to be a valid JSON object (https://uk.wikipedia.org/wiki/JSON). If you are using curl add `-d '{}'` options. During parsing an error occurred: EOF."

Теперь нам надо передать JSON объект в содержании запроса. В Python это можно сделать двумя способами, используя параметр data или параметр json.

import requests

resp = requests.post(url="https://api.e-olymp.com/uoi/crown", data="{}") 
# или
resp = requests.post(url="https://api.e-olymp.com/uoi/crown", json={})

print(resp.content)

Параметр data передает содержание запроса как строку, а параметр json позволяет передать содержание запроса как Python объект. Библиотека requests самостоятельно конвертирует Python объект в JSON объект.

Оба метода передадут к серверу идентиченые запросы и получат такой ответ.

b'Request must contain a valid participant_id. Make sure this participant is registered in UOI and has at least 500 points. You must find participant_id and pass it in request body like so: {"participant_id": "...not a very secret value which can be found when inspecting requests..."}'

Теперь нам надо найти корректное значение для идентификатора участника (participant_id). Смотрите секцию “Как найти participant_id” ниже, чтобы узнать как это сделать.

import requests

resp = requests.post(url="https://api.e-olymp.com/uoi/crown", json={"participant_id": "00000000-0000-0000-000-00000000000"})
print(resp.content)

В ответ мы получим сообщение:

C0ngr4tz! Y0u h4ve c0mpleted the t4sk! The crown 1s y0ur5!

Поздравляю! Вы выполнили задание, корона ваша!

Как найти participant_id?

Во время первого этапа олимпиады соревнования было размещено по ссылке https://uoi2021.org/, но после окончания этапа соревнование было перенесено на https://uoi2021-1.eolymp.io/. Поэтому сейчас participant_id можно найти именно по этой ссылке. Не забудьте ввойти в систему прежде чем искать значение.

На последнем шаге вы получаете сообщение:

Request must contain a valid participant_id. Make sure this participant is registered in UOI and has at least 500 points. You must find participant_id and pass it in request body like so: {"participant_id": "...not a very secret value which can be found when inspecting requests..."}

Чтобы завершить задание, вам необходимо найти ваш уникальный идентификатор участника (participant_id). В сообщении указано, что participant_id это “не очень секретное значение, которое можно найти просматривая запросы”. Можно догадаться, что participant_id должен быть доступен где-то на сайте олимпиады https://uoi2021-1.eolymp.io. Не забудьте ввойти в систему прежде чем искать значение.

Нам также нужно найти способ, как просматривать запросы. На самом деле в каждом браузере есть инструменты для просмотра HTTP запросов. Обычно эти инструменты можно активировать через F12 или пункт контектного меню “Inspect”. Выбрав этот пункт меню, вы увидите окно отладки сайта. В разных браузерах это окно будет выглядеть несколько иначе, но его элементы будут подобны.

Inspector

В этом окне доступны различные инструменты для отладки сайта. Вы можете просматривать HTML код страницы, можете посмотреть CSS стили и JavaScript. Но вкладка, которая нам интересна, называется Network (сеть). На этой вкладке мы можем просмотреть все HTTP запросы, которые делает страница.

Network

На картинке выше видно список запросов, которые сделал браузер. Если мы щелкнем на одном из них, мы можем увидеть параметры запроса, содержание запроса и ответа.

GraphQL

Например так выглядит запрос к серверу E-Olymp. Вы можете заметить, страница повторяет эти запросы время от времени, чтобы обновить данные о соревновании. Можно увидеть HTTP метод, адрес ресурса и, если спуститься вниз, можно увидеть данные, которые передаются на сервер (содержание запроса).

Request Body

Если перейти на вкладку “Preview” или “Response”, вы можете увидеть содержание ответа от сервера.

Response Body

Оригинальное решение предусматривало, что participant_id можно будет найти на странице “Отправки”. Эта страница доступна только во время первого этапа, но значения participant_id все еще можно найти в запросе graphql в ответе с сервера в секции, которая называется introspect.

Просматривая запросы на разных страницах, вы можете найти параметр называемый participant_id. Так на странице “Отправки” можно увидеть запрос ListSubmissions, в содержании этого запроса есть параметр participantId.

Response Body

Значение на снимке выше закрашено, но если вы повторите эти шаги, вы сможете увидеть собственное значение participantId.

Это значение также присутствует в запросе graphql, но там оно находится в ответе от сервера в секции, которая называется introspect.

Внимание! Такого рода задания не будут доступны во время следующих этапов олимпиады, поэтому не ищите задания во время олимпиады, а сфокусируйтесь на решении задач. Более того, действия связанные с поиском уязвимых мест во время этапа олимпиады могут быть расценены, как попытка вмешательства в работу системы, за что вы можете быть дисквалифицированы. Я размещу еще, как минимум, одно задание такого рода, но оно будет доступно только в дни, когда не проходят этапы олимпиады. Подпишитесь на нашу страницу в Facebook и телеграмм канал олимпиады, чтобы узнать когда будет доступно следующее задание.


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