Новое Распределяем каналы MAX по категориям и территориям. Читать новость
Открытый канал ID 71731633265244

Школа этичного хакинга Timcore

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

В школе есть очное онлайн обучение по хакингу, которое проводится пока дистанционно.

Я надеюсь, что Вы найдете что-то полезное и интересное для себя в сфере образования. Собственно, эту цель я поставил для себя изначально.

Каналов в рубрике
101 481
Место этого канала
№ 26 639
Открыть рубрику →
Каналов в рубрике
4 027
Место этого канала
№ 1 481
Открыть рубрику →
Россия
Открыть в MAX

Публикации за период

По реакциям

Поиск и вся лента — после бесплатной регистрации. Свои даты — по подписке; владелец канала видит их бесплатно. Сортировка по реакциям — по подписке. Зарегистрироваться

Загрузка…

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

⚡ Как я стал админом одним POST-запросом: Register Admin Challenge в OWASP Juice Shop

Гоняю по вечерам OWASP Juice Shop - магазинчик, специально напичканный дырами для тренировки. Взялся за челлендж «Register Admin» - зарегистрировать юзера с правами администратора.

Точка входа 🔍
Регистрация идёт через авто-сгенерённый CRUD - POST /api/Users. Рука сама тянется подкинуть лишнее поле в JSON:
JSON

{ "email": "x@y.z", "password": "123", "role": "admin" }

Сервер честно кладёт всё тело запроса в модель. Вайтлиста нет. Клиент попросил роль - клиент получил роль. Классика mass assignment: доверять инпуту от юзера - как оставлять шелл с root на проде.

Бам - админка за один запрос. 💥

Бонус-раунд: выбери правильный фикс 🎯
К задачке есть задачка посложнее - найти строку с багом и выбрать, как её починить. Виноват хук resource.create.send.before(...): последнее место, где можно перетереть роль до сохранения, - пропущено.

Фиксы:

❌ Добавить 'role' в exclude - обманка. В finale это работает на сериализацию ответа, а не на запись. Баг живее всех живых.
✅ Форсить роль на сервере: context.instance.role = 'customer' - критичные поля выставляет только бэк. Правильный фикс.
❌ «Если роль пришла - оставь как есть» - это не фикс, это официальное сохранение уязвимости 🍬
❌ Удалить несвязанный код - remediation by deletion, мимо кассы.

Выводы 💻

Увидел авто-CRUD (finale, loopback) - шли всё, что модель не должна принимать: role, isAdmin, balance.
«Не возвращается в ответе» ≠ «нельзя записать».
Исправление одно: критичные поля задаёт только сервер. Период.

Админы, которые думают, что их код безопасен, - мой любимый вид дичи 🦌
Просмотры: 3
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

💻 LabProbe: пишу свой сканер на Rust и проверяю его на OWASP Juice Shop

«Сервер вернул 200 - значит, путь найден!» Звучит красиво. Пока не выясняется, что на любой выдуманный адрес приложение отдаёт одну и ту же HTML-страницу 😏

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

🔍 Что сделал

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

Дальше сравнивает не только размер страницы, но и:
▪ HTTP-статус;
▪ тип содержимого;
▪ заголовок перенаправления;
▪ тело ответа целиком.

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

⚙️ Что умеет текущая версия

🦀 Асинхронные запросы на Rust.
🇷🇺 Русскоязычные описания параметров и результаты.
🎛 Настройка параллельности и таймаута.
📦 Ограничение размера тела ответа.
🔀 Работа через явно заданный прокси - в том числе Burp Suite.
🛑 Отключённые автоматические редиректы.
🏠 Ограничение целей локальными адресами.
📊 Итоговая статистика без молчаливого проглатывания ошибок.

🧪 Что получилось на стенде

Запустил инструмент на Parrot Security OS против локального OWASP Juice Shop.

Результат проверки словаря:
- 6 запросов;
- 4 совпадения с калибровочными ответами;
- 2 отличающихся ответа;
- 0 ошибок запросов и задач.

