Php Güvenlik Açıklarını Kapatmak

 bcakir
 28 Aralık 2011
 Php

Merhaba arkadaşlar, bu yazımda çoğu Php programcısının çok fazla önem göstermediği sıkça yapılan güvenlik açıklarını ve bu açıkların nasıl giderileceği konusunu anlatacağım. Genel olarak amaç yazılımı çalıştırabilmek ya da hızlı çalıştırabilmek olunca çoğu kişi güvenliği önemsemiyor ama bu yaptıkları hatanın bedelini, bütün emeklerinin heba olmasıyla ödemeleri pek muhtemel. Bundan dolayı yazdığımız betiklerin hızlı çalışması kadar güvenliğinin de üst düzey olması çok önemli. Yazımıza, güvenlik açıklarını teker teker inceleyerek ve çözümlerini ele alarak başlayalım.

Form Elemanlarından Veri Alırken Karşılaşılan Problemler: Burada iki türkü sorunla karşılaşılır. Birincisi Html etiketlerinin temizlenmemesinden (XSS “Cross Site Scripting”) kaynaklı olan problemlerdir. Böyle bir durumda, kullanıcıların çerezlerinde (cookie) saklı olan sisteme giriş bilgilerinin çalınması pek muhtemel. Diğeri ise veritabanına gönderilen bilgilerin temizlenmemesinden (SQL Injection) kaynaklanan problemlerdir. Bu durumun sonucunda ise veritabanınızın silinmesinden, izinsiz girişlerin olmasına kadar bir çok sorunla karşılaşırsınız. Şimdi de bu problemlerin nasıl çözüleceğini anlatayım.

<?php
//formdan girilen <script>alert('hecklendin');</script>
$formdan_gelen = "<script>alert('hacklendin');</script>";

//Html etiketlerini temizler
$formdan_gelen = strip_tags($formdan_gelen);
//Html etiketlerini zararsız hale getirir
$formdan_gelen = htmlentities($formdan_gelen);
//Html etiketlerini zararsız hale getirir
$formdan_gelen = htmlspecialchars($formdan_gelen);
?>

Yukarıda Html etiketlerinin zararsız hale getirme işlemini gösterdim. Şimdi de veritabanına yapılan saldırılardan ve izinsiz girişleri engelleme yöntemlerini açıklayayım.

<?php
//formdan girilen 1 OR '1=1'
$formdan_gelen = "1 OR '1=1'";

//Üsten kesme işaretini (') geçersiz yapar
$formdan_gelen = addslashes($formdan_gelen);
//Üsten kesme işaretini (') geçersiz yapar
//MySQL bağlantısı açık olmalı yoksa hata verir
$formdan_gelen = mysql_real_escape_string($formdan_gelen);
?>

Vertabanınında bulunan verilerin çalmasının, silmesinin ya da izinsiz girişlerin önüne geçmek için Html etiketlerini temizledikten sonra yukarıda bulunan kesme işaretini geçersiz yapmayı uygulamanız yeterli. Fakat mysql_real_escape_string kullanacaksanız, bu koddan önce MySQL bağlantınızı açmayı unutmayın.

Dosya Yükleme İle İlgili Problemler: Yüklen dosyalar diğer bir önemli güvenlik sorunudur. Bundan dolayı yüklediğiniz dosyaların türüne dikkat etmeyi sakın unutmayın. Şimdi bu sorunun çözümünü yapalım.

<?php
//izin verilen dosya türleri
$izinli_dosyalar = array(
'image/jpeg' => '.jpg',
'image/pjpeg' => '.jpg',
'image/png' => '.png',
'image/x-png' => '.png',
'image/gif' => '.gif'
);

//yüklenen dosyanın türü
$tur = $_FILES['file']['type'];

//dosya türü kontrolü
if(!array_key_exists($tur, $izinli_dosyalar)){
    echo "Bu türde dosya yükleyemezsiniz.";
}
?>

Dosya Import Ederken Karşılaşılan Problemler: Parametreden sayfa include ederken (index.php?sayfa=iletisim.php), allow_url_fopen ayarı açık olduğunda uzak siteden zararlı betikleri sisteminizde çalıştırabilirler (tam yol bağlantı adresi ya da ip adresi göstererek). Bunu çözmek için include yerine  file_get_contents() kullanabilir ya da uzak site olarak verilebilecek parametreleri temizleyebilirsiniz. Şimdi parametre temizleme ile ilgili çözümü yapalım.

