PHP Oturum Tespiti / Ele Geçirilmesi


146

PHP Oturum Tespiti ve korsanlığı ve bu sorunların nasıl önleneceği hakkında daha fazla bilgi edinmeye çalışıyorum . Chris Shiflett'in web sitesinde aşağıdaki iki makaleyi okuyorum:

Ancak, her şeyi doğru anladığımdan emin değilim.

Oturumu sabitlemeyi önlemeye yardımcı olmak için, session_regenerate_id(true);birini başarıyla oturum açtıktan sonra aramak yeterli mi? Bunu doğru anladığımı düşünüyorum.

Ayrıca, $_GEToturum kaçırmayı önlemek için url'lerde aktarılan jetonları kullanmaktan da bahsediyor . Bu tam olarak nasıl yapılır? Tahmin ediyorum ki birisi oturum açtığında, siz onun token'ını oluşturup bir oturum değişkeninde depoluyorsunuz, ardından her sayfada o oturum değişkenini,$_GET ?

Bu simgenin oturum başına veya her sayfa yüklemede yalnızca bir kez değiştirilmesi gerekir mi?

Ayrıca, URL'lerde bir değer iletmek zorunda kalmadan korsanlığı önlemenin iyi bir yolu var mı? Bu çok daha kolay olurdu.


Belki bu önerileri bulduğunuz sayfalara bağlantılar ekleyebilirsiniz.
Gumbo

Yanıtlar:


222

Tamam, iki ayrı ama ilişkili sorun var ve her biri farklı şekilde ele alınıyor.

Oturum Sabitleme

Bu, bir saldırganın bir kullanıcı için bir oturumun oturum tanımlayıcısını açıkça belirlediği yerdir. Tipik olarak PHP'de bu onlara beğeni URL'si verilerek yapılır http://www.example.com/index...?session_name=sessionid. Saldırgan url'yi istemciye verdiğinde, saldırı, oturum kaçırma saldırısıyla aynıdır.

Oturumu sabitlemenin birkaç yolu vardır (hepsini yapın):

  • Set session.use_trans_sid = 0sizin de php.inidosyaya. Bu, PHP'ye tanımlayıcıyı URL'ye dahil etmemesini ve tanımlayıcılar için URL'yi okumamasını söyleyecektir.

  • Set session.use_only_cookies = 1sizin de php.inidosyaya. Bu, PHP'ye oturum tanımlayıcıları olan URL'leri asla kullanmamasını söyleyecektir.

  • Oturumun durumu her değiştiğinde oturum kimliğini yeniden oluşturun. Bu, aşağıdakilerden herhangi biri anlamına gelir:

    • Kullanıcı doğrulama
    • Hassas bilgilerin oturumda saklanması
    • Seansla ilgili herhangi bir şeyi değiştirmek
    • vb...

Oturum çalma

Burası, bir saldırganın bir oturum tanımlayıcısını ele geçirdiği ve o kullanıcı gibi istekler gönderebildiği yerdir. Bu, saldırganın tanımlayıcıya sahip olduğu için, sunucu açısından geçerli kullanıcıdan ayırt edilemez olduğu anlamına gelir.

