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

12afd3d8aeb1d99a2f045c006cd41acb.jpg

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

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

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

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

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

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

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

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

7fd3fded3fda56e7e37a2e7999319ba6.jpeg

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

10cd93ab2c9b853fa1ebb3c14dea5cb7.jpg

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

3a68bd286841970b1c59588a68fd5467.jpeg

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

f22828757ebfafcf437b8be6ff1ece25.jpeg

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

96a883f0ecc0d95b630406247e80bade.jpeg

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

2ed6a0465c4cdd889cbc1e8dad646022.png

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

e400fc564203eace905b27b98b2e7125.jpeg

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

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

38f364cf9881528d79f0c645a780118c.jpeg

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

17d817935adfe1f6b5e84af3c2fa4868.png

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

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

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

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

43b0454776458b4e3525d9caa0d5834c.png

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

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

ce19e7a7d48c7c1d34a8e845e92b254a.jpeg

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

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

de6e124cca1c99153fcda1f412f2b418.jpeg

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

4604dfeafccdf99144b86e60fc9580e1.jpeg

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

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

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

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

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

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

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

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

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

Выводы

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

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

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

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

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

© Habrahabr.ru