OWASP Top 10: A8 Небезопасная десериализация
Этичный Хакер
Введение
Небезопасная сериализация исторически рассматривалась как очень сложная для понимания уязвимость, почти как черный ящик, но, хотя она содержит свои проблемы, как и любой другой тип проблем в OWASP top 10. сериализация - это метод, используемый для преобразования объекта в поток байтов, чтобы его можно было где-то сохранить илипередано в другую систему. Поскольку эти сериализованные объекты подвергаются десериализации, могут возникнуть опасные проблемы. Эта проблема часто упоминается как ”Сортировка“ и ”Отмена сортировки“ в PHP и как ”маринование“ и "удаление” в python.
Что такое сериализация?
Сначала нам нужно будет перейти к сериализации, это процесс, который происходит в приложениях, когда данные должны быть переданы и сохранены. Это может быть очень полезным методом, поскольку два приложения могут иметь совершенно разную внутреннюю структуру.

Что такое небезопасная десериализация и как она работает?
Хотя объекты могут быть сериализованы для их хранения или передачи, в какой-то момент их может потребоваться десериализовать снова. В этой логике десериализации могут присутствовать уязвимости. Самая большая проблема с этим алгоритмом заключается в том, что процесс десериализации не различает, поскольку он десериализует любой объект, к которому приложение может иметь доступ. Злоумышленник может изменить атрибуты объекта или даже полностью вставить новый. Процесс сериализации может сделать приложение уязвимым по нескольким причинам, в зависимости от логики приложения и объекта, который сериализуется. Мы рассмотрим несколько примеров, но, пожалуйста, знайте, что есть и другие способы использовать эту уязвимость.
Через параметры
В одном из примеров, допустим, наш объект содержит атрибут “isSuperUser: false”. Злоумышленник может просто десериализовать объект, чтобы изменить атрибут, прежде чем сериализовать его снова. Затем сервер примет этот новый объект и будет рассматривать пользователя как суперпользователя. Однако это лишь один из примеров того, как может произойти небезопасная десериализация.
мы должны знать, что злоумышленники могут с таким же успехом добавить параметр, который, как они подозревают, сервер использует в качестве свойства, например, если сервер использует isSuperUser в качестве атрибута сериализованного объекта, он все равно может принять его при десериализации.
Через логику приложения
В этом примере я хочу показать функциональность, предназначенную для обновления настроек профиля пользователя. В рамках этой функции существует вызов для обновления ссылок пользователя в социальных сетях. Обычно пользователь может указать только часть имени пользователя в URI (например, в https://twitter.com/theXSSrat обычно пользователь может редактировать только часть /theXSSrat), но как часть сериализованного объекта пользователь может найти полный URL-адрес.
После редактирования URL-адреса на собственных серверах атаки пользователи замечают, что поступает запрос, который означает, что слепой SSRF был вызван злоупотреблением бизнес-логикой. Этот полный URL-адрес никогда не должен быть в объекте в первую очередь, и злоумышленники могли злоупотреблять им.
Через волшебные события
Прежде всего, нам нужно начать с объяснения того, что такое магическое событие, потому что это может быть понятно не всем. Волшебное событие - это метод на языке программирования, который вызывается автоматически. Например, в PHP у нас есть следующий магический метод: __sleep(). Проблема с этими магическими методами заключается в том, что они могут быть уязвимы для атак, если они обрабатывают данные. Это может произойти, например, с помощью десериализованных объектов.
Посредством вставки объектов
Помимо примеров, которые мы видели ранее, которые в значительной степени зависят от вставки или адаптации данных, мы также можем иногда вставлять произвольные объекты. Это возможно, потому что в объектно-ориентированном программировании методы, к которым объект может получить доступ, делегируются его родительским классом. Это означает, например, что обычно пользовательский объект не имеет доступа к еще не выпущенным функциям, чтобы сделать пользователя администратором. Это находится в URI /makeAdmin.php . Злоумышленник может отправить сериализованный объект, принадлежащий классу makeAdmin, в не ожидающую конечную точку, чтобы изменить изображение своего профиля, которое также ожидает сериализованный объект. Проблема в том, что для десериализации коду все равно, какой объект ему передается. Он с радостью десериализует его, и хотя это может вызвать ошибку из-за неожиданных параметров, ущерб нанесен, и пользователь назначил себя администратором.

Типы небезопасной десериализации
Мы уже рассмотрели несколько примеров, но все они могут быть отнесены к одному из трех типов небезопасной десериализации.
- Атаки с асинхронной десериализацией
Это также известно как сохраненная небезопасная десериализация, поскольку для этого злоумышленнику требуется ввести вектор атаки, который будет сохранен, а затем десериализован. Это часто бывает подробным, поскольку в случае сбоя возвращает информацию об ошибке и желаемый результат, если этого не происходит, но также может случиться, что вектор атаки запускается позже, когда у самого злоумышленника нет доступа. Это было бы классифицировано как атаки со слепой десериализацией
- Атаки со слепой десериализацией
Атаки со слепой десериализацией происходят, когда злоумышленники отправляют вектор атаки в приложение, которое сохраняется, но злоумышленник не может запустить вектор атаки, например, из-за того, что он запускается из серверной системы. Эти типы уязвимостей трудно обнаружить и требуют от злоумышленника глубоких знаний о приложении, поскольку им необходимо знать, какой объект тестировать.
- Десериализация с отложенным выполнением
Это называется отложенным, потому что вектор атаки будет выполняться вторичной системой, созданной для очистки неиспользуемых объектов, таких как сборка мусора в java или file.close() в PHP.
Форматы десериализации
До этого момента мы много говорили о PHP, но это не единственный язык программирования, на котором можно найти небезопасную десериализацию. Существует много разных языков программирования, каждый из которых имеет свой уникальный подход к процессу серилизации. Как мы можем видеть на этой странице в Википедии, существует множество различных форматов сериализации, и мы рассмотрим некоторые из них на практике. При таком количестве форматов сериализации неудивительно, что большая часть уязвимостей еще не обнаружена.
https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats
Python pickle и marshal
Первый пример, который мы рассмотрим, - это то, как python обрабатывает сериализацию, и мы можем сделать вывод, что существует два способа, которыми python обрабатывает это. Один называется травлением, а другой маршлингом, который также является термином, который ruby использует для десериализации.
Прежде всего, нам нужно импортировать pickle, если мы, конечно, хотим его использовать.
import pickle
Это позволит нам импортировать pickle из python. После чего мы можем начать использовать модуль.
Затем мы можем добавить данные в переменную и передать их функции pickle вместе с файлом для сериализации объекта on.
data.append(“a”) pickle.dump(data, file)
Обратная операция так же проста
data = pickle.load(file)
Сортировка Ruby
Мы также можем увидеть функциональность ruby, импортировав модуль сортировки и повторив те же шаги.
data = Marshal.dump(“a”)
Как вы можете видеть, нам не нужно записывать эти данные в файл для сериализации объекта. Мы можем так же легко десериализовать его.
Java
deseriliased_data = Marshal.load(data) private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;
В Java доступно 3 метода, для этого нам сначала нужно его реализовать.
class s implements java.io.Serializable
Далее нам нужно вызвать метод writeobject для ObjectOutputStream.
FileOutputStream file = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(file);
Наконец-то мы можем сериализовать объект
// Method for serialization of object
out.writeObject(object);
Мы можем сделать почти то же самое, но наоборот. Нам просто нужно быть осторожными, мы используем другой метод readObject, тогда как сериализация будет user writeObject .
// Reading the object from a file FileInputStream file = new FileInputStream(filename); ObjectInputStream in = new ObjectInputStream(file); // Method for deserialization of object object1 = (Demo)in.readObject();
JSON.NET
До этого момента мы говорили только о языках программирования, но эти проблемы могут возникать и в самих форматах данных, таких как JSON, поскольку это также сериализованные данные. Отличный пример можно найти здесь:
https://medium.com/r3d-buck3t/insecure-deserialization-with-json-net-c70139af011a
Этот злоумышленник смог злоупотребить небезопасной десериализацией для выполнения кода на сервере.
Примеры небезопасной десериализации
Первый пример, который мы рассмотрим, - это CVE, который был найден в приложении под названием “Concrete5”. У этого приложения был файл журнала, который был проверен на существующий. Однако в этом файле журнала, похоже, есть сериализованный объект, в который могут быть введены объекты, позволяющие выполнять произвольное выполнение кода PHP.
Более подробную информацию можно найти по адресу https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-36766
Второй пример, который мы можем найти, довольно прост. Пользовательский объект был сериализован и содержит тип учетной записи. Изначально для этого параметра задано значение “user”, но его можно десериализовать и изменить на admin перед сериализацией и повторной отправкой на сервер.
a:4:{i:0;i:132;i:1;s:7:”user-1”;i:2;s4:”user”;i3;s32:”b6a8b3bea87fe0e05022f8f3c88bc960”;}
При изменении параметра, выделенного жирным шрифтом, на admin и повторной его сериализации злоумышленник может передать его на сервер и повысить свои привилегии.
a:4:{i:0;i:132;i:1;s:7:”user-1”;i:2;s4:”admin”;i3;s32:”b6a8b3bea87fe0e05022f8f3c88bc960”;}
Как обнаружить небезопасную десериализацию?
Обнаружение этой уязвимости будет зависеть от используемого языка программирования. Каждый язык имеет свой собственный способ обозначения сериализованных объектов, поэтому мы должны научиться распознавать их для каждого языка. Мы должны убедиться, что проверяем все данные, которые используются приложением, и когда мы идентифицируем объект, мы можем попытаться десериализовать его самостоятельно и посмотреть, сможем ли мы его использовать.
Как я могу предотвратить небезопасную десериализацию
Первый совет самый простой из всех, но его нелегко реализовать, следует избегать любой сериализации, и мы должны выбрать гораздо более простой формат данных, но это не всегда возможно. Когда организации уже используют много сериализации, сложно отказаться от нее, но рекомендуется также перейти на более простые форматы данных. Это такие форматы, как JSON и XML.
Однако, если нам придется использовать сериализацию, мы должны проверить все данные, контролируемые пользователем, и убедиться, что они содержат нормальные данные, которыми нельзя злоупотреблять. Например, пользователь никогда не сможет изменить тип своей учетной записи на admin. Мы также должны знать, что были подтверждены концепции о том, как обойти такого рода использование строгих ограничений на тип и параметры.
Одна из стратегий, которую мы также можем предпринять, - это сохранить наш код сериализации в изолированной среде или среде с низкими привилегиями, чтобы снизить любое возможное воздействие, которое может последовать за успешным взломом.
Как и в главе “недостаточный мониторинг и ведение журнала” в OWASP top 10, нам нужно соблюдать это и убедиться, что мы регистрируем любые исключения, возникающие во время десериализации, и исследуем их позже.
Это также помогает обеспечить безопасность API или других механизмов безопасности, проверяющих все входящие и исходящие данные на наличие правильных параметров и правильность объекта.
Инструменты для защиты от небезопасной десериализации.
Есть несколько доступных инструментов, которые помогут нам в борьбе с этим типом проблем. Некоторые из них будут более специфичны для языка, например Java Deserialization Scanner, который является расширением burp suite. Burp suite pro также имеет тенденцию указывать сериализованные объекты, чего для некоторых может быть достаточно.
Я лично также использовал ysoserial, который является отличным инструментом, помогающим генерировать доказательства концепций небезопасной десериализации.
Плагин FindBugs - это приложение, которое также поможет нам найти уязвимости.
Кроме того, существует Jinfinity, который представляет собой инструмент, предназначенный для заполнения памяти вашей цели, что вызывает DoS-атаку.
Serianalyzer - это специфичный для Java инструмент, который будет выполнять статический анализ кода.
Наконец, у нас есть возможность использовать скрипт Serializekiller, который будет сканировать набор портов по умолчанию, но вы можете настроить его для работы со всеми портами.