Oturum kaçırmayı doğrudan önleyemezsiniz. Bununla birlikte, kullanımı çok zor ve daha zor hale getirmek için adımlar atabilirsiniz.

  • Güçlü bir oturum karma tanımlayıcısı kullanın: session.hash_functioniçinde php.ini. PHP <5.3 session.hash_function = 1ise SHA1 için ayarlayın . PHP> = 5.3 ise, session.hash_function = sha256veya olarak ayarlayın session.hash_function = sha512.

  • Güçlü bir hash gönderin: session.hash_bits_per_characterin php.ini. Bunu olarak ayarlayın session.hash_bits_per_character = 5. Bu, kırılmasını daha da zorlaştırmasa da, saldırganın oturum tanımlayıcısını tahmin etmeye çalışması bir fark yaratır. Kimlik daha kısa olacaktır, ancak daha fazla karakter kullanır.

  • İle ek bir entropi ayarlayın session.entropy_fileve session.entropy_lengthsizin de php.inidosyaya. İlkini olarak session.entropy_file = /dev/urandomve ikincisini entropi dosyasından okunacak bayt sayısına ayarlayın, örneğin session.entropy_length = 256.

  • Varsayılan PHPSESSID'den oturumun adını değiştirin. Bu, aramadan session_name()önce ilk parametre olarak kendi tanımlayıcı adınızla çağrı yaparak gerçekleştirilir session_start.

  • Eğer gerçekten paranoyak iseniz, oturum adını da döndürebilirsiniz, ancak bunu değiştirirseniz (örneğin, saate bağlı hale getirirseniz) tüm oturumların otomatik olarak geçersiz kılınacağına dikkat edin. Ancak kullanım durumunuza bağlı olarak, bir seçenek olabilir ...

  • Oturum tanımlayıcınızı sık sık değiştirin. Bunu her istekte yapmazdım ( gerçekten o güvenlik seviyesine ihtiyacınız yoksa ), ancak rastgele bir aralıkta. Bunu sık sık değiştirmek istersiniz, çünkü bir saldırgan bir oturumu ele geçirirse, onu çok uzun süre kullanmasını istemezsiniz.

  • Kullanıcı aracısını$_SERVER['HTTP_USER_AGENT'] oturuma dahil edin . Temel olarak, oturum başladığında, bunu gibi bir yerde saklayın $_SESSION['user_agent']. Ardından, sonraki her istekte eşleşip eşleşmediğini kontrol edin. Bunun sahte olabileceğini unutmayın, bu yüzden% 100 güvenilir değildir, ancak olmamasından daha iyidir.

  • Dahil dan kullanıcının IP adresini$_SERVER['REMOTE_ADDR'] oturumunda. Temel olarak, oturum başladığında, bunu gibi bir yerde saklayın $_SESSION['remote_ip']. Bu, kullanıcıları için birden çok IP adresi kullanan bazı ISS'ler için sorunlu olabilir (eskiden AOL gibi). Ancak kullanırsanız çok daha güvenli olacaktır. Bir saldırganın IP adresini kandırmasının tek yolu, gerçek kullanıcı ile sizin aranızda bir noktada ağı tehlikeye atmaktır. Ve eğer ağı tehlikeye atarlarsa, bir korsanlıktan çok daha kötüsünü yapabilirler (MITM saldırıları vb.).

  • Oturuma ve tarayıcı tarafında sık sık artırıp karşılaştırdığınız bir belirteç ekleyin. Temel olarak, her istek $_SESSION['counter']++için sunucu tarafında yapın. Ayrıca aynı şeyi yapmak için tarayıcı tarafında JS'de bir şeyler yapın (yerel bir depolama kullanarak). Ardından, bir istek gönderdiğinizde, yalnızca bir belirteç alın ve nonce'nin sunucuda aynı olduğunu doğrulayın. Bunu yaparak, saldırganın tam sayacı olmayacağı için ele geçirilmiş bir oturumu tespit edebilmelisiniz veya eğer varsa, aynı sayıyı ileten ve birinin sahte olduğunu söyleyebilecek 2 sisteminiz olacaktır. Bu, tüm uygulamalarda işe yaramayacaktır, ancak sorunla mücadele etmenin bir yoludur.

İkisine bir not

Oturumu Sabitleme ile Ele Geçirme arasındaki fark, yalnızca oturum tanımlayıcının güvenliğinin nasıl ihlal edildiğiyle ilgilidir. Sabitlemede, tanımlayıcı saldırganın önceden bildiği bir değere ayarlanır. Ele geçirme işleminde ya tahmin edilir ya da kullanıcıdan çalınır. Aksi takdirde, tanımlayıcı tehlikeye atıldığında ikisinin etkileri aynıdır.

Oturum Kimliği Yenileme

session_regenerate_idEski oturumu kullanarak oturum tanımlayıcısını her yeniden oluşturduğunuzda silinmelidir. Bu, çekirdek oturum işleyicisinde şeffaf bir şekilde gerçekleşir. Ancak, kullanansession_set_save_handler() bazı özel oturum işleyicileri bunu yapmaz ve eski oturum tanımlayıcılarına saldırmaya açıktır. Özel bir oturum işleyicisi kullanıyorsanız, açtığınız tanımlayıcıyı takip ettiğinizden ve kaydettiğiniz tanımlayıcıyla aynı değilse, eskisi üzerindeki tanımlayıcıyı açıkça sildiğinizden (veya değiştirdiğinizden) emin olun.