Отдельно выделились /robots.txt и JSON-ответ /rest/products/search?q=apple. А выдуманные пути возвращали HTML по 9984 байта с кодом 200 - тот самый случай, когда один HTTP-статус ничего толком не говорит.

В карусели - четыре этапа: проверка и сборка проекта, справка, запуск на стенде и итоговая статистика. 📸

⚠️ Главное: «ответ отличается» не означает «найдена уязвимость». А «совпадает с заглушкой» не означает «пути не существует».

Пока это лабораторный инструмент для сбора наблюдений, а не волшебная кнопка «найти все дыры». Точное сравнение тоже не всесильно: динамические заглушки могут отличаться от запроса к запросу.

Мне в таких проектах нравится сам процесс: написать, запустить, увидеть слабое место в своей логике и исправить. Иногда главный баг на пентесте - не у приложения, а в предположениях сканера 😎

Тестирую только свой локальный стенд. Без чужих целей и приключений.
Просмотры: 7
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Прокачал сканер на Rust: теперь он не верит каждому 200 OK 🦀🔍

В прошлом посте я показал асинхронный сканер путей, который собрал за 30 минут и запустил на локальном OWASP Juice Shop. На этом решил не останавливаться: доработал инструмент - и заодно поймал ловушку, из-за которой сканер может радостно находить то, чего на сервере нет.

Что добавил:

- Внешний словарь: пути теперь читаются из файла, а не зашиты в исходник.
- Аргументы командной строки: можно задать адрес стенда, словарь, лимит одновременных запросов и прокси.
- Ограничение конкурентности через Semaphore в Tokio: количество запросов в работе теперь контролируется.
- Прокси для Burp Suite: запросы можно разбирать в HTTP history, а не судить о результате только по терминалу.

Но самое интересное началось после запуска.

Сканер показал 200 OK для /.env, /.git, /admin и других путей. На первый взгляд - праздник баг-хантера. Только шампанское оказалось преждевременным. 😏

Сервер отвечает - это ещё не находка
На нашем стенде приложение возвращало HTML-заглушку даже при обращении к несуществующему пути. Поэтому проверка «получил 200 - значит, нашёл файл» давала ложные срабатывания.

Добавил калибровку: перед проходом по словарю сканер запрашивает заведомо выдуманный путь и измеряет размер тела ответа. Затем отбрасывает ответы с такой же длиной. В вывод также добавил размер и Content-Type - теперь видно не только статус, но и характер ответа.

На моём стенде размер заглушки составил 9984 байта. После фильтрации из словаря на 13 путей в выводе остались:

[200] [28 байт] [text/plain] /robots.txt
[200] [26227 байт] [text/plain] /metrics
[200] [26411 байт] [application/json] /api/Products

Это результат конкретного локального прогона, а не список подтверждённых уязвимостей. Зато шума стало заметно меньше: вместо пачки одинаковых HTML-страниц - ответы, которые можно разбирать дальше.

Как запускаю

./target/release/juice_scanner \
-u http://127.0.0.1:3000 \
-w paths.txt \
-t 5 \
-p http://127.0.0.1:8080

Здесь -t 5 задаёт лимит пяти одновременно выполняющихся запросов, а -p направляет трафик через Burp Suite. Проверку провожу на своём локальном полигоне.

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

Главный апгрейд здесь даже не новые флаги. Я перестал считать зелёную строку в терминале доказательством находки.

Написать сканер, который радуется каждому 200 OK, несложно. Научить его сомневаться - вот где начинается интересная инженерная работа. 💻
Просмотры: 6
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Почему для тулинга в кибербезопасности я все чаще выбираю Rust: пишем асинхронный сканер за 30 минут 🦀💻

Python - отличный язык для быстрых скриптов, но когда дело доходит до высокой нагрузки, сотен параллельных сетевых запросов и работы без возни с виртуальными окружениями на целевой системе, на сцену выходит Rust.

Сегодня за полчаса собрал легковесный инструмент для поиска скрытых ручек и эндпоинтов, протестировав его на боевом стенде Parrot Security OS и полигоне OWASP Juice Shop.

