Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чим небезпечна десеріалізація даних від користувача?

unserialize() у PHP відтворює не лише дані, а й об'єкти довільних класів з довільними значеннями властивостей. При цьому автоматично викликаються магічні методи: __wakeup(), __unserialize(), а згодом __destruct().

Якщо нападник контролює рядок для unserialize(), він може створити об'єкти класів, які вже є в застосунку чи його залежностях, з потрібними йому властивостями. Ланцюжок викликів магічних методів («POP chain») призводить до запису файлів, SQL-запитів чи виконання коду. Готові ланцюжки для популярних фреймворків і бібліотек відомі й зібрані в інструментах на кшталт PHPGGC.

// Вразливо
$cart = unserialize($_COOKIE['cart']);

Захист:

  • Не десеріалізувати дані від користувача. Для обміну даними - json_decode(): він створює лише масиви й stdClass, без виклику коду класів.
  • Якщо unserialize() неминучий - allowed_classes:
$data = unserialize($payload, ['allowed_classes' => false]);           // лише скаляри й масиви
$data = unserialize($payload, ['allowed_classes' => [Money::class]]);  // білий список
  • Підписувати серіалізовані дані, що проходять через клієнта (HMAC), і перевіряти підпис до десеріалізації.

Де це трапляється в Laravel-застосунках:

  • Laravel шифрує cookie й підписує завдання черги, тож напряму від користувача серіалізовані дані туди не потрапляють. Але витік APP_KEY дозволяє підробити зашифровані дані - і раніше це давало виконання коду через десеріалізацію. Тому витік ключа - критичний інцидент.
  • Кеш і сесії в Redis/Memcached серіалізуються: доступ нападника до кешу - теж шлях до цієї атаки. Laravel дозволяє обмежити класи, які можна десеріалізувати з кешу (serializable_classes у config/cache.php).
  • Phar-архіви: у старих версіях PHP файлові функції з шляхом phar:// десеріалізували метадані архіву. PHP 8.0 це прибрав.

Аналогічні проблеми мають pickle у Python, Java-серіалізація, YAML.load у Ruby.

Докладніше в документації: OWASP: десеріалізація

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання