Php ve Mysql İle Güvenli Oturum Açmayı Sağlama (Session login hack için önlemler)

tarih26.12.2010 15:33 — PHP, Programlama, Webmaster,



 

Evvel emirde şunu belirtmek isterim ki bir şey ne kadar güvenli olursa olsun tamamen güvenli değildir. Ancak yeterince güvenli olabilir. Yani, aşılamayacak güvenlik önlemi yoktur. O yüzden yaptığınız işe bakıp “oh be ne iş çıkardım içeri sittin sene giremezler, edemezler” demeyin.


Bu makale (denemesi) giriş (login) script i yazarken nelere dikkat etmeniz gerektiğini anlatır, size hazır bir script sunmaz.

  • Son kullanıcılara hiç bir zaman güvenmeyin

Kullanıcı girişlerine (input) güvenmek yapılacak hataların başını çeker. Kullanıcıların doğru kutucuğa doğru formatta bilgi gireceğini hiç bir zaman düşünmeyin. Söz gelimi kullanıcı adı bölümünde kullanıcıdan girmesini beklediğiniz bilgi “hasanhuseyin” , “aliveli4950″ gibi bir şeydir. Ancak kullanıcının bu bölüme     ‘ or ” = ‘    girmeyeceğini (Bknz: SQL injection) kim garanti edebilir? Bu yüzden hardcoded olarak değerini atamadığınız ve bir sorguda kullanacağınız her değişkeni stripslashes(), addslashes() gibi fonksiyonlarla işleyiniz.

Kısaca Sql inject
Bir login scripti yazarken nihayi olarak yazacağınız kod ve sql kodu şunun gibi olacaktır:

 

 

$kullanici_adi = $_POST["kullanici"];
$parola = $_POST["parola"];
$sonuc = @mysql_query(”SELECT * FROM kullanicilar WHERE kullanici = ‘”.$kullanici_adi.”‘ AND parola = ‘”.$parola.”‘ LIMIT 1″);

if (@mysql_num_rows($sonuc) > 0)
echo “Sistemime hoş geldin”;
else
echo “Hatalı kullanıcı adı yada parola”;

 

Eğer bu kodu bu şekliyle yazarsanız. Çok ağlarsınız.  Yukarıda da bahsettiğim gibi eğer kullanıcı adı bölümüne sizin beklediğiniz gibi aliveli4950 yazılmaz da ‘ OR ” = ‘ yazılırsa veritabanına göndereceğiniz sorgu şu hale gelir:
SELECT * FROM kullanicilar WHERE kullanici = ‘‘ OR ” = ‘‘ AND parola = ‘kullanicinin girdiği herhangi birşey’ LIMIT 1

Bu sorgu veri tabanındaki ilk kayıda parola bölümünde ne yazarsa yazsın girer. Aynı model kullanıcı adının bilindiği parolanın bilinmediği durumlarda da işe yarar. Bu yüzden sql sorgusuna göndereceğiniz tüm kullanıcı kaynaklı verileri önce addslashes() fonksiyonu (Regular-Expressions ile de mümkün) ile işleyin.

Aynı injection modeli çerezlerde (cookie) ve get metoduyla aldığnız verilerde de geçerlidir es geçmeyin.
Örneğin şöyle bir bağlantınız var:
./kullanici-sil.php?id=17
Hiç kontrol yapmadan bu id değişkenini sql sorgusuna gönderirseniz. Gene ağlayabilirsiniz. Adresin sonuna kullanıcının şu satırcıkları eklediğini düşünelim
./kullanici-sil.php?id=17‘ OR 0 = 0 #

Sıfır her zaman sıfıra eşittir. Bir de bire. İki ise ikiye… Yani her zaman geçerli olacak ufacık bir kod yumağı sizi ne hale getirir düşünün. (Örnekte yetkilendirme kontrolü verilmemiştir, yapın tabi kullanıcı silerken bakın bakalım bunu isteyen kullanıcının bu işleme yetkisi var mı? Öyle her önüne gelen kullanıcı silse.. ohoooo. )
id gibi sadece rakamsal olmasını beklediğiniz değişkenleri is_integer() fonksiyoncuğuyla kontrol etmeniz yeterlidir.

  • Paylaşılan sunucularda sessionları veritabanında tutun.

Sessionlar güvenlik açısından sağlamdır. Ancak eğer paylaşılan bir sunucu kullanıyorsanız hangi session u hangi ip adresi için açtığınızı veritabanında tutun. Paylaşılan sunucularda php temp dizini aynı yerde olacağı için o sunucudaki herhangi bir site sizin siteniz için geçerli bir session oluşturabilir. Bunu engellemenin yegane yoluda hangi session u (session_id()) hangi ip adresine açtığınızı bir tabloda tutmaktır.

  • Parolaları SHA-1 ile şifreleyin

veritabanında parolaları tutmak için char(40) alan oluşturun. Oluşturduğunuz bu alana kayıt yaparken yada parola kontrolü yaparken sha1() fonksiyonunu kullanın.
Örneğin
$pasword = “123456″;
echo sha1($password); // 10470c3b4b1fed12c3baac014be15fac67c6e815 gibi bir çıktısı olacaktır.

  • Kullanıcılara ek bilgi vermeyin.

