Aynı sunucuda birden fazla site güvenle nasıl barındırılır?
Yayın:
- Sorun ne?
- Bütün siteler aynı kullanıcıyla çalışırsa, birindeki açık saldırgana hepsinin dosyalarını açar.
- Çözüm ne?
- Her siteye ayrı bir sistem kullanıcısı ve ayrı bir PHP havuzu vermek. Böylece bir site diğerlerinin dosyalarını okuyamaz.
- Zor mu?
- Elle her site için birkaç dosya demek. Kontrol paneli bunu site eklerken kendiliğinden yapabilir.
Tek bir sunucuda on site barındırmak ucuz ve pratiktir. Ama siteler birbirinden yalıtılmamışsa, en zayıf sitenin açığı on sitenin hepsinin açığı olur. Bu yazı, aynı sunucudaki siteleri birbirinden ayırmanın yollarını anlatıyor.
Sorun: herkes aynı kullanıcıyla çalışıyor
Varsayılan kurulumlarda bütün siteler web sunucusunun tek kullanıcısıyla (www-data) çalışır.
Bir sitede güncellenmemiş bir eklentiden içeri giren saldırgan, o kullanıcının okuyabildiği her şeyi okur: diğer
sitelerin dosyaları, wp-config.php gibi veritabanı parolası içeren ayar dosyaları dahil.
1. Her siteye ayrı bir sistem kullanıcısı
sudo useradd --system --home /var/www/ornek.com --shell /usr/sbin/nologin ornekcom
sudo mkdir -p /var/www/ornek.com/public_html /var/www/ornek.com/tmp
sudo chown -R ornekcom:ornekcom /var/www/ornek.com
sudo chmod 750 /var/www/ornek.com
sudo chmod 700 /var/www/ornek.com/tmp
750 izniyle dizine yalnız sahibi ve grubu girebilir; diğer sitelerin kullanıcıları giremez.
Web sunucusunun statik dosyaları okuyabilmesi için web sunucusu kullanıcısını sitenin grubuna eklemeniz gerekir;
ama bunu yalnız 3. adımdaki sembolik bağ korumasıyla birlikte yapın. Web sunucusu bütün sitelerin
grubunda olduğunda, bir site kendi dizinine komşu sitenin wp-config.php dosyasını gösteren bir
sembolik bağ koyup onu web sunucusuna okutabilir. Sitenin kendi tmp dizini PHP'nin geçici
dosyaları ve oturumları içindir (2. adım).
2. Her siteye ayrı bir PHP-FPM havuzu
PHP kodu sitenin kendi kullanıcısıyla çalışmalı. Bunun için her site kendi PHP-FPM havuzunu alır:
# /etc/php/8.4/fpm/pool.d/ornek.com.conf
[ornek.com]
user = ornekcom
group = ornekcom
listen = /run/php/ornek.com.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 5
php_admin_value[open_basedir] = /var/www/ornek.com:/usr/share/php
php_admin_value[upload_tmp_dir] = /var/www/ornek.com/tmp
php_admin_value[sys_temp_dir] = /var/www/ornek.com/tmp
php_admin_value[session.save_path] = /var/www/ornek.com/tmp
pm = ondemand az ziyaret alan sitelerin boşta bellek tüketmesini önler; open_basedir
PHP'nin site dizini dışındaki dosyalara erişmesini sınırlar. Ortak /tmp'yi listeye eklemeyin:
orada başka sitelerin yüklenen dosyaları, oturumları ve root'un geçici dosyaları durur; site oraya sembolik bağ da
kurabilir. Yükleme, geçici dosya ve oturum yolları bu yüzden sitenin kendi tmp dizinine alınır.
3. Web sunucusunda sembolik bağ koruması
Site, web sunucusu ayarında kendi PHP soketine yönlendirilir. Aynı yerde, başka bir kullanıcıya ait dosyayı gösteren sembolik bağları reddedin (nginx):
# /etc/nginx/sites-available/ornek.com
server {
server_name ornek.com www.ornek.com;
root /var/www/ornek.com/public_html;
# Bağ ile hedefi aynı kullanıcıya ait değilse 403
disable_symlinks if_not_owner from=/var/www/ornek.com;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/ornek.com.sock;
}
}
if_not_owner, sitenin kendi dosyalarını gösteren bağlara (ör. sürüm dizinine bağlanan
public_html) izin verir; komşu sitenin dosyasını gösteren bağı reddeder.
4. Her siteye ayrı veritabanı kullanıcısı
Bütün sitelerin aynı veritabanı kullanıcısını, hele root'u kullanması, bir sitenin parolasıyla
bütün veritabanlarının açılması demektir. Her siteye yalnız kendi veritabanında yetkili bir kullanıcı verin:
CREATE USER 'ornekcom'@'localhost' IDENTIFIED BY '<güçlü-parola>';
GRANT ALL PRIVILEGES ON ornekcom_db.* TO 'ornekcom'@'localhost';
5. Yönetim araçlarını herkese açmayın
phpMyAdmin gibi araçlar her sitenin adresinden (ornek.com/phpmyadmin) açık olursa saldırganlar için
hazır bir giriş kapısı olur. Bu araçlara yalnız panel üzerinden ve yetkili kişilerin erişmesini sağlayın.
6. Yedekleri de site site alın
Bir site ele geçirildiğinde yalnız o siteyi temiz bir yedekten dönebilmek, bütün sunucuyu geri almaktan çok daha hızlıdır. Yedekleri site bazında ve sunucu dışına kopyalayarak alın.
Yalıtımı kontrol edin
# PHP işçileri hangi kullanıcılarla çalışıyor? Hepsi www-data ise yalıtım yok.
ps -eo user,cmd | grep 'php-fpm: pool' | sort | uniq -c
# Havuzlarda ortak /tmp açık mı? Çıktı boş olmalı.
grep -H 'open_basedir.*:/tmp' /etc/php/*/fpm/pool.d/*.conf
# nginx sembolik bağ koruması her sitede var mı?
grep -L 'disable_symlinks' /etc/nginx/sites-enabled/*
SunucuKontrol'de
Bunların hepsini her site için elle yapmak zaman alır ve unutulmaya açıktır. SunucuKontrol'de siteler ortak bir
kullanıcıyı paylaşmaz: panel her alan adını eklerken ona kendi sistem kullanıcısını, kendi PHP-FPM soketini ve kendi
tmp dizinini (yükleme, geçici dosya ve oturumlar için) verir; nginx ayarına
disable_symlinks if_not_owner kendiliğinden yazılır.
phpMyAdmin müşteri alan adlarında hiç yayınlanmaz, yalnız panelden açılır. Ayrıntılar için
panel seçerken dikkat edilmesi gerekenler
yazısına bakabilirsiniz.
İlgili yazılar
Sunucu kontrol paneli nedir, ne işe yarar?
Sunucu kontrol panelinin ne olduğu, neleri yönettiği, ne zaman gerektiği ve panel seçerken güvenliğin neden ilk sırada geldiği.
Sunucu kontrol paneli seçerken dikkat edilmesi gereken 8 şey
Güvenlik mimarisi, güncelleme yöntemi, lisans modeli, yedekleme ve taşıma: panel seçmeden önce sormanız gereken sekiz soru.
VPS'e kontrol paneli nasıl kurulur? Ubuntu ve Debian'da adım adım
Temiz bir Ubuntu ya da Debian sunucuya kontrol paneli kurmak: sunucu gereksinimleri, imza doğrulamalı kurulum ve kurulumdan sonraki ilk güvenlik adımları.
cPanel ya da Plesk'ten yeni sunucuya site taşıma: kesintisiz adım adım
Siteleri, veritabanlarını ve e-postaları başka bir panelden yeni sunucuya kesinti olmadan taşımak: DNS hazırlığı, yedek, deneme ve geçiş günü.