Görsel kabul eden bir yükleme formu, sunucunuza dosya koymanın bir yoludur. Doğrulama içeri sızanı azaltır; dizini güvenli kılmaz. Onu güvenli kılan şey, dosyanın ne çıkacağı fark etmeksizin web sunucusunun orada hiçbir şeyi ÇALIŞTIRMAYI reddetmesidir.

Nginx

location ^~ /uploads/ {
    location ~ \.php$ { deny all; }
    add_header X-Content-Type-Options nosniff;
}

Apache ve LiteSpeed

# /var/www/site/uploads/.htaccess
php_flag engine off
<FilesMatch "\.(php|phar|phtml|cgi|pl)$">
    Require all denied
</FilesMatch>
Options -ExecCGI -Indexes

Ayrıca doğrulayın, gereğince

  • Bir tarayıcının gönderdiği ada değil, gerçek türe bakın: PHP'de finfo_file().
  • Her yüklemeyi kendi ürettiğiniz bir adla yeniden adlandırın. Ziyaretçinin dosya adını asla korumayın.
  • Çift uzantıları reddedin - invoice.php.jpg adlı bir dosya rastlantı değildir.
  • Görselleri yeniden kodlayın. Bir resmi bir görsel kitaplığından geçirmek, içine gizlenmiş her şeyi söker.
$f = new finfo(FILEINFO_MIME_TYPE);
$type = $f->file($tmp);
if (!in_array($type, ['image/jpeg','image/png','image/webp'], true)) {
    // reject
}
$name = bin2hex(random_bytes(16)) . '.webp';

Daha da iyisi, onları ağın ulaşamadığı bir yerde saklayın

Yüklemeleri belge kökünün dışında tutun ve kimin istediğine bakan bir betik üzerinden sunun. Bir milisaniye daha yavaştır, ve o zaman hiçbir şeyi çalıştırabilecek bir adres kalmaz.

Onu sınayın. Yükleme dizinine kendi elinizle zararsız bir PHP dosyası koyun ve onu isteyin: 403 ya da kaynak metni almalısınız, çıktıyı asla. Bu bir dakika sürer ve tek kanıt budur.