PHP - CSRF - tüm sekmeleri çalışır nasıl yapılır?

2 Cevap php

Ben son günlerde CSRF-saldırıları önlemek için nasıl okudum. Ben, her pageload belirteci güncelleştirmek oturumda belirteci kaydetmek ve bir form göndererek zaman bir kontrol yapmak için gidiyorum.

Ama ne kullanıcı varsa, benim web sitesi ile 3 sekme açık diyelim, ve ben sadece oturumda son belirteci saklamak? Bu başka bir simge ile belirteci üzerine yazılır ve bazı post-eylem başarısız olacak.

Ben oturumda tüm belirteçleri saklamak gerekir, ya da bu çalışma almak için daha iyi bir çözüm var mı?

2 Cevap

Evet, saklanan-token yaklaşım ile herhangi bir noktada geri geldi sadece durumda üretilen tüm belirteçleri tutmak gerekiyor. Tek saklı-token sadece birden fazla tarayıcınızdan sekmeleri / windows için değil, aynı zamanda ileri / geri navigasyon için değil başarısız olur. Genellikle (yaş ve / veya yana verilen belirteçleri sayısına göre) eski belirteçleri dolan tarafından potansiyel depolama patlama yönetmek istiyorum.

Tamamen belirteç depolama önleyen bir başka yaklaşım, bir sunucu tarafı gizli kullanarak oluşturulan imzalı bir belirteç hazırlamaktır. Sonra belirteç geri almak ne zaman imzayı kontrol edebilir ve bu maçlar eğer bunu imzaladı biliyorsun. Örneğin:

// Only the server knows this string. Make it up randomly and keep it in deployment-specific
// settings, in an include file safely outside the webroot
//
$secret= 'qw9pDr$wEyq%^ynrUi2cNi3';

...

// Issue a signed token
//
$token= dechex(mt_rand());
$hash= hash_hmac('sha1', $token, $secret);
$signed= $token.'-'.$hash;

<input type="hidden" name="formkey" value="<?php echo htmlspecialchars($signed); ?>">

...

// Check a token was signed by us, on the way back in
//
$isok= FALSE;
$parts= explode('-', $_POST['formkey']);
if (count($parts)===2) {
    list($token, $hash)= $parts;
    if ($hash===hash_hmac('sha1', $token, $secret))
        $isok= TRUE;
}

Eşleşen bir imza ile bir simge olsun eğer bu ile, bunu oluşturulan biliyorsun. Bu başlı başına çok yardım değil, ama daha sonra, örneğin bir kullanıcı kimliği için, rastgele dışında belirteç başka ekstra şeyler koyabilirsiniz:

$token= dechex($user->id).'.'.dechex(mt_rand())

...

    if ($hash===hash_hmac('sha1', $token, $secret)) {
        $userid= hexdec(explode('.', $token)[0]);
        if ($userid===$user->id)
            $isok= TRUE

Şimdi her form gönderme oldukça fazla CSRF yendi formu, aldı, aynı kullanıcı tarafından yetkilendirilmiş olması gerekir.

Bir anlık istemci uzlaşma ya MiTM saldırı sonsuza kadar o kullanıcı için çalışmak olacak bir belirteç sızıntı ve şifre sıfırlar üzerinde değişiklikler olduğunu bir değeri olmadığını böylece bir belirteç koymak için iyi bir fikirdir başka bir şey, bir zaman aşımı süresi olan parola değiştirilirken mevcut belirteçleri geçersiz böylece.

Sadece geçerli oturumda hatta kullanıcı (kullanıcı parolasının karma örneğin bir karma) için kalıcı ve üçüncü bir şahıs tarafından tespit edilemez (kullanıcının IP hash kullanarak, örneğin kötü) bir belirteç kullanabilirsiniz .

Sonra muhtemelen üretilen belirteçleri ton saklamak zorunda değilsiniz ve oturum (muhtemelen yine tekrar giriş için kullanıcı gerektiren hangi) sona sürece istediği gibi kullanıcı sayıda sekme kullanabilirsiniz.