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

Лабораторные работы
Если вы уже знакомы с базовыми концепциями уязвимостей десериализации и просто хотите попрактиковаться в их эксплуатации на реалистичных, намеренно уязвимых целях, вы можете получить доступ ко всем лабораторным работам по этой теме по ссылке ниже.
Что такое сериализация?
Сериализация — это процесс преобразования сложных структур данных, таких как объекты и их поля, в «плоский» формат, который можно отправлять и получать как последовательный поток байтов. Сериализация данных существенно упрощает:
Запись сложных данных в межпроцессную память, файл или базу данных
Отправку сложных данных, например по сети, между различными компонентами приложения или в вызове API
Критически важно, что при сериализации объекта также сохраняется его состояние. Иными словами, атрибуты объекта сохраняются вместе с их присвоенными значениями.
Сериализация и десериализация
Десериализация — это процесс восстановления этого потока байтов до полностью функциональной копии исходного объекта в точном состоянии на момент сериализации. Логика веб‑сайта затем может взаимодействовать с этим десериализованным объектом так же, как с любым другим объектом.

Многие языки программирования предоставляют нативную поддержку сериализации. Точный способ сериализации объектов зависит от языка. Некоторые языки сериализуют объекты в бинарные форматы, тогда как другие используют различные строковые форматы с разной степенью читаемости человеком. Обратите внимание, что все атрибуты исходного объекта сохраняются в сериализованном потоке данных, включая любые приватные поля. Чтобы предотвратить сериализацию поля, его необходимо явно отметить как «transient» в объявлении класса.
Имейте в виду, что при работе с разными языками программирования сериализация может называться marshalling (Ruby) или pickling (Python). Эти термины в данном контексте синонимы «сериализации».
Что такое небезопасная десериализация?
Небезопасная десериализация — это ситуация, когда веб‑сайт десериализует данные, контролируемые пользователем. Это потенциально позволяет злоумышленнику манипулировать сериализованными объектами, чтобы передать вредоносные данные в код приложения.
Возможно даже заменить сериализованный объект объектом совершенно другого класса. Что тревожно, объекты любого класса, доступного приложению, будут десериализованы и созданы их экземпляры независимо от того, какой класс ожидался. По этой причине небезопасная десериализация иногда называется как object injection. Объект неожиданного класса может вызвать исключение. Однако к этому моменту ущерб уже может быть нанесён. Многие атаки на основе десериализации выполняются ещё до завершения десериализации. Это означает, что сам процесс десериализации может инициировать атаку, даже если собственная функциональность веб‑сайта напрямую не взаимодействует со вредоносным объектом. По этой причине сайты, чья логика основана на строго типизированных языках, также могут быть уязвимы к этим техникам.
Как возникают уязвимости небезопасной десериализации?
Небезопасная десериализация обычно возникает из‑за общего непонимания того, насколько опасной может быть десериализация данных, контролируемых пользователем. В идеале пользовательский ввод вообще никогда не должен десериализоваться.
Однако иногда владельцы веб‑сайтов считают себя в безопасности, потому что внедряют некоторую дополнительную проверку десериализованных данных. Этот подход часто неэффективен, поскольку практически невозможно реализовать валидацию или санитизацию, учитывающие все варианты. Эти проверки также принципиально порочны, так как они полагаются на проверку данных после их десериализации, что во многих случаях будет слишком поздно, чтобы предотвратить атаку.
Уязвимости также могут возникать из‑за того, что десериализованные объекты часто считаются доверенными. Особенно при использовании языков с бинарным форматом сериализации разработчики могут думать, что пользователи не смогут эффективно прочитать или изменить данные. Однако, хотя это может требовать больших усилий, эксплуатировать бинарные сериализованные объекты столь же возможно, как и форматы на основе строк.
Атаки на основе десериализации также становятся возможны из‑за большого числа зависимостей в современных веб‑сайтах. Типичный сайт может использовать множество различных библиотек, каждая из которых имеет свои собственные зависимости. Это создаёт огромный набор классов и методов, которыми сложно безопасно управлять. Поскольку злоумышленник может создавать экземпляры любого из этих классов, трудно предсказать, какие методы могут быть вызваны на вредоносных данных. Это особенно верно, если злоумышленник способен создать длинную последовательность неожиданных вызовов методов, передавая данные в sink, полностью не связанный с исходным source. Поэтому практически невозможно предугадать поток вредоносных данных и залатать каждую потенциальную дыру.
Короче говоря, можно утверждать, что безопасно десериализовать недоверенный ввод невозможно.
Каков эффект небезопасной десериализации?
Воздействие небезопасной десериализации может быть очень серьёзным, поскольку она предоставляет точку входа к значительно увеличенной поверхности атаки. Она позволяет злоумышленнику повторно использовать существующий код приложения вредоносными способами, что часто приводит к RCE и множеству других уязвимостей.
Даже в случаях, когда удалённое выполнение кода невозможно, небезопасная десериализация может приводить к повышению привилегий, произвольному доступу к файлам и атакам типа DoS.
Как эксплуатировать уязвимости небезопасной десериализации
Как предотвратить уязвимости небезопасной десериализации
В целом десериализации пользовательского ввода следует избегать, если только это не абсолютно необходимо. Высокая критичность потенциальных эксплойтов и сложность защиты от них во многих случаях перевешивают выгоды.
Если вам всё же нужно десериализовать данные из недоверенных источников, внедрите надёжные меры, чтобы убедиться, что данные не были изменены. Например, можно реализовать цифровую подпись для проверки целостности данных. Однако помните, что любые проверки должны выполняться до начала процесса десериализации. В противном случае от них мало пользы.
По возможности следует вовсе избегать использования универсальных механизмов десериализации. Сериализованные данные из таких методов содержат все атрибуты исходного объекта, включая приватные поля, которые потенциально содержат конфиденциальную информацию. Вместо этого вы можете создать собственные, специфичные для класса методы сериализации, чтобы контролировать, какие поля раскрываются.
Наконец, помните, что уязвимость заключается именно в десериализации пользовательского ввода, а не в наличии gadget chains, которые затем обрабатывают данные. Не полагайтесь на попытки устранить цепочки гаджетов, обнаруженные при тестировании. Непрактично пытаться закрыть их все из‑за большого количества межбиблиотечных зависимостей, которые почти наверняка существуют на вашем сайте. В любой момент также следует учитывать публично документированные эксплойты повреждения памяти, что означает, что ваше приложение может быть уязвимым вне зависимости от этого.
Last updated