نموذجُ رفعٍ يقبل الصور سبيلٌ لوضع ملفٍّ على خادمك. والتحقّقُ يقلّل ما يمرّ، ولا يجعل الدليلَ آمنًا. والذي يجعله آمنًا أن يرفض خادمُ الوِب تنفيذَ أيّ شيءٍ هناك، مهما تبيّن أنّ الملفّ.
Nginx
location ^~ /uploads/ {
location ~ \.php$ { deny all; }
add_header X-Content-Type-Options nosniff;
}
Apache وLiteSpeed
# /var/www/site/uploads/.htaccess
php_flag engine off
<FilesMatch "\.(php|phar|phtml|cgi|pl)$">
Require all denied
</FilesMatch>
Options -ExecCGI -Indexes
وتحقّق كذلك، كما ينبغي
- افحص النوع الحقيقيّ لا الاسم الذي أرسله متصفّح:
finfo_file()في PHP. - وأعد تسمية كلّ رفعةٍ إلى اسمٍ ولّدته أنت. ولا تُبقِ اسمَ ملفّ الزائر أبدًا.
- وارفض الامتدادات المزدوجة — فملفٌّ اسمه invoice.php.jpg ليس مصادفة.
- وأعد ترميز الصور. فتمريرُ صورةٍ عبر مكتبة صورٍ ينزع ما خُبّئ فيها.
$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';
والأفضل أن تخزّنها حيث لا تبلغه الوِب
أبقِ الرفوعات خارج جذر المستندات وقدّمها عبر سكربتٍ يفحص من السائل. أبطأُ بجزءٍ من الألف، ولا يبقى عندئذٍ عنوانٌ يستطيع تشغيل شيء.
واختبره. ضع بنفسك ملفَّ PHP غيرَ مؤذٍ في دليل الرفع واطلبه: يجب أن تنال 403 أو نصَّ المصدر، لا الخرجَ أبدًا. وهذا يأخذ دقيقةً وهو الدليلُ الوحيد.