<?php
//parametreden gelen sayfa bilgisini alma
$sayfa = addslashes(strip_tags($_GET['sayfa']));
//ilk önce temizleme işlemi
$sayfa = preg_replace('/\W/si', '', $sayfa);
//sonra include etme işlemi
include('./'.$sayfa.'.php');
?>

Bağlantıdaki Parametre İle İlgili Problemler: Form elemanlarından veri alırken karşılaşılan problemlerin aynısı bu konu için de geçerlidir. Bundan dolayı o sorunları burada yapacağımız örneklere de uygulayın. Ben diğer önemli bir açıktan daha bahsedeceğim. Sayfamızın bilgisini başka bir sayfaya aktarırken kullandığımız parametre değerlerine, müdahale etmek çok kolay. Bu sorunu en çok özel mesaj kutusunda yaşarız. Eğer şifreleme yapmazsak herkesin mesajlarına erişmemiz mümkün. Bundan dolayı, bu parametre değerlerini şifrelemeniz kullanıcılarınızın ve bilgilerinizin güvenliği açısından çok önemlidir.

<?php
//parametremizin sonuna 10 karakterli sabit yapma
$sabit = Sha1(rand(0,1000000));
$sabit = substr($sabit, Rand(0,30), 10); 

//sayfa id değeri ile birlikte sabiti de veritabanına kaydedin
$query = "INSERT INTO mesaj (id, sabit, mesaj) VALUES ('$id', '$sabit', '$mesaj')";
$ekle = mysql_query($query);

//sabit değer kullanılarak oluşturulan mesajın bağlantısı
//index.php?sayfa=mesaj&id=23&sabit=dss3lkj87a
//bu parametreden değerleri alma
$sayfa = mysql_real_escape_string(strip_tags($_GET['sayfa']));
$id = mysql_real_escape_string(strip_tags($_GET['id']));
$sabit = mysql_real_escape_string(strip_tags($_GET['sabit']));
//veritabanından doğruysa mesajı getirme
$al = mysql_query("SELECT mesaj FROM mesaj Where id='$id' AND sabit='$sabit'");
?>

Bu örnekte parametreye erişmek mümkün fakat hem mesaj id değeri hem de sabit değerin ikisini birden doğru tahmin etme olasılığı neredeyse mümkün olmadığı için bilgileriniz (örnekteki özel mesajlar için) güvende oluyor.

Global Değişken İle İle İlgili Problemler: Register Globals olarak bilinen bu sorunla en çok oturum açarken karşılaşırız. Global değişkenler ($_SESSION, $_POST, $_GET vs.) evrensel olduklarından dolayı değerleri her yerde geçerlidir. Bundan dolayı, bu değişkenlere yapılacak saldırıları hesaba katmak zorundayız. Sorunu çözmek için oturum açılmamışsa bile ilk önce oturumu iptal etmeli sonra oturum açılmalıdır. Hemen bu durumun örneğini yapalım.

<?php
//index.php?oturum=true gibi bir saldırı olabilir
//ilk önce oturumu iptal edin
$_SESSION['oturum'] = false;

if(($_POST['user'] == '$username') && ($_POST['pass'] == '$pass')){
    //içeriği kontrol edip oturumu açın
    $_SESSION['oturum'] = true;
}
?>

Bu örnekte oturumu iptal edip sonra açtığımız için saldırıda bulunan kişi giriş izni alamayacaktır. Yazdığınız programların güvenli olmasını istiyorsanız bu yazıdaki örneklerin hepsini birbiriyle uyum içerisinde kullanmalısınız. Bir kaçını dikkate alıp birkaçını dikkate almazsanız da güvenlik açığı vermiş olursunuz. Bu yazıda, sıkça düşülen güvenlik hatalarını anlatmaya çalıştım. Umarım faydalı olmuştur. Kısaca söylemek istediğim, kod yazmak kolay güvenliğini sağlamak zordur, verdiğiniz emekleri küçük ihmaller yüzünden kaybetmek istemiyorsanız yazılımı yaptığınız kadar güvenliğine de zaman ve emek harcayın.

 10.200 Okunma

Bu yazıya 19 yorum yapılmış.

  1. 10 numara makale olmuş tam aradığım makaleydi teşekkürler.

  2. Hocam valla 10 numara ders olmuş, bilmediğim açıklar varmış güzel oldu bu..bir formdan gönderilen post değerlerini alabiliyorlarmış sanırım, bunla ilgili bilginiz var mı

    • Formdan gelen değerleri anlatılan şekilde temizlerseniz problem olmaz. Aksi halde, formdan girilen değerleri almakla kalmazlar, veritabanınızla, serverınızıda yanında götürürler.

  3. Çok güzel bir makale olmuş. Teşekkürler

  4. Hocam çok saoğlun, makale çok başarılı olmuş. Burdakileri şimdi uygulayacam

  5. şimdi bu kodları var olan sitemin neresine ve nasıl yerleştirecek bilgi verebilirmisiniz ?

    • Bu kodları direk alıp kullanamazsın, kodları bunlara dikkat ederek optimize etmen gerekiyor.

  6. Makalenizi çok beğendim. Emeğinize sağlık….

  7. Öncelikle faydalı paylaşımlarınız için teşekkür ederim çok yararlı bir konu paylaşmışsınız. Dosya Yükleme İle İlgili Problemler kısmında pdf , exel , word dosyalarını nasıl ekleyebiliriz? diziye direk uzantıları eklesek olur mu yoksa ‘image/jpeg’ => ‘.jpg’, bu şekildemi olmak zorunda saat ilerledi baya denemeden sorayım dedim.

  8. Dosya yükleme işleminde malesef güvenlik yeterli değil, php dosyasını resim dosyası olarak gösterip istediği şeyi sunucuya yükleyebilir.

  9. mükemmel bir paylaşım olmuş, .htacces e de değinseymişsiniz şamda kayısı ama emeğinize sağlık

  10. Ooooooo, burayı yeni gördüm ben. Harika paylaşımlarınız var teşekkür ederim kendi adıma. İyi çalışmalar.

  11. Merhabalar, hocam öncelikle teşekkür ederim. Yaptığım sitede anlattıklarınızı uygulamaya başladım, sorum şu olacak. Form elemanlarından veri alırken karşılaşılan problemler bölümünde 3 değişik komutla temizleme işlemi göstermişsiniz, hepsini mi uygulamamız gerekiyor yoksa bir tanesini mi seçelim?

    • Hangisini kullanmak istiyorsanız aralarından onu tercih edin. Örneğin; strip_tags tamamiyle html etiketlerini kaldırırken, htmlentities etiketleri kaldırmaz sadece zararsız formata dönüştürür.

  12. gerçekten çok yararlı makale elinize emeğinize sağlık

  13. Selamün Aleyküm Arkadaşlar,
    Benim sitede mail formu var or’=1 bu tur kodları çekiyor. Sizden bu kodu aldım
    $Email = preg_replace(‘/\W/si’, ”, $Email);
    ‘or=’1 kodu olsun baska kodlar olsun hepsini temizliyor öyle kayıt ediyor, bu güzel bir şeyde bu seferde . veya @ bunları göstermiyor. Çalışan benim sorunumu giderecek kod var mı? Yardımcı olursanız sevinirim.

  14. Abi on numara makale, arayıp bulamadığım her şey senin makalelerde.

  15. Hocam bu bilgileri güncellemen gerek artık. Msql real in felan bypassları var. Dosya türü kontrol demişsin oda açıkta kalmış mesela gif89 açığı ve dosya bilgisini ara programlarla temperler ile değiştire biliyoruz. Bir php dosyasını jpg olarak gösterebiliyoruz felan.

    En basiti resim yüklerken dosyayı resim olarak işleyebiliriz veya dosya içinde <? gibi phpye özgü stringleri aratabiliriz.

  16. Üstad Maşallah. Teşekkür ediyorum. Hazine gibi paylaşımlar yapıyorsun.

Yazı hakkında görüşlerinizi belirtmek istermisiniz?

Daha fazla Php
Kapat