Varsayılan oturum işleyiciyi kullanarak, sadece aramakta sorun yok session_regenerate_id(true). Bu sizin için eski oturum bilgilerini kaldıracaktır. Eski kimlik artık geçerli değildir ve saldırgan (veya bu konuda başka biri) kullanmaya çalışırsa yeni bir oturum açılmasına neden olur. Yine de özel oturum işleyicilerine dikkat edin ....

Bir Oturumu Yıkmak

Bir oturumu yok edecekseniz (örneğin oturumu kapattığınızda), tamamen yok ettiğinizden emin olun. Bu, çerezin ayarının kaldırılmasını içerir. Kullanarak session_destroy:

function destroySession() {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
    session_destroy();
}

4
Karakter başına 4 bit yerine 5 kullanılması "gücü" hiçbir şekilde değiştirmez (bu durumda "güç" ne anlama gelirse gelsin). Ancak genel olarak puanlarınız tavsiye edilebilir olsa da, bazı önemli ayrıntılardan yoksundurlar. Örneğin, eski oturum kimliğiyle ilişkilendirilen oturuma ne olur veya eski oturum kimliğine sahip bir oturum geçersiz olduktan sonra nasıl ele alınmalıdır.
Gumbo

2
@battal: Hayır, konu bu. session_regenerate_idhala eski kimlikle ilişkili olan oturumu geçersiz kılmaz; yalnızca delete_old_session parametresi true olarak ayarlanmışsa oturum yok edilir. Peki ya bu kimlik yenilemesini bir saldırgan başlattıysa?
Gumbo

6
Bir oturum değişkenini her değiştirdiğinizde oturum yenilenmesine katılmıyorum, yalnızca oturum açıldığında / oturumu kapatıldığında yapılmalıdır. Ayrıca kullanıcı aracısını kontrol etmek anlamsızdır ve REMOTE_ADDR'yi kontrol etmek sorunludur. Eklemek istediğim bir şey var session.entropy_file = /dev/urandom. PHP'nin dahili entropi üretiminin son derece zayıf olduğu kanıtlanmıştır ve / dev / random veya / dev / uranom tarafından sağlanan entropi havuzu, bir donanım rng'si olmadan bir web sunucusunda alabileceğiniz en iyi şeydir.
kale

4
Ayrıca session.cookie_httponlyve eklemelisiniz session.cookie_secure. İlki xss'i engellemeye yardımcı olur (ama mükemmel değildir). 2., OWASP A9'u durdurmanın en iyi yoludur ...
kale

4
Böyle harika bir cevabı anlamayın ama en önemli parçayı kaçırmayın: SSL / HTTPS kullanın. Sayaç artışı, birbiri ardına hızlı bir şekilde birden çok istekle ilgili bir sorun kaynağıdır, kullanıcı bir sayfayı iki kez yeniler veya bir gönderme düğmesine iki kez basar. IP adresi çözümü, günümüzde tüm mobil kullanıcılar ve sürekli değişen IP'ler için bir sorundur. IP'nin ilk setine bakabilirsiniz, ancak yine de sorun arıyor. En iyisi, oturum kimliğinin ilk etapta keşfedilmesini engellemek ve bu SSL / HTTPS kullanmaktır.
Sanne 13

37

Her iki oturum saldırısı da aynı amaca sahiptir: Başka bir kullanıcının meşru oturumuna erişim sağlamak. Ancak saldırı vektörleri farklıdır:

Her iki saldırıda da oturum kimliği, bu saldırıların odaklandığı hassas verilerdir. Dolayısıyla, hem okuma erişimi (Oturum Kaçırma) hem de yazma erişimi (Oturum Sabitleme) için korunması gereken oturum kimliğidir.

Hassas verileri HTTPS kullanarak korumanın genel kuralı bu durumda da geçerlidir. Ek olarak, aşağıdakileri yapmanız gerekir:

Oturum Sabitleme saldırılarını önlemek için şunlardan emin olun:

Oturum Saldırı saldırılarını önlemek için şunlardan emin olun:

