Paylaşımlı hosting üzerinde çalışan bir PHP uygulamasında ziyaretçilere dosya yükleme imkânı verdiğiniz anda, sitenizin saldırı yüzeyini ciddi şekilde genişletmiş olursunuz. Profil fotoğrafı, fatura PDF’i, özgeçmiş veya destek bileti eki… Senaryo ne olursa olsun, kullanıcıdan gelen her dosya potansiyel bir saldırı vektörüdür. Özellikle aynı fiziksel sunucuda birden fazla hesabın bulunduğu paylaşımlı hosting ortamlarında, küçük bir güvenlik açığı bazen tüm hesabı, hatta yan hesapları bile etkileyebilir.
Bu yazıda DCHost ekibi olarak, paylaşımlı hosting’de dosya yükleme formlarını gerçekten güvenli hale getirmek için neler yapmanız gerektiğini adım adım ele alacağız. Odakta üç temel başlık var: PHP ayarları, MIME türü / içerik kontrolü ve klasör izinleri. Ayrıca tipik bir PHP upload akışını örnek kodlarla inceleyecek, dosyaların web kökü dışında tutulması, .htaccess ile erişimin sınırlandırılması ve log tutma gibi kritik detaylara da değineceğiz. Yazının sonunda, hangi aşamada paylaşımlı hosting’den çıkarak DCHost üzerinde bir VPS veya dedicated sunucuya geçmeyi düşünmeniz gerektiğini de daha net görebileceksiniz.
İçindekiler
- 1 Paylaşımlı Hosting’de Dosya Yükleme Neden Bu Kadar Riskli?
- 2 Güvenli Dosya Yükleme Akışı Nasıl Olmalı?
- 3 PHP Ayarlarıyla Dosya Yüklemeyi Sıkılaştırmak
- 4 MIME Türü ve İçerik Doğrulama: Sadece Uzantıya Güvenmeyin
- 5 Klasör Yapısı ve İzinleri: 777’den Uzak Durun
- 6 Paylaşımlı Hosting’e Özel Ek Önlemler
- 7 WordPress ve Hazır Script’lerde Dosya Yükleme Güvenliği
- 8 HTTP Güvenlik Başlıkları ve Tarayıcı Tarafı Koruma
- 9 Ne Zaman VPS veya Dedicated Sunucuya Geçmeyi Düşünmelisiniz?
- 10 Sonuç ve DCHost Üzerinde Güvenli Yükleme Stratejisi
Paylaşımlı Hosting’de Dosya Yükleme Neden Bu Kadar Riskli?
Paylaşımlı hosting’in doğası gereği, aynı fiziksel sunucuda yüzlerce hatta binlerce site bir arada barınır. Her ne kadar modern izolasyon teknolojileri (CloudLinux, cagefs vb.) riskleri azaltsa da, hatalı bir dosya yükleme mantığı hâlâ en sık gördüğümüz saldırı girişimlerinden biridir.
En yaygın riskler:
- PHP shell yüklenmesi: Kullanıcı .php, .phtml, .php5 gibi bir dosyayı resim uzantısıyla gizleyip yükler ve sunucu bunu çalıştırırsa, hesabınız tamamen ele geçirilebilir.
- Uzaktan kod çalıştırma ve dosya okuma: Yanlış yapılandırılmış upload klasörleri, saldırganların konfigürasyon dosyalarını okumasına, loglara erişmesine hatta diğer sitelere sıçramasına yol açabilir.
- Disk dolması ve inode tüketimi: Sınırsız gibi görünen upload formları, özellikle spam bot’ları tarafından kullanıldığında, paylaşımlı hosting hesabınızın disk kotasını ve inode limitini çok hızlı doldurabilir.
inode tarafındaki etkileri pratikte sıkça görüyoruz; bu konuyu detaylı ele aldığımız paylaşımlı hosting’de inode limitine takılmamak için uygulamalı temizlik rehberi yazısına da göz atmanız faydalı olur.
Riskleri azaltmanın yolu, tek bir önlemden değil, katmanlı bir yaklaşımdan geçiyor: PHP seviyesinde sıkı ayarlar, uygulama kodunda dosya ve MIME doğrulaması, dosya sisteminde güvenli klasör yapısı ve izinleri, artı web sunucusu seviyesinde ek korumalar.
Güvenli Dosya Yükleme Akışı Nasıl Olmalı?
Önce ideal akışı netleştirelim. Güvenli bir dosya yükleme süreci kabaca şu adımlardan oluşmalı:
- Kullanıcı oturumunun (login) ve CSRF tokenının doğrulanması
- Dosyanın boyutunun kontrolü (hem PHP ini limitleri hem uygulama limiti)
- Dosya adının ve uzantısının beyaz listeye göre kontrolü
- MIME / içerik türü doğrulaması (finfo_file, getimagesize, exif_imagetype vb.)
- Rastgele isimlendirme ve güvenli bir hedef klasöre taşıma (move_uploaded_file)
- Upload klasörünün web’den doğrudan erişilememesi veya en azından çalıştırılabilir dosyalara kapatılması
- Gerekli log kayıtlarının tutulması ve şüpheli durumların raporlanması
İzin verilen dosya türlerini net tanımlayın
“Her şeyi yükleyebilsin” dediğiniz anda büyük ihtimalle kaybediyorsunuz. İhtiyacınız neyse, sadece onu kabul edin:
- Profil fotoğrafı: jpg, jpeg, png, webp
- Doküman: pdf (gerekirse docx, xlsx ama çok düşünerek)
Ve kesinlikle şu uzantıları yasaklayın (tam liste değil, örnek):
- php, php3, php4, php5, php7, php8, phtml, phar
- cgi, pl, asp, aspx, jsp
- sh, bash, exe, dll, so
Uzantı kontrolü tek başına yeterli değil ama “ilk savunma hattı” olarak mutlaka olmalı.
Basit bir HTML formu ve temel PHP işleyici örneği
Önce oldukça sade bir form:
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token']); ?>">
<input type="file" name="dosya" required>
<button type="submit">Yükle</button>
</form>
Şimdi de bu formu işleyecek upload.php dosyasında minimum güvenlik adımlarını içeren basit bir örnek:
<?php
session_start();
// 1) CSRF kontrolü
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token']) ||
!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die('Geçersiz istek');
}
// 2) Dosyanın gerçekten yüklendiğinden emin olun
if (!isset($_FILES['dosya']) || $_FILES['dosya']['error'] !== UPLOAD_ERR_OK) {
die('Dosya yükleme hatası');
}
$dosya = $_FILES['dosya'];
// 3) Maksimum boyut (örnek: 2 MB)
$maxBoyut = 2 * 1024 * 1024; // 2 MB
if ($dosya['size'] > $maxBoyut) {
die('Dosya çok büyük');
}
// 4) Uzantı kontrolü
$izinliUzantilar = ['jpg', 'jpeg', 'png', 'pdf'];
$orijinalIsim = $dosya['name'];
$uzanti = strtolower(pathinfo($orijinalIsim, PATHINFO_EXTENSION));
if (!in_array($uzanti, $izinliUzantilar, true)) {
die('Bu dosya türüne izin verilmiyor');
}
// 5) MIME kontrolü (aşağıda detaylandıracağız)
// 6) Güvenli klasöre rastgele isimle kaydetme
Buraya kadar olan kısım sadece “ısınma”. Asıl kritik noktalar, PHP ayarları ve MIME / içerik doğrulaması ile klasör izinlerinde başlıyor.
PHP Ayarlarıyla Dosya Yüklemeyi Sıkılaştırmak
Paylaşımlı hosting’de çoğu zaman php.ini’yi doğrudan editleyemezsiniz. Ancak DCHost gibi modern platformlarda genellikle .htaccess üzerinden php_value ile ya da paneldeki PHP seçici arayüzü üzerinden birçok önemli limiti özelleştirebilirsiniz. upload güvenliğiyle doğrudan ilişkili kritik ayarlara bakalım.
upload_max_filesize, post_max_size ve max_file_uploads
- upload_max_filesize: Tek bir dosyanın maksimum boyutu.
- post_max_size: Tüm POST içeriğinin (form alanları + dosyalar) toplam boyutu.
- max_file_uploads: Tek istekte izin verilen maksimum dosya sayısı.
Örneğin sadece profil fotoğrafı alıyorsanız, 50 MB gibi gereksiz yüksek değerler yerine, 2–5 MB seviyesinde limitler belirlemek çok daha güvenlidir. Bu ayarları ve memory_limit, max_execution_time gibi diğer kritik değerleri detaylı anlattığımız PHP ayarlarını doğru yapmak rehberi yazısına mutlaka göz atmanızı öneririz.
Örnek .htaccess ayarları (sunucu izin veriyorsa):
php_value upload_max_filesize 4M
php_value post_max_size 4M
php_value max_file_uploads 5
Buradaki değerler üst sınırdır. Uygulama kodunuzda da ayrıca daha düşük limit uygulayabilirsiniz (örneğin 2 MB).
Geçici dizin, open_basedir ve hata logları
PHP önce dosyayı geçici dizine (tmp) yazar, ardından move_uploaded_file() ile sizin belirttiğiniz klasöre taşır. İki noktaya dikkat:
- open_basedir: Bu ayarla PHP’nin erişebileceği dizinleri sınırlandırabilirsiniz. Paylaşımlı hosting’de çoğu zaman hosting sağlayıcınız bunu sizin yerinize güvenli bir şekilde ayarlamıştır. DCHost’ta da kullanıcıların birbirlerinin dosyalarına erişememesi için gerekli izolasyon yapılandırmaları varsayılan olarak etkindir.
- error_log: Hataların nereye yazıldığını bilmek, upload problemlerini teşhis ederken çok yardımcı olur. PHP log yapılandırmasını detaylı anlattığımız PHP hata kayıtlarını doğru yapılandırma rehberi yazısını da buraya not düşelim.
Hata loglarında özellikle:
- upload hataları (UPLOAD_ERR_*)
- “Exceeded filesize limit” benzeri iletiler
- Beklenmedik MIME türleri veya bozuk dosya hataları
karşınıza çıkıyorsa, hem güvenlik hem de kullanılabilirlik açısından ayarlarınızı yeniden gözden geçirmeniz gerekir.
MIME Türü ve İçerik Doğrulama: Sadece Uzantıya Güvenmeyin
Uzantı kontrolü gereklidir ama asla yeterli değildir. shell.php dosyasını “shell.php.jpg” olarak isimlendirip yüklemek, daha sonra da web sunucusunun zayıf bir yapılandırmasından faydalanarak bunu çalıştırmaya çalışmak saldırganların klasik numaralarından biridir.
Bu nedenle hem dosya adını/uzantısını hem de dosyanın gerçek içeriğini kontrol etmek zorundasınız.
finfo_file ile sunucu taraflı MIME kontrolü
PHP’nin fileinfo eklentisi, dosyanın başlık bilgisinden (magic bytes) yola çıkarak gerçek türünü anlamaya çalışır. Örnek bir kontrol akışı:
<?php
$izinliMime = [
'image/jpeg',
'image/png',
'application/pdf',
];
$finfo = new finfo(FILEINFO_MIME_TYPE);
$gercekMime = $finfo->file($dosya['tmp_name']);
if (!in_array($gercekMime, $izinliMime, true)) {
die('Geçersiz dosya formatı');
}
Dikkat edilmesi gereken bir nokta: Tarayıcının gönderdiği $_FILES['dosya']['type'] alanı güvenilir değildir; bunu kullanmayın. Her zaman sunucu tarafında finfo_file veya benzeri fonksiyonlarla analiz yapın.
Görseller için ek kontroller (getimagesize, exif_imagetype)
Eğer sadece görsel kabul eden bir upload alanınız varsa, ek güvenlik için:
getimagesize()ile resmin boyutlarını ve türünü okumak,exif_imagetype()ile gerçekten resim olduğundan emin olmak,
mantıklıdır. Örneğin:
<?php
$bilgi = @getimagesize($dosya['tmp_name']);
if ($bilgi === false) {
die('Geçerli bir resim dosyası değil');
}
$genislik = $bilgi[0];
$yukseklik = $bilgi[1];
if ($genislik > 2000 || $yukseklik > 2000) {
die('Resim boyutu çok büyük');
}
Bu tür kontroller, bozuk ya da zararlı payload içeren sözde “resim” dosyalarını önemli ölçüde filtreler.
Klasör Yapısı ve İzinleri: 777’den Uzak Durun
Upload güvenliğinin en kritik fakat en çok ihmal edilen kısmı, dosya sistemindeki konum ve izinlerdir. Paylaşımlı hosting’de “çalışsın da nasıl çalışırsa çalışsın” diye upload klasörüne 777 vermek, saldırganlar için davetiye çıkarmaktır.
Upload klasörünü web kökünün dışına taşıyın
En güvenli senaryo, yüklenen dosyaların web’den doğrudan erişilemeyen bir dizinde tutulmasıdır. Örneğin cPanel benzeri bir yapıda:
- Web kökü:
/home/kullanici/public_html - Upload klasörü:
/home/kullanici/uploads(public_html dışında)
Bu durumda kullanıcıya dosya sunmak için bir PHP betiği üzerinden “proxy” yaparsınız:
<?php
// dosya_indir.php
// Yetki kontrolü, login vb.
$dosyaYolu = '/home/kullanici/uploads/' . $kaydedilenDosyaAdi;
if (!file_exists($dosyaYolu)) {
http_response_code(404);
exit('Bulunamadı');
}
// İçerik türünü ayarla (güvenli bir whitelist üzerinden)
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="indirme.pdf"');
readfile($dosyaYolu);
Böylece dosya asla doğrudan URL ile çağrılamaz; mutlaka sizin kontrolünüzden geçer.
Mecbursanız, public_html içinde .htaccess ile erişimi kısıtlayın
Bazı hazır script’ler veya kısıtlı yapılandırmalarda upload klasörünü web kökü dışına çıkarmak zor olabilir. Bu durumda en azından o klasör içinde .htaccess ile script çalıştırılmasını engellemek kritik bir adım olur:
# uploads/.htaccess
Options -Indexes
<FilesMatch ".(php|php3|php4|php5|php7|php8|phtml|phar)$">
Deny from all
</FilesMatch>
Bu ayarlar Apache tabanlı sistemler için örnektir. LiteSpeed gibi uyumlu sunucularda da benzer şekilde çalışır. Nginx kullanıyorsanız, ilgili location bloğunda PHP uzantılarını devre dışı bırakmanız gerekir.
Doğru dosya izinleri: 644, 755 ve asla 777 değil
Dosya ve klasör izinleri konusunda ayrıntılı olarak Linux dosya izinleri 644, 755, 777 rehberi yazımızda bahsetmiştik; burada upload özelinde özetleyelim:
- Klasörler: Genellikle
755yeterlidir (sahip: yazma, diğerleri: okuma + çalıştırma). - Dosyalar: Çoğu senaryoda
644idealdir (sahip: okuma + yazma, diğerleri: okuma). - 777: Herkese yazma izni verdiğinden, çok ciddi güvenlik riski taşır; kaçınmalısınız.
Paylaşımlı hosting’de dosya ve klasörler genellikle web sunucusuyla aynı kullanıcı ya da aynı grup altında çalıştığı için, 755/644 izinleri hem “çalışır” hem de makul güvenlik seviyesi sunar. İzinleri sürekli 777 yapmanız gerekiyorsa, asıl sorunu (sahiplik, PHP-FPM kullanıcı ayarı vb.) tespit etmek daha doğrudur.
Paylaşımlı Hosting’e Özel Ek Önlemler
Paylaşımlı hosting’de saldırganlar genellikle tek bir açığı kitlesel olarak sömürmeye çalışır: Aynı yazılımı kullanan yüzlerce siteye otomatik bot’larla aynı payload’ı yollarlar. Dosya upload formları da bu otomatik saldırıların popüler hedefidir.
Oran sınırlama, CAPTCHA ve oturum kontrolleri
Şu önlemler özellikle önemlidir:
- Giriş zorunluluğu: Mümkünse dosya upload’ını sadece giriş yapmış kullanıcılara açın.
- reCAPTCHA / Honeypot: Otomatik bot’ların formu doldurmasını zorlaştırır. Bu konuda daha genel bir bakış için iletişim formu spam’ini azaltma rehberi yazımıza bakabilirsiniz.
- Oran sınırlama (rate limiting): Aynı IP veya kullanıcı için birim zamanda yapılabilecek upload sayısını sınırlayın.
Bunlar doğrudan PHP upload güvenliği değilmiş gibi görünse de, pratikte en çok işinize yarayan savunma katmanlarından biridir.
Log tutma, izleme ve şüpheli dosyaları temizleme
Ne kadar iyi tasarlarsanız tasarlayın, pratikte hatalar olabilir veya yeni saldırı teknikleri ortaya çıkabilir. Bu nedenle:
- Her upload işlemini (kullanıcı, IP, dosya adı, boyutu, MIME türü) basit bir tabloya veya log dosyasına kaydedin.
- Normalde beklemediğiniz dosya türleri, aşırı büyük boyutlar veya aynı IP’den kısa sürede gelen çok sayıda dosya gibi anomalileri tespit edin.
- Şüpheli durumlarda ilgili dosyaları devre dışı bırakın, hesabı kilitleyin veya en azından manuel incelemeye alın.
Eğer sitenizin daha önce upload üzerinden hacklendiğini düşünüyorsanız, hacklenmiş PHP sitelerini temizleme rehberimiz size sağlam bir yol haritası sunacaktır.
WordPress ve Hazır Script’lerde Dosya Yükleme Güvenliği
Çoğu WordPress, forum veya hazır CRM/yardım masası script’i kendi upload mantığını beraberinde getirir. “Ben zaten popüler bir sistem kullanıyorum, düşünmeme gerek yok” demek ise maalesef gerçekçi değil.
- Kullandığınız tema ve eklentilerin hangi upload endpoint’lerine sahip olduğunu bilin.
- Mümkün olduğu kadar az eklentinin dosya yüklemesine izin verin.
- Güncellemeleri düzenli yapın; upload ile ilgili güvenlik yamaları sıkça yayınlanır.
- Ek koruma için WAF (Web Uygulama Güvenlik Duvarı) ve güvenlik eklentileri kullanın.
WordPress kullanıyorsanız, paylaşımlı hosting ortamında alabileceğiniz ek önlemleri paylaşımlı hosting’de WordPress güvenliği yazımızda detaylı anlattık. Dosya izinleri, WAF, 2FA ve yedekleme stratejileriyle birlikte ele alındığında, upload yüzeyiniz çok daha güvenli hâle gelir.
HTTP Güvenlik Başlıkları ve Tarayıcı Tarafı Koruma
Dosya upload’ı doğrudan HTTP güvenlik başlıklarıyla ilgili olmasa da, indirilen dosyaların tarayıcıda nasıl işlendiği üzerinde etkili olabilirsiniz. Örneğin:
- Content-Type başlığını doğru ayarlayarak, dosyanın “indirme” mi yoksa “tarayıcıda görüntüleme” mi olacağını kontrol edebilirsiniz.
- Content-Disposition: attachment kullanarak, örneğin PDF’lerin tarayıcı içinde değil de indirme şeklinde açılmasını sağlayabilirsiniz.
- X-Content-Type-Options: nosniff ile tarayıcının içerik türünü tahmin etmeye çalışmasını engelleyebilirsiniz.
HTTP başlıklarıyla ilgili kapsamlı bir anlatımı HTTP güvenlik başlıkları rehberimizde bulabilirsiniz. Özellikle X-Content-Type-Options ve Content-Security-Policy, zararlı içeriklerin tarayıcıda çalıştırılmasını zorlaştırma açısından önemlidir.
Ne Zaman VPS veya Dedicated Sunucuya Geçmeyi Düşünmelisiniz?
Paylaşımlı hosting, doğru kullanıldığında son derece ekonomik ve pratik bir çözümdür. Ancak dosya yükleme yoğunluğu ve güvenlik beklentisi arttıkça, daha fazla kontrol ihtiyacınız da artar. Şu durumlarda DCHost üzerinde bir VPS veya dedicated sunucu düşünmek mantıklı olabilir:
- Çok sayıda kullanıcıya dosya yükleme imkânı veriyorsanız (örn. müşteri portalı, eğitim platformu, dosya paylaşım servisi).
- Yüklenen dosyaları arka planda işliyorsanız (görsel sıkıştırma, video dönüştürme vb.).
- Web sunucusu ve PHP yapılandırmasını (Nginx/Apache kuralları, ayrı PHP-FPM havuzları, özel güvenlik modülleri) ince ayar yapmak istiyorsanız.
- Upload trafiğiniz ve depolama ihtiyacınız klasik paylaşımlı hosting sınırlarını zorluyorsa.
DCHost olarak hem VPS hem de dedicated sunucu ve colocation hizmetleriyle, dosya yükleme yoğunluğu yüksek uygulamalarınızı izole ve ölçeklenebilir bir altyapıya taşımanıza yardımcı olabiliriz. Böylece upload güvenliğini sadece uygulama kodu seviyesinde değil, ağ, firewall, WAF ve dosya sistemi seviyelerinde de dilediğiniz kadar sıkılaştırabilirsiniz.
Sonuç ve DCHost Üzerinde Güvenli Yükleme Stratejisi
Paylaşımlı hosting’de dosya yükleme formlarını güvenli hale getirmek, tek bir “sihirli ayar”la çözülebilecek bir konu değil. PHP ayarları, MIME / içerik doğrulaması ve klasör izinleri bir araya geldiğinde, üzerine de oturum kontrolleri, CAPTCHA, oran sınırlama ve loglama gibi katmanlar eklendiğinde gerçekten tatmin edici bir güvenlik seviyesi oluşturabilirsiniz.
Özetle:
- İzin verilen dosya türlerini net tanımlayın, uzantı ve MIME kontrolünü birlikte kullanın.
upload_max_filesizevepost_max_sizedeğerlerini ihtiyacınıza göre kısıtlayın; gereksiz “dev” limitlerden kaçının.- Upload klasörünü mümkünse web kökü dışına taşıyın; değilse .htaccess ile script çalıştırılmasını engelleyin.
- Dosya ve klasör izinlerinde 755/644 çizgisini koruyun; 777’yi gündeminizden çıkarın.
- Şüpheli aktiviteleri tespit edebilmek için upload işlemlerini mutlaka loglayın.
Eğer mevcut sitenizde dosya yükleme güvenliğinden emin değilseniz veya yeni bir proje planlarken mimariyi doğru kurmak istiyorsanız, DCHost ekibi olarak hem paylaşımlı hosting hem de VPS / dedicated çözümler üzerinde sizinle birlikte en uygun stratejiyi tasarlayabiliriz. İhtiyaçlarınız büyüdüğünde, paylaşımlı hosting’den DCHost VPS’e geçişi nasıl sorunsuz yapabileceğinizi anlattığımız paylaşımlı hosting’den VPS’e sorunsuz geçiş rehberi yazımız da yolun devamı için iyi bir rehber olacak.
Doğru kurgulanmış bir upload akışı hem kullanıcı deneyimini bozmadan çalışır, hem de güvenlik denetimlerinden yüzünüzün akıyla çıkmanızı sağlar. Bir sonraki projede, dosya yükleme kısmını “son dakikaya” bırakmayın; mimari tasarımın ilk günlerinden itibaren oyunun bir parçası yapın.