Bunu ürettiğiniz her hata mesajı için yapın. Örneğin bir giriş formunda “kullanıcı adınız yanlış” yada “parolanız sondaki 6 rakamı eksik”  gibi mesajlar vermeyin. Sadece “gerçersiz giriş denemesi” yada “geçersiz kullanıcı adı ve/veya parola” deyin.

  • Hataları yakalayın.

Php de bir çok fonksiyon hata yada uyarı mesajları gösterir. Bu uyarı yada hata mesajlarının ekranda gözükmesi geliştirme süresince sizin yardımcınız olsa da, son kullanıcıya hitap eden bir sistemde yalnızca saldırganlara hizmet eder. Örneğin:
Warning: file_exists() [function.file-exists]: open_basedir restriction in effect. File(/usr/local/lib/php/extensions/no-debug-non-zts-20060613/../../../../../../home/ioncube/ioncube_loader_lin_5.2.so) is not within the allowed path(s): (/home/rxsex:/usr/lib/php:/usr/local/lib/php:/tmp) in /home/rxsex/public_html/fonksiyon.php on line 2

Tarzı bir hata mesajı hangi dosyanızın hangi satırında hangi işlemleri yapmaya çalıştığınızla ilgili kafisiyle bilgi içeriyor. Bu hata mesajlarını fonksiyonların başlarına @ işareti getirerek susturabilirsiniz. Daha sonra da işlemin başarıyla gerçekleşip gerçekleşmediğini sonuç değişkenlerinden (her fonksiyon döndürür) yada mysql_affected_rows() gibi fonksiyonlarında yardımıyla öğrenip hata yada başarı mesajlarınızı kullanıcıya gösterin.

  • HTTP_REFERER i kontrol edin.

HTTP_REFERER istemini bulunduğunuz sayfa kullanıcının buraya hangi adresten geldiğini döndürür. Ancak aldatılması kolaydır. Sadece bir kaç çaylağı ve basit spam botlarını engeller. Çok güvenmeyin ama genede kullanın.

  • Gelen bilgileri kırpın.

Örneğin kullanıcı adı kutucuğunuz en fazla 32 karakterden oluşacaksa önce input kutusunun “maxlength” özelliğini kullanın sonra da substr() gibi fonksiyonlar yardımıyla kırpın. Örnek
<input type=”text” maxlength=”32″ name=”kullaniciadi”>
$kullaniciadi = substr($kullaniciadi,0,32);

  • $_POST kullanın $_REQUEST değil!

Sayfaya post metoduyla gönderdiğniz bilgileri $_POST ile alın $_REQUEST ile değil. $_REQUEST get metoduyla gönderilmiş formlarında bilgilerini alır.

  • Sorgu sonlarına LIMIT 1 ekleyin

Tek sonuç döndürmesini/işlemesini beklediğiniz her sorgunun sonuna LIMIT 1 özelliğini ekleyin.

  • IP adresini engelleyin!

Bir çok kez login denemesinde başarısız olan ip adresini geçici bir süreliğine engelleyin. (15 dk?) Yada gene geçici bir süreliğine resim kontrollü (captcha) giriş ekranına yönlendirin.

  • Log tutun

Kritik hataların ve giriş denemelerinin loglarını tutun. Örneğin
$result = @mysql_query($query) or die(”Öldü bu, olmadı bu sorgu”);
Yerine
$result = @mysql_query($query) or logla_baboli(”Hata dosyası: ABCD.php, satır: 56″, mysql_error(), $kullanici, time());
daha sonra da $result değişkenine göre sayfada hata veya başarı mesajı çıkartın.

  • Global değişkenlere dikkat!

Global değişkenleri register etme php.ini dosyasında aktif edildiyse (register_globals = On) sayfa global değişkenleri GET metoduyla atanabilir olur. Deneyin:
<?
if ($kacki_bu_sayi > 0 )
echo “yok artık ebenin….”;
?>
bunu yerel sunucumuzda test dizinin altına test.php olarak kaydettik ve şu adrese girdik diyelim
http://localhost/test/test.php
adres bu şekilde yazdığımızda hiç bir sorun yok..Sayfa beyaz ötesi ace kıvamında. Ancak şu şekilde yazarsak:
http://localhost/test/test.php?kacki_bu_sayi=2
o zaman sayfa ebemizin kulaklarını çınlatıyor.

Bunu engellemenin 2 güzide yolu mevcut.
1: php.ini dosyasında register_globals özelliğini kapatın (register_globals = off)
2: Eğer php.ini dosyasına erişiminiz yoksa her değişkenin işlemden önceki değerini atayın. Örnek:
$kullanici_giris_yaptimi = false;
if (giriş kontrolü kodu)
$kullanici_giris_yaptimi = true;

Son olarak SSL
Daha fazla güvenlik için giriş scriptlerinizde SSL kullanın.

Kaynak: http://furkan.rgbteam.com

 

 




Bir önceki konu başlığımıza göz atmak isterseniz tıklayınız : Php Alt Satıra Geçmesin – br ve \n gibi kodları engelleme – Satır atlamayı engelleme




    Yorumlar...
    (Toplam 1 yorum var.)


    Sayfa: 1

    Bu yorumu gerçekten şikayet etmek istiyor musunuz ???


    Bir sebep belirtmek isterseniz alttaki kutucuğa yazabilirsiniz...




    Pencereyi Kapat...
  1. 13.06.2014 18:56
    ufuk


    Misafir




    Güzel yazı olmuş teşekkürler.



Yorum Yazın