Почему связка Rust + Tokio + Reqwest отрабатывает эффективнее:

1. Автономный бинарник. На выходе получаем один скомпилированный файл без внешних зависимостей. Его можно закинуть на любой сервер, и он сразу готов к работе.

2. Честная асинхронность. Рантайм Tokio обрабатывает сотни параллельных соединений в неблокирующем режиме без просадки по оперативной памяти.

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

Результат работы прототипа на локальном полигоне:

[+] НАЙДЕНО: http://127.0.0.1:3000/metrics (Код: 200 OK)
[+] НАЙДЕНО: http://127.0.0.1:3000/#score-board (Код: 200 OK)
[+] НАЙДЕНО: http://127.0.0.1:3000/assets/public (Код: 200 OK)
[+] НАЙДЕНО: http://127.0.0.1:3000/ftp (Код: 200 OK)

Утилита моментально зацепила открытый листинг директории /ftp (классическая точка входа для атак типа Path Traversal и поиска забытых бэкапов) и метрики Prometheus, через которые в реальных проектах нередко утекают внутренние конфигурации.

В следующей итерации планирую прикрутить поддержку внешних словарей из SecLists, ограничение пула соединений через семафоры и экспорт трафика в Burp Suite.
Просмотры: 7
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Очередной 0day без официального патча

Не успели админы во всем мире выпить валерьянки после миллионных сканов PHP2Shell, как команда PHP подкинула новый повод для бессонницы. В стеке обнаружена свежая RCE-дыра CVE-2026-115560, и официального бинарного патча под нее пока попросту нет. Разработчики решили не выпускать экстренный хотфикс, посчитав сценарий редким, но для баг-хантера любое «маловероятно» - это прямой вызов и повод расчехлить сканеры.

Архитектурный рассинхрон
Вектор атаки бьет в старый механизм отслеживания прогресса загрузки файлов (session upload progress), включенный в движке по умолчанию. Брешь активируется из-за конфликта грамматик десериализации сессий в памяти веб-сервера.

Что сразу бросилось в глаза при препарировании логики:

- Исходный параметр session.serialize_handler в php.ini задан как php_binary или php_serialize.

- Приложение на лету динамически меняет обработчик через вызов ini_set('session.serialize_handler', 'php') строго до исполнения session_start().

- Встроенный функционал upload progress пишет служебные данные сессии в одном формате сериализации, а парсер пытается прочитать их по правилам другого.

- Имя ключа в загрузке контролируется атакующим через POST-запрос, открывая прямой путь к serializer confusion.

Вектор атаки и механика эксплуатации
Для исполнения произвольного кода злоумышленнику достаточно отправить многочастный multipart/form-data запрос на эндпоинт, принимающий файлы. В скрытое поле с прогрессом загрузки внедряется сериализованный пейлоад с контролируемыми объектами.

Из-за разницы в кодировании ключей между php_serialize и легаси-хендлером php движок путает границы данных. Служебный байт превращается в префикс нового объекта, вызывая мгновенную десериализацию контролируемого класса прямо в памяти рабочего процесса. В легаси-кодовой базе фреймворков десятилетней давности такой кульбит встречается куда чаще, чем думают разработчики ядра.

Мнение специалиста о мнимом спокойствии
Как специалист по информационной безопасности, предостерегаю от опасной иллюзии: аргумент «это специфическая конфигурация, поэтому патчить не к спеху» регулярно хоронит корпоративные периметры.


В энтерпрайзе и самописных CMS разработчики сплошь и рядом переопределяют хендлеры сессий через ini_set(), чтобы подружить старые модули с новыми базами данных. Оставлять в ядре языка боевой вектор RCE без вендорского бинарника - это игра в русскую рулетку с автоматизированными ботнетами. Безопасность не терпит компромиссов: если уязвимость существует в коде, атакующие напишут под нее фаззер.

Митигация и чеклист для защиты серверов
Пока официальный апдейт отложен до следующего планового релиза, закрываем периметр вручную одной строкой конфига: ⚙🚨

