Мы решили не один CTF-турнир. За плечами остались KnightCTF, 0xL4ugh и DiceCTF. Найти по-настоящему интересные и сложные задачи все труднее, поэтому будем смотреть в оба глаза и следить за несколькими мероприятиями одновременно.
На этот раз — порешаем задачи сразу двух CTF-турниров: Space Heroes и ThCon 2024. Уже интересно, что подготовили безопасники из США и Франции? Тогда добро пожаловать!
Дисклеймер: материал не обучает хакингу и не призывает к противозаконным действиям. Все описанное ниже лишь демонстрирует, какие пробелы в безопасности встречаются в реальных веб-приложениях. И предупреждает, на что нужно обратить внимание при разработке программного обеспечения.
Space Heroes: Slowly Downward
Дано
Решение
По ссылке открывалась простая страница с текстом и скрытым списком, который я нашел в HTML-коде. Удаляю у тегов класс — появляются дополнительные ссылки. Нажимаю на одну из них — получаю подсказку.
По указанным путям расположены логин и пароль:
4dm1n
p4ssw0rd1sb0dy5n4tch3r5
Отлично, теперь перехожу на страницу ввода учетной записи и авторизуюсь. После отображается такая структура веб-приложения:
Из структуры понятно, что флаг находится по пути secret/flag.txt. Пробую обратиться к нему, но получаю исключение: не хватает прав доступа. Поэтому иду смотреть исходный код страницы и вижу интересный блок кода JavaScript:
if (fileName.includes('arbiter.txt; cat /secret/flag.txt') || fileName.includes('carts.txt; cat /secret/flag.txt') || fileName.includes('arbiter.txt; cat secret/flag.txt') || fileName.includes('carts.txt; cat secret/flag.txt') || fileName.includes('arbiter.txt;cat secret/flag.txt') || fileName.includes('carts.txt;cat secret/flag.txt')){
// Fetch secret flag using the session token
fetch('/text/secret/flag.txt', {
headers: {
'Authorization': `Bearer ${sessionToken}`,
'Secret': 'mynameisstanley'
}
})
То есть для доступа к флагу нужно добавить нескольких заголовков. Для этого необходимо в качестве filename передать одну из строк, указанных в первом условии. Пробую отправить такую строку:
carts.txt; cat /secret/flag.txt
Готово — флаг в кармане.
Space Heroes: GTFO Jabba’s Palace
Задание
Han Solo is frozen in carbonite! Jabba definitely won’t like you taking his favorite decoration, but you need to GTFO of Jabba’s Palace! Find the key phrase to get out of the main gate. Chewie is waiting outside!
Primary Link: http://74.207.229.213:999/
Backup: http://jabba.martiansonly.net Backup: http://srv3.martiansonly.net:5555 Backup: http://srv2.martiansonly.net:5555
Решение
Перехожу на http://74.207.229.213:999/, вижу Джаббу и форму ввода адреса назначения:
В исходном коде страницы ничего интересного, пробую в destination передать flag.txt и смотрю в Burp:
Вижу, что отдался cookie-токен jabba=myfavoritedecoration. Больше зацепиться не за что, передаю в destination myfavoritedecoration:
Отлично — теперь появилась новая форма по пути /destination, а в HTML закомментирована подсказка. Передам в форму password и посмотрю на ответ:
Снова в комментариях HTML есть подсказка. Смотрю в https://gtfobins.github.io/gtfobins/jq/#file-read, где описана работа утилиты jq для чтения файлов:
Вижу сообщение: разработчики буквально сказали, какую команду нужно использовать, чтобы прочитать команду. Ввожу ее, подставив вместо $FILE значение flag.txt, и получаю такой результат:
Похоже, я на правильном пути, но никаких ключей в ответе сервера нет. Рабочая консольная команда, переданная в форме, может говорить о наличии command-injection. Похоже, файл flag.txt действительно существует, — пробую передать дополнительные команды:
Отлично — command-injection действительно есть. Но если ввести команду (jq -Rr . «flag.txt»; cat ./flag.txt), окажется, что на стороне сервера работает фильтр, который ее блокирует.
Это не страшно, ведь есть и другие утилиты. Пробую ввести head и получаю флаг:
ThCon: Find me if you can
Задание
Dark backdoors controls all the satellite, but there’s one in particular that is key to their mischief : the one they use to communicate, located at 20.19.38.158
Here is a network trace of an exchange we have intercepted between two members of DarkBackdoor (Cecile and Ben), Find the password they use to log in on the satellite.
Note that this challenge requires you to use a VPN if you are on site!
This challenge will unlock other challenges and so on
Дано
Решение
Приложен дамп трафика. Открываю его в Wireshark и вижу UDP-пакеты:
Дальше все просто. Перехожу в раздел Анализ → Отслеживать → UDP Stream и вижу текст, в котором находится флаг:
Копирую флаг — и сдаю его. Готово!
ThCon: Let us Phone Home
Задание
Congratulation, now we need to follow their procedures and connect to the server at 20.19.38.158
Note that this challenge requires you to use a VPN if you are on site!
Решение
В решении предыдущего задания был текст, который содержит порт подключения. Оказывается, что флаг — это пароль. С помощью утилиты netcat пробую подключиться к 20.19.38.158:4242:
После авторизации сервер отдает новый флаг — сдаю его.
ThCon: SpaceNotes
Задание
We’ve stumbled upon a straightforward web application of Dark Backdoor that allows note storage without requiring passwords! Sounds too good to be true, doesn’t it? Think you can access the admin note? If you can get us this access we may be able to understand how they broke into our satelites and maybe regain control over these!
Дано
Решение
Запускаю задачу, перехожу по адресу http://chall.ctf.thcon.party:33064/ и вижу такую страницу:
На странице есть активная ссылка на toto. Если по ней перейти, будет сформирован такой запрос-ответ:
Видно, что логин преобразовывается в кодировку base64 и передается в параметре username. Далее решаю проверить приложенный файл и открываю его. Из кода PHP понятно несколько вещей.
1. Логин забирается из параметра username, значение присваивается переменной encodedUsername:
$encodedUsername = str_replace("=", "", $_GET["username"]);
2. Значение admin в base64 будет YWRtaW4=. Если передать это значение, то знак равно удалится. В этом случае выполнится условие, которое обнулит значение переменной decodedUsername:
if ($encodedUsername === "YWRtaW4") {
$decodedUsername = "";
3. Если передать любое другое значение, то оно декодируется:
$decodedUsername = base64_decode($encodedUsername);
4. Далее в скрипте идет проверка с помощью регулярного выражения. Если декодированное значение содержит любые символы (кроме a-z, A-Z, 0-9), то decodedUsername обнулится:
if (!preg_match('/^[a-zA-Z0-9_]+$/', $decodedUsername)) {
$decodedUsername = "";
5. Из кода также видно, что нельзя передать пустой параметр username:
<?php if ($decodedUsername === ""): ?>
<h1>Error</h1>
<p class="error">Invalid username</p>
6. Флаг можно получить только при условии, декодированное значение — admin:
<?php elseif ($decodedUsername === "admin"): ?>
<h1>🟢 Welcome admin! 🟢</h1>
<p><?php echo $flagMessage; ?></p>
Итак, в параметр username нужно как-то передать скорректированное значение YWRtaW4= или YWRtaW4, чтобы оно не попало под фильтр. Из документации PHP известно, что в качестве параметра можно использовать список, а функция preg_match() обработает только первое переданное значение.
Передаю значение с апострофом — и получаю в ответ флаг:
В целом, Space Heroes и ThCon — интересные турниры. Они хорошо подходят как начинающим, так и продолжающим специалистам. В арсенале организаторов есть много категорий интересных задач с разным уровнем сложности.