PHP, sunucu tarafında çalışan ve web uygulamalarında yaygın olarak kullanılan bir betik dilidir. PHP kaynaklı güvenlik sorunlarının önemli bir bölümü uygulama kodundan değil, hatalı veya eksik sunucu yapılandırmalarından ortaya çıkar. Varsayılan ayarlarla çalışan PHP kurulumları, özellikle çoklu site barındırılan sistemlerde sunucu güvenliğini zayıflatır. Bu yazıda ele alınan önlemler, kontrolü uygulama seviyesinden alıp işletim sistemi katmanına taşımayı amaçlar.
PHP Tarafında Sık Görülen Saldırı Türleri
PHP tabanlı sistemlerde saldırılar çoğunlukla benzer zayıf noktalara odaklanır. Sahada en sık karşılaşılan ve etkisi en ağır olan saldırı türleri aşağıda özetlenmiştir.
Remote Code Execution (RCE)
RCE, PHP üzerinden sunucuda sistem komutlarının çalıştırılabilmesidir. exec, system ve shell_exec gibi fonksiyonlar açık olduğunda ortaya çıkar. Başarılı bir RCE saldırısı genellikle tüm sunucunun ele geçirilmesiyle sonuçlanır.
disable_functions = exec,system,shell_exec,passthru,proc_open,popenDosya Yükleme Üzerinden Web Shell
Yanlış yapılandırılmış dosya yükleme alanları istismar edilir. Saldırgan PHP dosyası yükleyerek sunucu üzerinde kalıcı erişim elde edebilir.
location /uploads {
php_admin_flag engine off;
}Local File Inclusion (LFI)
Kullanıcı girdisiyle dosya include edilmesi sonucu oluşur. Sistem dosyaları ve loglar okunabilir, log poisoning ile birlikte RCE’ye dönüşebilir.
open_basedir = "/var/www/site:/tmp"SQL Injection
Filtrelenmeyen kullanıcı girdileri SQL sorgularına girdiğinde ortaya çıkar. Veritabanı içeriği sızdırılabilir veya yetkili hesaplar ele geçirilebilir.
SELECT * FROM users WHERE id = ?Bu saldırıların ortak noktası, PHP’nin erişim ve yetki sınırlarının net tanımlanmamış olmasıdır.
PHP’yi Her Zaman Güncel Tutalım
Eski PHP sürümleri, bilinen güvenlik açıklarının en kolay hedefidir. Özellikle EOL olmuş PHP 7.x serisini üretimde çalıştırmak, saldırganlar için gereksiz bir avantaj oluşturur.
Dağıtımına uygun paket yöneticisiyle (apt, dnf, yum, zypper) güvenlik güncellemelerini geciktirmeden uygulayın ve yükseltme planını test ortamında doğrulayın.
PHP 7.4.3 sürümünden PHP 8.x serisine geçişi komut satırından nasıl yapacağını adım adım görmek için aşağıdaki rehbere bakabilirsiniz.
🟠 PHP 7.4.3’ten PHP 8.x’e Komut Satırıyla Geçiş
Dosya Sistemi Erişimini Sınırlama
PHP, dosya sistemiyle doğrudan etkileşime giren bir dil olduğu için hatalı yapılandırmalar ciddi güvenlik riskleri doğurur. Bu nedenle ilk yapılması gereken işlem, PHP’nin hangi dizinlere erişebileceğinin açık ve net şekilde tanımlanmasıdır.
open_basedir = "/var/www/site:/tmp"PHP İşlemlerinin Yetkisi
Root yetkisiyle çalışan bir PHP süreci, oluşabilecek tek bir güvenlik açığında tüm sunucunun ele geçirilmesine yol açabilir. Bu sebeple PHP-FPM veya CGI süreçleri mutlaka düşük yetkili kullanıcılar altında çalıştırılmalıdır.
ps aux | grep phpHer uygulama için ayrı PHP-FPM havuzu tanımlanmalı ve her havuz kendine ait kullanıcıyla çalıştırılmalıdır. Plesk kullanılan ortamlarda domain bazlı PHP-FPM havuzu ve kaynak limitleri belirlenerek bu izolasyon daha net hale getirilebilir.
PHP Fonksiyonlarını Devre Dışı Bırak
PHP varsayılan olarak sistem komutu çalıştırabilen fonksiyonlarla gelir. Uygulama kullanmıyorsa açık kalmamalıdır.
disable_functions = exec,system,shell_exec,passthru,popen,proc_openPHP’nin İletişimini Sınırla
Uzak dosya erişimi çoğu zaman zincirleme açıkların başlangıcıdır. Varsayılan olarak kapalı olmalıdır.
allow_url_fopen = Off<br>allow_url_include = OffPHP Loglarını Ayır ve İzle
PHP error log’ları sadece debug değil, saldırı tespiti içindir. Her PHP-FPM havuzu için ayrı log dosyaları tanımlanmalıdır. Loglar merkezi sistemlere aktarılmalı ve izlenmelidir.
PHP Modüllerini Ters Mantıkla Yönet
Önce neye ihtiyaç olduğunu belirle, sonra modülleri aç. Kullanılmayan her modül ek saldırı yüzeyidir.
php -m
mv /etc/php.d/xmlrpc.ini /etc/php.d/xmlrpc.off
systemctl restart php-fpmDosya Yükleme Mekanizmalarını Daralt
Dosya yükleme mümkünse kapatılmalıdır. Zorunluysa sınırlandırılmalıdır.
file_uploads = On
upload_max_filesize = 2M
upload_tmp_dir = /var/lib/php/tmpPHP Hata Mesajlarını Kullanıcıdan Gizle
Hata mesajları saldırgan için ipucu olabilir. Ekran kapalı, log açık olmalıdır.
display_errors = Off
log_errors = On
error_log = /var/log/php/runtime-error.logScript Süresi ve Bellek Sınırları Koy
Sonsuz veya ağır script’ler saldırı olmasa bile sorundur. Temel sınırlar mutlaka tanımlanmalıdır.
max_execution_time = 30
max_input_time = 30
memory_limit = 256MDosya ve Dizin İzinlerini En Sona Al
En doğru zaman en sondur. Artık uygulamanın nereye yazdığını biliyorsundur.
find /var/www/site -type f -exec chmod 0444 {} \;
find /var/www/site -type d -exec chmod 0555 {} \;SELinux ve WAF ile İkinci Savunma Katmanını Kur
PHP ayarları ilk savunma hattıdır. SELinux ve WAF ikinci katmandır.
getsebool -a | grep httpdSık Sorulan Sorular
PHP-FPM havuzları dolup taşıyorsa güvenlik mi performans mı sorunudur?
Genellikle güvenliktir. Beklenmeyen istekler veya kötü niyetli script’ler PHP-FPM child’larını kilitleyebilir. Havuz dolulukları incelenmeli, istek kaynağı loglardan tespit edilmelidir.
PHP bir dizine erişmeye çalışıyor ama neden eriştiğini bilmiyorum, nasıl bulurum?
PHP-FPM süreci sistem çağrılarıyla izlenmelidir. Dosya erişim denemeleri bu şekilde netleşir.
strace -e trace=file -p $(pgrep -n php-fpm)PHP prosesleri neden DNS sorgusu atıyor olabilir?
Genellikle harici API çağrıları veya loglama servisleri sebep olur. resolv.conf erişimleri ve outbound bağlantılar kontrol edilmelidir.
PHP’de sessiz çalışan bir web shell’i nasıl fark ederim?
Anormal dosya zaman damgaları ve beklenmeyen PHP child’ları kontrol edilmelidir. Upload dizinleri özellikle izlenmelidir.