it-swarm-tr.com

"Beni Hatırla" Özelliği Nasıl Güvenli Bir Şekilde Uygulanır?

Tüm standart giriş malzemelerini uygulayan bir web siteniz olduğunu varsayarsak, kullanıcıların belirli bir süre için otomatik olarak giriş yapmasına izin vermenin doğru ve en güvenli yolu nedir (diyelim 30 gün)? Bu zaman dilimi kesinlikle uygulanmalıdır; Yani, geçerli bir çözümün bir çereze bir son kullanma tarihi vereceğini ve kullanıcının tarayıcısının zamanında silmesini umduğunu sanmıyorum.

Mevcut giriş sisteminin detayları:

  • Bir kullanıcı bir kullanıcı adı ve şifre girmelidir
  • Veritabanı, kullanıcı adlarının yanı sıra strong_hash_function (password + user_specific_random_salt) depolar
  • Giriş formları, sonraki tüm sayfalar gibi SSL üzerinden yüklenir ve gönderilir

Orada birçok örnek ve bariz güvenlik açıklarına sahip birçok örnek var. Hedef dil olarak PHP kullanalım, ancak kavramlar herhangi bir dile uygulanabilir olmalıdır).

57
colithium

Cevabım eksik ve önemsiz olmayan bir kusura sahip, bazı durumlarda - lütfen @ Scott'ın cevabı yerine bakın.


Cevabımın iki kısmı var:

İlk olarak, tehdit modelinizin istemci tarafı çerezlerinin gösterilmesinden endişe etmediğini varsayarsak, sunucu tarafında bir nonce oluşturabilir ve depolayabilirsiniz. kullanıcı adı ve diğer bilgiler (ör. istemci ip, bilgisayar adı, zaman damgası, benzer şeyler) ve bunu çerezde gönderin. Nonce, son kullanma tarihi ile birlikte veritabanında saklanmalı ve her ikisi de çerez geri geldiğinde kontrol edilmelidir.
Bu sadece bir "hatırlatma" çerezi olmalı, bir oturum çerezi DEĞİL - yani, bu çerezi bir oturum olmadan aldığınızda, yeni, düzenli bir oturum çerezi yeniden yayınlayın. Ayrıca, oturum çerezi gibi, bunun yalnızca https üzerinden ve secure ve httpOnly öznitelikleri kullanılarak dağıtılması ve elbette çerezin doğru bir şekilde belirtilmesi vb.

İkincisi, hatırlanan kullanıcılar için (muhtemelen hassasiyete bağlı olarak) belirli hassas işlemler için bir yeniden kimlik doğrulama işlemi başlatmalısınız. Yani, bazen parolalarını yine de tekrar girmeleri gerekir, ancak nadiren ve sadece hassas işlemler için. Bunun amacı CSRF ve paylaşılan masaüstüne maruz kalma gibi saldırıları önlemektir.

31
AviD

Güvenli girişler ve "beni hatırla" onay kutuları hakkında çok uzun yazdım. Kabul edilen cevap yanlış değil, ancak bir açıdan olması gerekenden biraz daha karmaşık olduğunu ve biraz daha karmaşıklığın gerekli olduğu bir alanı ihmal ettiğini iddia ediyorum.

sunucu tarafında bir nonce oluşturun ve saklayın, bunu kullanıcı adı ve diğer bilgilerle (örneğin, istemci ip, bilgisayar adı, zaman damgası, benzer şeyler) karma yapın ve bunu çereze gönderin. Nonce, son kullanma tarihi ile birlikte veritabanında saklanmalı ve her ikisi de çerez geri geldiğinde kontrol edilmelidir.

Yani istemciye herhangi bir bilgi göstermeyen bir uygulama ...

// 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)
);

Buradaki bariz sınırlama, IP adresiniz (veya diğer bilgiler) değişirse, çerezinizin işe yaramaz olmasıdır. Bazıları bunu iyi bir şey olarak görebilir, Tor kullanıcıları için gereksiz yere düşmanca görüyorum.

Yukarıdaki alıntıyı, fakir bir adamın JSON Web jetonu gibi farklı bir şey anlamına da kesinlikle yorumlayabilirsiniz. Ancak, HTTP çerezleri etki alanı başına 4 KiB ile sınırlıdır. Yer bir prim.

Başka bir sorun: Veritabanı sorgunuz uygulamanız hakkında ne kadar bilgi sızdırıyor? (Evet, yan kanallardan bahsediyorum.)


Paragon Girişimi'nin Güvenli "Beni Hatırla" Stratejisi