- Открыть рабочий php.ini и жестко прописать директиву: session.upload_progress.enabled = 0.

- Перезапустить демоны веб-серверов и пулы php-fpm для применения изменений в памяти.

- Провести аудит исходников проекта командой grep -rn "session.serialize_handler" . на предмет runtime-смены хендлеров.

- Настроить правила WAF на блокировку аномально длинных значений ключа прогресса загрузки в multipart-запросах.
Просмотры: 8
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Когда математика против защиты: как целочисленное переполнение ломает логику в коде на Си

В прошлых разборах мы изучали ошибки адресации: выход за пределы массива на стеке, утечки через форматные строки и повторное использование памяти в куче. Сегодня протестируем вектор, где код внешне выглядит аккуратно, проверка размера буфера на месте, но программа все равно падает в Segmentation fault.

Речь идет об Integer Overflow (целочисленном переполнении).

Я собрал тестовый стенд в Parrot Security OS на ARM64 и разобрал, почему проверка if (size > MAX) может пропустить опасный объем данных.

1. В чем идея уязвимости?
Представьте обработчик сетевых пакетов: сервер принимает длину полезной нагрузки, прибавляет к ней фиксированный размер служебного заголовка (например, 8 байт) и проверяет, поместится ли итоговый блок в локальный буфер на 64 байта.

Логика программиста:
unsigned short total_size = length + 8;
if (total_size > 64) { reject(); }

Если передать length = 100, программа честно вычислит 108, увидит превышение лимита и отклонит пакет. Проверка работает штатно.

Но у типа unsigned short фиксированный размер - 16 бит.
Его диапазон строго ограничен значениями от 0 до 65535 (0xFFFF).

2. Эксперимент: переполняем 16-битный регистр
Что произойдет, если на вход передать число 65530?

1. Процессор выполняет сложение: 65530 + 8 = 65538.
2. Значение 65538 не помещается в 16 бит (0x10002).
3. Старший семнадцатый бит отбрасывается аппаратным сумматором, и в переменной total_size остается остаток от деления на 65536 - число 2!
4. Условие if (total_size > 64) проверяет двойку: 2 > 64 ложно.
5. Проверка безопасности успешно пройдена!

А дальше управление переходит к функции копирования:
memcpy(local_buffer, data, length);
где length по-прежнему равен исходным 65530 байтам.

3. Результат в терминале
Программа бодро рапортует:

- [*] Входящая длина: 65530 (размер short: 2 байт)
- [*] Вычисленный общий размер (length + 8): 2
- [+] Проверка пройдена! Выделяем место и копируем 65530 байт...
- Segmentation fault

Попытка записать 65 килобайт данных в буфер размером 64 байта мгновенно разрушает структуру памяти и приводит к аварийному завершению процесса. Математический оборот счетчика (Wrap-around) полностью обошел логический фильтр.

4. Вторая сторона медали: знаковые числа (Signedness Bug)
Еще опаснее ситуация, когда разработчик использует обычный знаковый int:
Если переменная длины принимает значение -1, проверка вида if (len > 64) сочтет его безопасным (-1 меньше 64).

Однако стандартная функция memcpy() ожидает параметр размера типа size_t (беззнаковый 64-битный тип). При передаче в функцию -1 неявно приводится к гигантскому числу 18 446 744 073 709 551 615 (0xFFFFFFFFFFFFFFFF), что приводит к попытке чтения несуществующей памяти и моментальному падению сервиса.

Как предотвратить такие уязвимости?
1. Проверять границы до выполнения операции:
Вместо сложения с последующим сравнением используйте вычитание из константы предела: if (length > MAX_BUFFER_SIZE - 8) { reject(); }. В таком случае переполнение физически невозможно.

2. Использовать встроенные макросы компилятора:
Современные версии GCC и Clang поддерживают встроенные функции с аппаратной проверкой флага переноса: __builtin_add_overflow(a, b, &res).

