PHP, CSRF, proč nepoužívat při porovnání == / ===

Dobrý den,

otázka pro PHPáře, když ochraňuji POST/GET formuláře, generuji CSRF tokeny.

Má otázkní zní, proč se při následné kontrole nedoporučuje používat == nebo ===, ale ideálně hash_equals?

Fungují všechny tři varianty, ale pokud se nepletu, hash_equals je nejbezpečnější :)

Děkuji za objasnění.

PS: nejsem úplný odborník, proto vás žádám o "lidské" vysvětlení :)


tecka

Re:PHP, CSRF, proč nepoužívat při porovnání == / ===
« Odpověď #1 kdy: 07. 01. 2021, 08:15:48 »
Operátor == dělá implicitní konverzi typu a tím potažmo i hodnoty. Výraz 0 == "asd" je true.
Operátor === testuje typ i hodnotu.

https://www.php.net/manual/en/language.types.type-juggling.php
https://www.php.net/manual/en/types.comparisons.php

Naivní porovnávání stringů je postupné procházení a testování obsahu dokud se nenarazí na rozdíl (pak nejsou shodné) nebo na konec (jsou shodné). Při dostatečně přesném měření tak můžeš zjistit, jak daleko porovnávání došlo a kde je rozdíl, který potřebuješ upravit. hash_equals trvá vždycky stejně dlouho, pokud ho použiješ správně - viz dokumentace.

https://www.php.net/manual/en/function.hash-equals.php

AoK

  • ***
  • 248
    • Zobrazit profil
Re:PHP, CSRF, proč nepoužívat při porovnání == / ===
« Odpověď #2 kdy: 07. 01. 2021, 10:11:27 »
protože:
Kód: [Vybrat]
> var_dump(0 == "0e48a24b70a0b37653552b996af51739");
bool(true)

hash_equals pak brání i dalším útoků typu timing attack.

Re:PHP, CSRF, proč nepoužívat při porovnání == / ===
« Odpověď #3 kdy: 07. 01. 2021, 11:11:44 »
V PHP8 sa to uz menilo. Vid aj:
Kód: [Vybrat]
$ php -v
PHP 8.0.0 (cli) (built: Nov 27 2020 11:28:33) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.0, Copyright (c), by Zend Technologies
$ php -r 'var_dump(0 == "0e48a24b70a0b37653552b996af51739");'
bool(false)
$

AoK

  • ***
  • 248
    • Zobrazit profil
Re:PHP, CSRF, proč nepoužívat při porovnání == / ===
« Odpověď #4 kdy: 07. 01. 2021, 11:57:30 »
ano, sesumírovali to v https://www.php.net/manual/en/migration80.incompatible.php, konečně kontrolují jestli druhá strana je číslo. Kromě toho se opravil i dlouholetý problém s 0 == strcmp. Od php 8 krom toho hash_equals akceptuje jako vstup pouze string, tím zamezí problémům typu předání v postu/get pole.

To nic nemění na tom, že hash_equals tady je od 5.6 a je právě určen pro porovnávání tokenů a hashů, bude na tenhle use case testování, zamezuje řadě jiných útoků, nejen chybnému přetypování.

Time attack je třeba pěkně vysvětlen tady https://blog.ircmaxell.com/2014/11/its-all-about-time.html, to jen pro ilustraci, že i === nemusí být vždy bezpečné.



Re:PHP, CSRF, proč nepoužívat při porovnání == / ===
« Odpověď #5 kdy: 12. 01. 2021, 07:43:03 »
Všem moc děkuji za objasnění. Teď už chápu.