Depolama:

  1. random_bytes() (PHP 7.0+ veya random_compat ) aracılığıyla rastgele 9 bayt dizesi oluşturun, base64 12 olarak kodlar. Bu, veritabanı aramaları için kullanılır.
  2. Tercihen en az 18 bayt uzunluğunda başka bir rastgele dize oluşturun ve bir kez daha base64 onu kodlayın (24+). Bu aslında kimlik doğrulama için kullanılacaktır.
  3. Veritabanında $lookup Ve hash('sha256, $validator) depolayın; Elbette belirli bir kullanıcı hesabıyla ilişkili.
  4. $lookup . $validator Öğesini kullanıcının HTTP çerezinde saklayın (örneğin rememberme).

Doğrulama (Otomatik Giriş):

  1. Çerezi $lookup Ve $validator Olarak ayırın.
  2. $lookup 'A dayalı bir veritabanı araması yapın; Burada bir zamanlama yan kanalı varsa sorun değil.
  3. hash_equals($row['hashedValdator'], hash('sha256', $validator))'u kontrol edin.
  4. 3. adım TRUE değerini döndürürse, geçerli oturumu uygun kullanıcı hesabıyla ilişkilendirin.

Güvenlik analizi:

  • Hangi yan kanallar azaltılır?
    En önemlisi: zamanlama bilgisi sızıntılarının veritabanı aramasında kullanılan dize karşılaştırma işlemi üzerindeki etkisini azaltır.

    Saf bir rastgele belirteç kimlik doğrulaması uyguladıysanız, bir saldırgan bir kullanıcı için geçerli bir kimlik doğrulama belirteci bulana kadar çok sayıda istek gönderebilir. (Muhtemelen hangi kurbanı taklit ettiklerini seçemezler.)

  • Bir saldırgan uzun süreli kimlik doğrulama veritabanı tablosuna sızabilirse ne olur?
    Veritabanında $validator SHA256 karmasını sakladık, ancak karmanın düz metni çerezde saklandı. Girdi yüksek bir entropi değeri olduğundan, bunu araştıran kaba kuvvetin herhangi bir sonuç vermesi olası değildir. (Bu aynı zamanda örneğin bcrypt ihtiyacını da azaltır.)

Bu strateji Gatekeeper içinde uygulanır.

10

Bu ilginç bir soru. Uygulamanın güvenliğini biraz zayıflatmadan yapılabileceğinden emin olmadığımı söyleyerek başlayacağım, ancak daha sonra değiş tokuşa değer kabul edilebilecek siteye bağlı olarak.

Yani bir yaklaşım

Oturum durumu veritabanının, bir belirtecin ayarlandığı zamanı ve bunun belirtildiği süreyi kaydetmesi gerekir, böylece sunulan belirteci karşılaştırabilir.

Kullanıcı uygulamada oturum açtığında, oturum açmış olmalarını sağlayan bir onay kutusu vardır (ideal olarak kullanıcının seçmesi için belirli zaman aralıklarında)

Oturum belirteci ayarlandığında, çerez zaman aşımı olarak bu süre kullanılır. Sonraki ziyaretlerde çerez uygulamaya sunulacak ve sunucunun hala geçerli olup olmadığını kontrol etmesi gerekecektir (örneğin, beni hatırla işlevinin son kullanma süresine ulaşılmamıştır). Jeton hala geçerliyse, kullanıcı kimliği doğrulanmış olarak kabul edilir, aksi takdirde simge silinir ve kullanıcı giriş ekranına yeniden yönlendirilir.

Bu yaklaşımla ilgili sorunlar. Paylaşılan tarayıcılar, yetkisiz erişimin mümkün olduğu anlamına gelir.

Ayrıca, çereze erişebilen herkes (sitedeki bir güvenlik açığı, bir tarayıcı sorunu veya makineye yerleştirilen kötü amaçlı yazılımlar aracılığıyla) siteye yetkisiz erişim elde edebilir. Bunu hafifletmek için yaygın bir öneri, çerezi, kullanıcı çerezi sunduğunda kontrol edilen bir kaynak IP adresine (elbette şifrelenmiş veya depolanmış) bağlamaya çalışmaktır, ancak bu, kullanıcının gelebileceği büyük şirket ortamlarında sorunlara neden olur. IP adreslerinden ve ayrıca kimlik sahtekarlığına karşı hassas olabilir.

5
Rory McCune

Çerezleri silmek için tarayıcıya bağımlı olmanız gerekmez, sitenin çerez üzerindeki son kullanma tarihini kontrol etmesini sağlamanız gerekir.

Aslında, bunun güvenli olması için, muhtemelen yine de yapmanız gerekenin bu olduğunu söyleyebilirim, çünkü son kullanma tarihini çerez değerinin bir parçası olarak ayarlamak ve güvenmek yerine şifrelemek istersiniz. çerezin kendisinin düz metin son kullanma özelliği.

Ayrıca, çerezi güvenli olarak işaretlemek ve tek bir oturum süresince ikincil bir çerez kullanmak veya çerezin kablodan çalınmasını önlemek için tüm oturumu (sadece giriş işlemi değil) SSL ile korumak istersiniz. ve yetkisiz bir tarafça kullanılır.

4
Xander

Bu makale , çerez hırsızlığına ve oturum kimliklerinin tahmin edilmesine karşı savunan bir yaklaşımı açıklar:

  • "Beni hatırla" çerezi, kullanıcı kimliği, bir belirteç (büyük rastgele sayı) ve bir dizi belirtecinden (başka bir büyük rastgele sayı) oluşur.
  • Bir kullanıcı çerezi sunduğunda, veritabanı bu üç bilgi parçasını arar.
    • Bulunursa, sıra belirteci yeniden oluşturulur, veritabanında depolanır ve kullanıcıya gönderilir
    • Yalnızca kullanıcı adı ve jeton bulunursa, dizi jetonu zaten kullanıldığından başka birinin çerezi çaldığı varsayılır. Sistem daha sonra kullanıcıyı uyarabilir ve/veya bu kullanıcıdan saklanan tüm jetonları veritabanından silebilir.

Ek bir güvenlik önlemi olarak, kullanıcı yalnızca "beni hatırla" çereziyle doğrulanmışsa, giriş verilerini değiştirme veya bir şey için ödeme yapma gibi kritik işlemlerin şifreyi istemesi önerilir.

Kullanıcı kimliğini ve belirteçleri içeren veritabanı tablosu, belirteçlerin son kullanma tarihini de içerir. Ayrıca kullanıcı aracısını ve IP adresini de içerebilir, böylece bir saldırgan bunları da çoğaltmalıdır. Tüm jetonlar yalnızca karma olarak saklanmalıdır çünkü temelde parolalar gibi çalışır ve veritabanına ulaşan bir saldırganın oturum açmasını sağlar.

PHP için bir örnek uygulama oluşturdum.

0
chiborg