3. Статический анализ кода:
Линтеры и SAST-инструменты уверенно находят неявные приведения типов (signed в unsigned) и предупреждают о риске переполнения еще на этапе сборки проекта.
Просмотры: 9
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Призрак освобожденной памяти: как работает Use-After-Free и почему его боятся даже создатели браузеров

Мы уже посмотрели, как компилятор отбивает атаки на стек и как ошибки форматирования сливают токены из памяти. Теперь шагнем на территорию, где находят самые дорогие уязвимости в ядрах ОС, браузерах и демонах - в динамическую память (Heap / Кучу).

Сегодня в Parrot Security OS на ARM64 я разобрал уязвимость класса Use-After-Free (UAF) и получил доступ администратора без единой ошибки сегментации.

Делюсь пошаговым разбором того, как аллокатор памяти сам отдает контроль над чужими объектами.

1. В чем суть бага Use-After-Free?
Когда программа выделяет блок памяти через malloc(), а затем освобождает его через free(), программист обязан занулить указатель (ptr = NULL).

Если этого не сделать, указатель становится «висячим» (Dangling Pointer). Он продолжает указывать на адрес в куче, хотя система считает этот кусок свободным. Если программа позже снова обратится по этому указателю, она прочитает то, что окажется на этом месте.

2. Эксперимент: симулируем веб-сессию
Я написал сервис, где есть две сущности:

1. Сессия пользователя UserSession: логин (24 байта) и флаг роли is_admin (4 байта).

2. Заметка пользователя global_note: обычный текстовый буфер того же размера.

Смотрим на первый скриншот:

1. Создаем сессию: выделяется блок по адресу 0xaaaaaaac16b0, статус is_admin = 0.

2. Пользователь выходит: вызывается free(), но указатель не зануляется.

3. Создаем заметку: и аллокатор glibc выделяет под нее ровно тот же самый адрес 0xaaaaaaac16b0!

Почему адреса совпали?
В glibc работает механизм кэширования Tcache (Thread Local Cache). Чтобы не тратить время на системные вызовы, аллокатор складывает недавно освобожденные чанки одинакового размера в быстрый список и при следующем malloc мгновенно отдает их повторно!

3. Ловушки ядра: почему нельзя передать нули в argv
Казалось бы, достаточно записать в новую заметку 24 символа имени и байт \x01\x00\x00\x00, чтобы выставить флаг is_admin = 1.

Но тут включились правила Linux и POSIX (второй и третий скриншоты):

- Командная строка argv считает нулевой байт \x00 концом строки.

- Python при попытке передать бинарный ноль в аргумент выбросил системную ошибку ValueError: embedded null byte.

- А когда мы передали строку без нулей, memcpy скопировал наш байт \x01, но не затер старые служебные указатели аллокатора, выдав статус is_admin = 1213399041 вместо единицы!

4. Взлом через сырой поток stdin (четвертый и пятый скриншоты)
В реальных сетевых службах данные приходят не из аргументов запуска, а из сокета или стандартного ввода stdin.

Я переписал чтение заметки на fread() из потока ввода и передал пейлоад через пайп:
python3 -c 'import sys; sys.stdout.buffer.write(b"A"*24 + b"\x01\x00\x00\x00")' | ./uaf

Все 28 байт прошли без искажений:

- 24 буквы A заполнили поле логина;

- байты \x01\x00\x00\x00 аккуратно легли на место флага роли;

- программа обратилась к старому висячему указателю global_user->is_admin, увидела значение 1 и выдала флаг:
[+++] ДОСТУП РАЗРЕШЕН! Привет, Администратор! Флаг: FLAG{UAF_HEAP_MASTER_2026}.

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

Главные выводы по безопасности кучи
1. Правило чистого указателя: Вызвал free(ptr) - сразу пиши ptr = NULL;. Обращение к нулевому адресу приведет к мгновенному и безопасному завершению программы вместо скрытой эксплуатации.

2. Динамический анализ (ASan): Собирайте тестовые билды с флагом -fsanitize=address. AddressSanitizer блокирует использование освобожденной памяти и сразу выводит имя проблемной строки.

3. Тренд на Memory-Safe языки: Именно сложности контроля времени жизни объектов в Си/C++ подталкивают индустрию к переходу на Rust и Go, где компилятор проверяет владение памятью на этапе сборки.
Просмотры: 14
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Как одна опечатка в printf сливает секретные токены из памяти: разбираем Format String bug на ARM64

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

Сегодня я протестировал в Parrot Security OS еще один фундаментальный класс уязвимостей - Format String Vulnerability (уязвимость строки формата).

Делюсь экспериментом, где одной короткой строкой из терминала удалось вытащить закрытый токен прямо из оперативной памяти процесса.

1. В чем ошибка разработчика?
В языке Си классический вывод строки на экран должен выглядеть так:
printf("%s", user_input);

Здесь первый аргумент - это жестко заданный шаблон формата (%s), а второй - пользовательские данные.

Но разработчики нередко сокращают код до опасной конструкции:
printf(user_input);

На первый взгляд всё работает штатно: передал фразу «Hello Parrot» - программа напечатала «Hello Parrot».
Но если пользователь передаст специальные спецификаторы вроде %p (вывод указателя), функция printf посчитает их служебными командами и начнет доставать значения из регистров и стека процессора!

2. Эксперимент: сканируем память аргументами
Я написал микросервис, где внутри функции на стеке объявляется локальная переменная с секретным ключом:
char secret_key[] = "SUPER_SECRET_TOKEN_2026";

Запускаем бинарник с серией спецификаторов:
./format "%p.%p.%p.%p.%p.%p.%p.%p"

И программа послушно выводит сырые адреса из регистров:
0xfffff7ffdb60.(nil).(nil).0xffffffff.0xfbad2a84...0xffffffffeda0

Почему выводятся разные значения?
В архитектуре ARM64 первые семь аргументов передаются через физические регистры процессора x1–x7, а всё, что идет дальше, printf начинает читать напрямую со стека. Мы получили чистый примитив Information Disclosure (утечка памяти).

3. Точечный удар: декодируем токен из шестнадцатеричных байт
В синтаксисе printf можно обращаться к конкретным позициям стека через конструкцию вида %N$p.

Я запросил срез данных со стека (обязательно в одинарных кавычках, чтобы Bash не перехватил знак доллара):
./format '%8$p %9$p %10$p %11$p %12$p %13$p %14$p %15$p'

И в позициях 13, 14 и 15 терминал выдал три 64-битных блока данных:

- 0x45535f5245505553
- 0x4b4f545f54455243
- 0x363230325f4e45

Поскольку архитектура ARM64 хранит байты в формате Little-Endian (младший байт первым), переводим шестнадцатеричные пары в символы ASCII справа налево:

- 0x45... -> 53 (S), 55 (U), 50 (P), 45 (E), 52 (R), 5F (_), 53 (S), 45 (E) = SUPER_SE

- 0x4B... -> 43 (C), 52 (R), 45 (E), 54 (T), 5F (_), 54 (T), 4F (O), 4B (K) = CRET_TOK

- 0x36... -> 45 (E), 4E (N), 5F (_), 32 (2), 30 (0), 32 (2), 36 (6) = EN_2026

Складываем строки вместе - и получаем исходный токен:
SUPER_SECRET_TOKEN_2026!

Без отладчика, без декомпилятора и без прав администратора - секрет извлечен обычной строкой параметров.

4. Почему этот баг критичен для безопасности?
В реальных пентестах и CTF уязвимости формата строки используют не только для чтения:

1. Обход ASLR и канареек: Атакующий сливает реальный адрес стека и системных библиотек, нивелируя рандомизацию адресного пространства.

2. Запись в произвольную память (Arbitrary Write): Спецификатор %n позволяет не читать, а записывать количество напечатанных байт по любому переданному адресу памяти, что позволяет перехватывать поток управления программы без переполнения буфера.

5. Как защитить свой код?
Исправление элементарно и не требует переписывания архитектуры:

- Всегда передавайте строку формата жестко заданным литералом: printf("%s", user_input); или используйте fputs(user_input, stdout);.

- Включайте флаги строгого контроля компилятора: -Wformat -Wformat-security -Werror=format-security. При таких флагах gcc просто откажется компилировать небезопасный вызов.
Просмотры: 13
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

Почему программы на Си больше нельзя сломать «по методичкам из нулевых»: разбираем переполнение буфера на ARM64

Когда новички приходят в тему бинарных уязвимостей, классический Buffer Overflow (переполнение буфера) часто преподносят как простую формулу: залил в строку 100 символов, перезаписал адрес возврата и получил шелл.

Сегодня я решил развернуть лабораторный стенд в Parrot Security OS на архитектуре ARM64, написать уязвимый микросервис на Си и разобрать на реальных регистрах процессора, почему в современных системах всё устроено значительно глубже и надежнее.

Делюсь выводами и наглядными логами из терминала.

1. В чем корень проблемы?
В коде на Си классическая функция strcpy() не проверяет длину входящих данных. Если я выделяю под строку локальный массив размером 64 байта, а пользователь передает 80, лишние байты физически выходят за границы массива и начинают затирать соседние данные на стеке: сохраненный указатель фрейма и адрес возврата из функции.

2. Эксперимент №1: намеренно отключаем все щиты
Чтобы увидеть механику без помех, я скомпилировал файл с отключенными защитами компилятора (-fno-stack-protector -z execstack -no-pie).

Утилита checksec сразу подсветила мне беззащитный бинарник (первый скриншот):

- No canary found - нет контроля целостности стека;
- NX disabled - стек исполняемый;
- No PIE - адреса функций зафиксированы и не меняются.

Я рассчитал смещение и попытался направить поток выполнения на скрытую функцию по адресу 0x40070c.

И вот тут сработала аппаратная специфика (второй скриншот):
Процессор выбил ошибку SIGSEGV на странном адресе 0x0000ffff0040070c.

Почему так произошло?
В 64-битной архитектуре адрес функции содержит нулевые байты (\x00). Функция strcpy честно скопировала первые байты пейлоада, наткнулась на ноль и посчитала строку завершенной. В итоге младшая часть адреса перезаписалась, а старшая осталась от старого системного адреса libc (0xffff...). Программа упала в сегфолт, доказав: бинарные данные и строковые функции Си фундаментально несовместимы.

3. Эксперимент №2: компилируем по современным стандартам
Дальше я пересобрал тот же самый исходник так, как собираются пакеты в современных дистрибутивах Linux:
gcc -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -o target_hardened target.c

Смотрим в checksec (третий скриншот):

- Включена канарейка (Canary found);
- Стек закрыт для исполнения кода (NX enabled);
- Включена рандомизация адресов (PIE enabled);
- Активирован динамический контроль функций (FORTIFY: Yes).

Подаю ту же самую длинную строку - и программа мгновенно прерывает выполнение:
*** buffer overflow detected ***: terminated (Aborted)

Никакого неконтролируемого падения и никаких шансов добраться до управления регистрами.

4. Взгляд под капот: ассемблер AArch64 (четвертый скриншот)
Самое интересное видно при дизассемблировании скомпилированного файла (objdump -d):
Компилятор еще на этапе сборки вычислил, что размер буфера равен ровно 64 байтам.

Он автоматически вырезал небезопасный вызов strcpy и заменил его на библиотечную проверку __strcpy_chk:

- Строка mov x2, #0x40 - жестко заносит лимит буфера (64 в шестнадцатеричной системе) в служебный регистр;
- Строка bl <__strcpy_chk@plt> - вызывает проверку границ до того, как байты попадут в память.

Если длина ввода превышает 64 байта, программа не ждет перезаписи адресов, а немедленно завершает процесс через аварийный сигнал.

Резюме для практики
Этот разбор наглядно показывает, почему безопасность создается на стыке кода и компилятора:

