Привет! Я Артемий Богданов, эксперт по практической безопасности Start X. Сегодня я расскажу, как небезопасная десериализация может привести к взлому сервиса.

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

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

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

Как происходит взлом

Чтобы продемонстрировать эту уязвимость, мы создали приложение‑симулятор сервиса доставки еды.

Покажу, как действует хакер в процессе поиска уязвимости:

  1. Злоумышленник вводит данные, которые просит приложение: адрес, имя, телефон.

  1. Далее он делает заказ.

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

  1. Чтобы понять, каким образом приложение сохранило данные, хакер переходит в консоль разработчика на вкладку Application и в cookie видит записи:

Какие особенности мы видим? Здесь закодированы специальные символы, в частности, символы кириллического алфавита, а перенос строки отмечается спецсимволом.

  1. Хакер обращает внимание на формат данных и видит, что они сериализованы в YAML. Если окажется, что на сервере используется небезопасная функция десериализации этих данных, это позволит злоумышленнику провести атаку на приложение.

  1. Теперь можно поискать данные о бэкенде. Злоумышленник смотрит заголовки ответа сервера: видит, что используется Python 3.8.17. Это значит, что перед нами приложение на Python, которое принимает данные от пользователя, сериализует их и кладет в cookie.

  1. Самая популярная библиотека, которая позволяет сериализовать и десериализовать данные в YAML в Python, — PyYAML. Если открыть документацию библиотеки PyYAML, то мы увидим, что при сериализации в YAML используются объекты классов.

    Существуют YAML.tag, которые соответствуют типам в Python. В нашем случае хакера больше всего интересует apply module, который можно использовать при составлении эксплойта:

С его помощью можно создать эксплойт, который позволит выполнить произвольный код:

  • эксплойт при десериализации выполнит команду операционной системы;

  • команда вызовет bash;

  • bash скажет эксплойту подключить еще один bash к удаленному серверу (к IP‑серверу хакера).

Поэтому хакер на своем сервере открывает порт, чтобы принять соединение от уязвимого сервера:

Таким образом, при десериализации YAML‑строки взломщик получит Back Connect Shell.

  1. Хакер подменяет значение user data на эксплойт. Для этого он переходит в браузер на вкладку Application и меняет значение cookie на пейлоад, который заранее составил, и который позволит выполнить зловредный код. После этого злоумышленник перезагружает страницу.

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

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

  1. Сервер захвачен. Уязвимость привела к тому, что хакер может выполнить произвольную команду на сервере: заставить его майнить, получить все пользовательские данные и так далее. Выполнив команду id, злоумышленник выясняет, что у него есть не только доступ к серверу, но и root‑права.

Мы показали, что захватить корпоративный сервер злоумышленнику удаётся за несколько минут.

Как предупредить уязвимости и атаки при сериализации и десериализации

На мой взгляд, главный совет для безопасности вашего сервера — отказаться от десериализации пользовательских данных совсем. Это полностью исключит вероятность таких атак.

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

  1. Сериализованные данные нужно шифровать и использовать механизмы подписи или хэширования. Чтобы не дать возможность злоумышленнику их каким‑то образом подменить.

  2. Вместо разрешения на десериализацию любого объекта используйте белые списки для указания доверенных классов.

  3. Используйте надежные и безопасные библиотеки.

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

  5. Разбирайте конкретные практические задачи с примерами кода и безопасной реализацией на языке программирования, который вы используете в работе.

Выводы

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

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

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

Основа безопасного программирования — это обучение и развитие навыков разработчиков. Понимание основ безопасности, осведомленность о распространенных уязвимостях и методиках их предотвращения — ключевые аспекты в написании безопасного кода. Инвестиции в обучение разработчиков и повышение их осведомленности по вопросам безопасности не только помогают минимизировать риски, но и способствуют созданию более качественного и надежного программного обеспечения.

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

Комментарии (3)


  1. shai_hulud
    30.11.2023 14:11
    +3

    Разработчик который использует YAML для передачи данных заслуживает быть взломанным.

    Более неоднозначного для реализации текстового формата еще надо поискать. Одинаковых реализаций нет, все имеют хоть какие-то отклонения от стандарта.

    Даже, JSONа, спека которого умещается на салфетке, корректных реализаций дай бог одна на ЯП. Одни игнорируют лишние/отсутствующие запятые, многие поддерживают комментарии итд.

    В таких расхождениях реализации стандартов и живут многие уязвимости (HTTP Request Smuggling, URL Parsing Confusion ...). Чем сложнее и запутанее спека, тем больше там спрятано баунти для взломщика.


  1. Shaman_RSHU
    30.11.2023 14:11
    +1

    Обычно хакеры под рукой держат что-то набодобие https://gchq.github.io/CyberChef/ и проблем с анализом никаких нет


  1. IvanG
    30.11.2023 14:11

    главный совет для безопасности вашего сервера — отказаться от десериализации пользовательских данных совсем

    Простите, а это как? Бинарных протоколов обмена с браузером не так много, из самого популярного только вебсокеты вспоминаю, но и там по-моему строки гоняются (grpc тоже сериализуется хоть и не в человекочитаемый).

    В целом конечно интересно, но а кроме питоновской библиотеки работы с ямлом что-то ещё так же легко даёт доступ к системе?

    Если нет, то имхо, совет отказываться от десериализации данных всех видов и на всех языках слишком спекулятивный.

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