Her iki oturum saldırısını da önlemek için şunlardan emin olun:

  • sadece başvurunuzun başlattığı oturumları kabul etmek. Bunu, müşteriye özel bilgilerle başlatma sırasında bir oturumun parmak izini alarak yapabilirsiniz. Sen kullanabilirsiniz User-Agent kimliğini ancak uzaktan IP adresini veya istekleri arasında değişecektir olabilecek diğer bilgileri kullanmayın.
  • session_regenerate_id(true)bir kimlik doğrulama girişiminden sonra ( trueyalnızca başarılı olduğunda) veya ayrıcalıkların değiştirilmesinden sonra oturum kimliğini değiştirmek ve eski oturumu yok etmek için. (Herhangi bir değişiklik saklamak için emin olun $_SESSIONkullanmadan session_write_close önce eski kimliğine bağlı oturumu korunmuş istiyorsanız kimliği yenileyici;. Yeni kimliği ile aksi yalnızca oturum bu değişikliklerden etkilenecektir)
  • uygun bir oturum sona erme uygulaması kullanmak için (bkz . 30 dakika sonra bir PHP oturumunu nasıl sona erdirebilirim? ).

Harika gönderi, özellikle son bölüm.
Mattis

6

Bahsettiğiniz jetonlar "tek seferlik" - bir kez kullanılan sayıdır. Mutlaka yalnızca bir kez kullanılmaları gerekmez, ancak ne kadar uzun süre kullanılırlarsa, nonce'nin yakalanma ve oturumu ele geçirmek için kullanılma olasılığı o kadar yüksek olur.

Nonceslerin bir başka dezavantajı, onları kullanan ve aynı form üzerinde birden çok paralel pencereye izin veren bir sistem kurmanın çok zor olmasıdır. örneğin, kullanıcı bir forumda iki pencere açar ve iki gönderi üzerinde çalışmaya başlar:

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

Birden fazla pencereyi izlemenin bir yolu yoksa, yalnızca bir kerelik (B / Q penceresi) kaydetmiş olursunuz. Kullanıcı daha sonra gönderisini A penceresinden gönderdiği ve nonce 'P' ile geçtiği zaman, bu sistem gönderiyi olarak reddedecektir P != Q.


Peki bunun oturum sabitlemeyle ne ilgisi var?
kale

2
Özellikle birçok AJAX talebini aynı anda kullanma alanında geçerli bir noktası var.
DanielG

2

Shiflett'in makalesini okumadım ama sanırım bir şeyi yanlış anladınız.

Varsayılan olarak PHP, istemci çerezleri kabul etmediğinde URL'deki oturum belirtecini iletir. Aksi takdirde, en yaygın durumda, oturum belirteci bir çerez olarak saklanır.

Bu, URL'ye bir oturum belirteci koyarsanız, PHP'nin onu tanıyacağı ve daha sonra kullanmaya çalışacağı anlamına gelir. Oturum sabitleme, bir kişi bir oturum oluşturduğunda ve ardından başka bir kullanıcıyı, oturum jetonunu içeren bir URL açarak aynı oturumu paylaşması için kandırdığında gerçekleşir. Kullanıcı bir şekilde kimlik doğrulaması yaparsa, kötü niyetli kullanıcı, farklı ayrıcalıklara sahip olabilecek kimliği doğrulanmış birinin oturum jetonunu bilir.

Shiflett'in açıkladığından emin olduğum gibi, yapılacak olağan şey, bir kullanıcının ayrıcalıkları her değiştiğinde farklı bir belirteci yeniden oluşturmaktır.


Buna eklemek için lütfen önceden açılmış oturumları yok ettiğinizden emin olun çünkü bunlar mevcut kullanıcı izinleriyle geçerli olmaya devam edecek.
corrodedmonkee

0

Evet, oturum açtıktan sonra oturum kimliğini bir kez yeniden oluşturarak oturumun sabitlenmesini önleyebilirsiniz. Bu şekilde, eğer saldırgan yeni kimliği doğrulanmış oturumun çerez değerini bilmeyecekse. Sorunu tamamen durduran başka bir yaklaşım session.use_only_cookies=True, çalışma zamanı yapılandırmanızda belirlenir. Saldırgan, başka bir etki alanı bağlamında bir tanımlama bilgisinin değerini ayarlayamaz. Oturum sabitleme, çerez değerini GET veya POST olarak göndermeye dayanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.