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

Як нестроге порівняння типів у PHP призводить до вразливостей?

Оператор == у PHP перед порівнянням приводить типи. Правила складні, і на них будувалися обходи автентифікації й перевірок.

«Магічні» хеші. Два числові рядки порівнюються як числа. Рядок виду "0e" + цифри - число в експоненційному записі, тобто нуль:

"0e123456" == "0e987654";   // true: обидва дорівнюють 0
md5('240610708') == md5('QNKCDZO');   // true - обидва хеші починаються з 0e і далі лише цифри

Перевірка if ($providedHash == $storedHash) пропускає інший рядок з таким самим «нульовим» хешем. Так обходили перевірку токенів скидання пароля й підписів.

Інші пастки (поведінка PHP 8):

"1" == "01";        // true  - числові рядки
"10" == "1e1";      // true
100 == "1e2";       // true
null == false;      // true
[] == false;        // true
"0" == false;       // true

PHP 8 виправив найгірше: "abc" == 0 тепер false (у PHP 7 було true), а in_array('abc', [0]) - false. Але порівняння числових рядків і null/false лишилися.

Де це небезпечно:

  • перевірка токенів, хешів, підписів, кодів підтвердження;
  • in_array / array_search без третього аргументу true - нестроге порівняння;
  • switch - теж використовує ==;
  • JSON-ввід: клієнт надсилає {"code": true} чи число замість рядка, і $code == $expected поводиться несподівано. Типи з JSON не гарантовані - їх треба валідувати.

Захист:

  • === і !== за замовчуванням - порівняння без приведення типів;
  • hash_equals($known, $user) для секретів - строге порівняння ще й у постійному часі (захист від атак за часом);
  • in_array($value, $list, true), array_search(..., true);
  • match замість switch - використовує строге порівняння;
  • declare(strict_types=1) - строгі типи аргументів функцій (не впливає на ==, але ловить передачу не того типу);
  • валідація типів вхідних даних ('code' => ['required', 'string', 'size:6']);
  • статичні аналізатори (PHPStan, Psalm) і правила code style попереджають про ==.

Докладніше в документації: PHP: оператори порівняння

Перевір себе

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

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