1. Заменяйте небезопасные функции (strcpy, sprintf, gets) на строгие аналоги с контролем размера буфера (snprintf, strlcpy).
2. Никогда не отключайте базовые флаги защиты компилятора в продакшене.
3. Проверяйте результирующие бинарники через checksec и статические анализаторы кода.
Просмотры: 15
Перейти в пост Открыть в MAX Сообщить о неточности

Репост из «Хакер | Этичный хакинг с Михаилом Тарасовым»

🚨 ФЛЭШ-АКЦИЯ | 29–31 ОКТЯБРЯ ВКЛЮЧИТЕЛЬНО

Здравствуйте, дорогие друзья!

3 книги по OSINT, хакингу и форензике - за 2000 ₽ вместо 4500 ₽
Экономия 2500 рублей. Распродажа длится 3 дня. Потом - всё, цены вернутся.

💻 ЧТО ВХОДИТ В КОМПЛЕКТ:

📘 1. «Цифровой след: путеводитель начинающего кибердетектива»
Стань тем, кто видит невидимое. Google Dorks, Wayback Machine, поиск по никнеймам через Sherlock и Maigret, обратный поиск по фото, анализ EXIF, восстановление «удалённых» файлов, разбор заголовков email и IP-адресов - всё с нуля, по-человечески.
→ Плюс: OpSec, сервис на три буквы, Tor, работа через VM. Чтобы не спалиться самому, пока ищешь других.

Содержание: https://timcourse.ru/courses/elektronnaya-kniga-cifrovoj-sled-putevoditel-nachinayushego-kiberdetektiva/

📕 2. «Parrot Security OS 7.0: Практический гайд - Часть 1»
1030 страниц и 55+ инструментов с реальными примерами из боевых пентестов.
Nmap, Maltego, gobuster, wafw00f, theHarvester, masscan - и ещё 49 штук.
DNS-анализ, OSINT, сканирование портов, обход защит, автоматизационные скрипты - бери и запускай.
→ Это только 1 из 14 частей серии.

Содержание: https://timcourse.ru/courses/elektronnaya-kniga-parrot-security-os-7-0-prakticheskij-gajd-chast-1/

📗 3. «Логи не врут. Практическая форензика для параноиков»
162 страницы без воды о том, как Windows стучит на своего хозяина.
Реестр, LNK-файлы, Prefetch, ShimCache, дамп RAM через FTK Imager, Volatility, карвинг данных из неразмеченного пространства диска, вскрытие баз Telegram Desktop, анализ режима «Инкогнито» (спойлер: он не работает так, как ты думаешь).
→ Бонус: Anti-Forensics - как работают профи на другой стороне.

Содержание: https://timcourse.ru/courses/elektronnaya-kniga-logi-ne-vrut-prakticheskaya-forenzika-dlya-paranoikov/

🎯 КОМУ ЭТО НУЖНО:

- Начинающим ИБ-специалистам и пентестерам
- OSINT-аналитикам и кибердетективам
- Сисадминам, которые хотят понять, как их взламывают
- Всем, кто хочет понять, что ОС знает о тебе больше, чем ты думаешь

💰 ЦЕНА ПО АКЦИИ: 2000 ₽
Обычная цена: 4500 ₽

⏳ Акция действует: 29, 30, 31 октября включительно.
После 31 октября - цена возвращается. Без напоминаний и продлений.

Для приобретения, пишите в ЛС паблика: https://vk.ru/hacker_timcore
Просмотры: 17
Перейти в пост Открыть в MAX Сообщить о неточности
Вся лента — после бесплатной регистрации
ВКонтакте Телеграм Одноклассники
Избранное в datool.ru

Следите за каналом в личном кабинете

Зарегистрируйтесь в datool.ru, чтобы добавить канал «Школа этичного хакинга Timcore» в избранное и отслеживать его показатели.

Зарегистрироваться
Для владельцев каналов

Подтвердите свой канал

Войдите или зарегистрируйтесь в datool.ru, затем добавьте нашего бота в канал по инструкции в личном кабинете. После проверки владения замок исчезнет и вам станет доступно управление каналом.

Войти или зарегистрироваться

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти