it-swarm-eu.dev

Jak bezpečně implementovat funkci „Pamatuj si mě“?

Za předpokladu, že již máte web, který implementuje všechny standardní přihlašovací údaje, jaký je správný a nejbezpečnější způsob, jak uživatelům umožnit automatické přihlášení po určitou dobu (řekněme 30 dní)? Toto časové období by mělo být přísně vymáháno; tj. nemyslím si, že by platným řešením bylo poskytnout cookie datum vypršení platnosti a doufat, že prohlížeč uživatele jej včas odstraní.

Podrobnosti o existujícím přihlašovacím systému:

  • Uživatel musí zadat uživatelské jméno a heslo
  • V databázi jsou uložena uživatelská jména a také silná_hash_funkce (heslo + uživatelské_pecifické_random_salt)
  • Přihlašovací formuláře se načítají a odesílají přes SSL, stejně jako všechny následující stránky

Existuje mnoho příkladů a mnoho zjevných bezpečnostních nedostatků. Jako cílový jazyk použijeme PHP), ale pojmy by se měly vztahovat na jakýkoli jazyk.

57
colithium

Moje odpověď je neúplná a v některých situacích má netriviální chybu - viz místo toho @ Scottova odpověď .


Moje odpověď má dvě části:

Za prvé, za předpokladu, že váš model hrozby se nebojí o vystavení souborů cookie na straně klienta , můžete vygenerovat a uložit neteř na straně serveru, hash to s uživatelské jméno a další informace (např. IP klienta, název počítače, časové razítko, podobné věci) a odešlete je do souboru cookie. Nonce by měl být uložen v databázi spolu s datem expirace a oba by se měli zkontrolovat, jakmile se cookie vrátí.
Měl by to být pouze „pamětní“ soubor cookie, NENÍ soubor cookie relace - tj. Když tento soubor cookie získáte bez relace, znovu zadejte nový soubor cookie pravidelné relace. Také si všimněte, že stejně jako soubor cookie relace by měl být doručován pouze prostřednictvím protokolu https a pomocí atributů secure a httpOnly, a samozřejmě mít soubor cookie správně nastaven atd.

Zadruhé, pro uživatele, kteří si pamatovali, byste měli (pravděpodobně v závislosti na citlivosti) vyvolat proces opětovné autentizace pro určité citlivé operace. To znamená, že někdy budou muset znovu vložit své heslo, ale jen zřídka a pouze pro citlivé operace. Tím se zabrání útokům, jako je CSRF a sdílení sdílené plochy.

31
AviD

Napsal jsem velkou délku o zabezpečená přihlášení a zaškrtávací políčka "pamatujte si mě" . Přijatá odpověď není špatná, ale tvrdil bych, že je to v jednom ohledu o něco složitější, než je třeba, a zanedbává oblast, kde je potřeba o něco složitější.

generovat a ukládat nonce na straně serveru, hash, který s uživatelským jménem a dalšími informacemi (např. ip klienta, computername, timestamp, podobné věci), a poslat to v cookie. Nonce by měl být uložen v databázi spolu s datem expirace a oba by se měli zkontrolovat, jakmile se cookie vrátí.

Implementace, která nevystavuje klientovi žádné informace, by tedy mohla vypadat jako ...

// Storage:
setcookie(
    'rememberme',
    hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce),
    time() + 8640000 // 100 days, for example
);
// Validation:
$valid = hash_equals(
    $_COOKIE['rememberme'],
    hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce)
);

Zde je zřejmé omezení, že pokud se změní vaše IP adresa (nebo jiné informace), váš cookie je zbytečný. Někteří to považují za dobrou věc, vidím to jako zbytečně nepřátelské vůči použitelnosti pro uživatele Tor.

Výše uvedenou nabídku můžete určitě interpretovat tak, že znamená něco jiného, ​​jako je například token JSON chudého člověka. Cookies HTTP jsou však omezeny na 4 kB na doménu. Prostor je prémiový.

Další problém: Kolik informací vytéká váš databázový dotaz o vaší aplikaci? (Ano, mluvím o vedlejších kanálech.)


Paragon Initiative je bezpečná strategie „Pamatuj si mě“

Úložný prostor:

  1. Generujte náhodný 9 bajtový řetězec z random_bytes() (PHP 7.0+ nebo přes random_compat ), base64 jej zakódujte do 12. Toto bude použito pro vyhledávání v databázi.
  2. Vytvořte další náhodný řetězec, pokud možno nejméně 18 bajtů, a znovu jej zakódujte base64 (až 24+). Toto bude skutečně použito pro autentizaci.
  3. Ukládejte $lookup A hash('sha256, $validator) do databáze; samozřejmě spojené s konkrétním uživatelským účtem.
  4. Uložte $lookup . $validator V HTTP cookie uživatele (např. rememberme).

Ověření (automatické přihlášení):

  1. Rozdělte cookie na $lookup A $validator.
  2. Proveďte vyhledávání databáze na základě $lookup; je to v pořádku, pokud je zde načasovaný vedlejší kanál.
  3. Zkontrolujte hash_equals($row['hashedValdator'], hash('sha256', $validator)).
  4. Pokud krok 3 vrátí TRUE, přiřaďte aktuální relaci k příslušnému uživatelskému účtu.

Analýza zabezpečení:

  • Jaké vedlejší kanály jsou zmírněny?
    Nejvýznamněji: zmírňuje dopad úniků časovacích informací na operaci porovnávání řetězců použitou při vyhledávání v databázi.

    Pokud jste implementovali naivní autentizaci náhodným tokenem, mohl by útočník poslat mnoho požadavků, dokud nenajde platný autentizační token pro uživatele. (Pravděpodobně by si nemohli vybrat, kterou oběť se předstírají.)

  • Co když útočník může uniknout z tabulky dlouhodobé autentizační databáze?
    Do databáze jsme uložili hash SHA256 $validator, Ale prostý text pro hash je uložen v cookie. Protože vstup je vysoká entropická hodnota, je nepravděpodobné, že by při hledání brutální síly přineslo nějaké výsledky. (To také snižuje potřebu např. Bcrypt.)

Tato strategie je implementována v Gatekeeper .

10

To je zajímavá otázka. Začnu tím, že řeknu, že si nejsem jistý, že se to dá udělat bez nějakého oslabení bezpečnosti aplikace, ale pak v závislosti na webu, který lze považovat za kompromis.

Takže jeden přístup by mohl být

Databáze stavu relace bude muset zaznamenat čas, kdy je nastaven token, a dobu, po kterou by měl být zapamatován, aby mohl porovnat prezentovaný token.

Když se uživatel přihlásí do aplikace, má zaškrtávací políčko, které mu umožňuje zůstat přihlášeni (ideálně s rozsahem časových období, které si uživatel může vybrat)

Když je nastaven token relace, použije se toto časové období jako doba platnosti souboru cookie. Při následných návštěvách bude cookie předložena aplikaci a server bude muset zkontrolovat, zda je stále platný (tj. Nebylo dosaženo doby vypršení platnosti funkce zapamatovat si mě). Pokud je token stále platný, je s uživatelem zacházeno jako s ověřeným, pokud ne, token je vymazán a uživatel je přesměrován na přihlašovací obrazovku.

Problémy s tímto přístupem. Sdílené prohlížeče by znamenaly, že je možný neoprávněný přístup.

Neautorizovaný přístup k webu bude moci získat také kdokoli, kdo může získat přístup k souboru cookie (buď prostřednictvím zranitelnosti na webu, problémem s prohlížečem nebo malwarem umístěným na počítači). Jedním z běžných návrhů, jak to zmírnit, je pokus o navázání cookie na zdrojovou IP adresu (samozřejmě zašifrovanou nebo uloženou na serveru), která je kontrolována, když uživatel prezentuje cookie, ale to způsobuje problémy s velkým podnikovým prostředím, kde může uživatel přijít z několika IP adres, a také mohou být citlivé na spoofing.

5
Rory McCune

Chcete-li soubor cookie smazat, nemusíte záviset na prohlížeči, web musí zkontrolovat datum vypršení platnosti souboru cookie.

Ve skutečnosti, aby to bylo bezpečné, řekl bych, že to je pravděpodobně to, co budete muset udělat, tak jako tak, protože byste chtěli nastavit datum vypršení platnosti jako součást hodnoty souboru cookie a zašifrovat jej spíše než spoléhat na vlastnost expirace prostého textu samotného souboru cookie.

A opravdu byste chtěli označit cookie jako zabezpečené a použít sekundární cookie po celou dobu jednotlivé relace, nebo chránit celou relaci (nejen proces přihlášení) pomocí SSL, abyste zabránili ukradení cookie z drátu a používá je neoprávněnou stranou.

4
Xander

Tento článek popisuje přístup, který brání proti krádeži souborů cookie a hádání ID relací:

  • Soubor cookie „pamatujte si mě“ se skládá z ID uživatele, tokenu (velké náhodné číslo) a sekvenčního tokenu (další velké náhodné číslo).
  • Když uživatel předloží soubor cookie, v databázi se vyhledají tyto tři informace.
    • Pokud je nalezen, obnoví se token sekvence, uloží se do databáze a odešle se uživateli
    • Pokud jsou nalezeny pouze uživatelské jméno a token, předpokládá se, že někdo jiný ukradl cookie, protože již byl použit sekvenční token. Systém pak může uživatele varovat a/nebo vymazat všechny uložené tokeny z tohoto uživatele z databáze.

Jako další bezpečnostní opatření se doporučuje, aby kritické akce, jako je změna přihlašovacích údajů nebo platba za věci, vyžadovaly heslo, pokud byl uživatel autentizován pouze pomocí souboru „zapamatovat si mě“.

Databázová tabulka, která obsahuje ID uživatele a tokeny, také obsahuje datum vypršení platnosti tokenů. Může také obsahovat uživatelského agenta a IP adresu, takže je musí útočník také replikovat. Všechny tokeny by se měly ukládat pouze jako hash, protože v zásadě fungují jako hesla a umožňují útočníkovi, který získal databázi, přihlásit se.

Vytvořil jsem kázková implementace pro PHP.

0
chiborg