آموزش جامع اعتبارسنجی حجم و نوع فایل آپلودی در PHP طبق استانداردهای امنیتی گوگل
چرا امنیت آپلود فایل تا این حد حیاتی است؟
یکی از بزرگترین آسیبپذیریهای امنیتی در وبسایتها، آپلود فایلهای مخرب (مانند شلهای PHP یا کدهای مخرب جاوا اسکریپت) است. بر اساس راهنماهای امنیتی گوگل و استانداردهای جهانی OWASP، هرگز نباید به دادههای ارسالی از سمت مرورگر (مانند نام فایل یا پسوند فرستاده شده) اعتماد کرد. هکرها به سادگی میتوانند نوع فایل ارسالی در هدر درخواست را دستکاری کنند. بنابراین، اعتبارسنجی در سمت سرور (Back-end) تنها راه نجات است.
سه قانون طلایی گوگل در اعتبارسنجی فایلها
گوگل در مستندات امنیتی خود سه نکته کلیدی را برای فرآیند آپلود فایل پیشنهاد میکند:
- بررسی هویت واقعی فایل (MIME Type): نوع واقعی فایل باید با خواندن بایتهای جادویی (Magic Bytes) درون محتوای فایل مشخص شود، نه از روی نام یا پسوند فایل.
- اعمال محدودیتهای سختگیرانه برای حجم فایل: جلوگیری از حملات DoS (محرومسازی از سرویس) با رد کردن فایلهای حجیم پیش از پردازش سنگین در سرور.
- ذخیرهسازی امن: تغییر نام فایلها با استفاده از الگوریتمهای هش و ذخیره آنها در پوشهای غیرقابل اجرا (Non-executable).
گام اول: پیکربندی امن سرور در php.ini
پیش از نوشتن هر کدی، باید مطئمن شوید که تنظیمات پیشفرض PHP پذیرای حجم مدنظر شما هستند. فایل php.ini خود را بررسی و مقادیر زیر را متناسب با نیازتان تنظیم کنید:
upload_max_filesize = 2M
post_max_size = 8M
memory_limit = 128M
گام دوم: بررسی حجم فایل در سمت سرور
اولین لایه دفاعی، بررسی حجم فایل ارسال شده است. ما باید سایز فایل را با مقدار مجاز خود مقایسه کنیم. به نمونه کد زیر دقت کنید:
// حداکثر حجم مجاز: 2 مگابایت
$max_file_size = 2 * 1024 * 1024;
if ($_FILES['uploaded_file']['size'] --> $max_file_size) {
die("خطا: حجم فایل ارسالی بیشتر از حد مجاز (2 مگابایت) است.");
}
گام سوم: اعتبارسنجی امن نوع فایل (MIME Type) با finfo
بسیاری از برنامهنویسان تازه کار از $_FILES['uploaded_file']['type'] استفاده میکنند که یک فاجعه امنیتی است! این فیلد مستقیماً توسط مرورگر کلاینت ارسال شده و به سادگی قابل جعل است. راهکار استاندارد گوگل، استفاده از افزونه داخلی Fileinfo در PHP برای خواندن بایتهای امضای فایل است:
// نمونه کد اعتبارسنجی واقعی نوع فایل
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
$file_tmp = $_FILES['uploaded_file']['tmp_name'];
// ایجاد یک شیء finfo
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$real_mime_type = finfo_file($finfo, $file_tmp);
finfo_close($finfo);
if (!in_array($real_mime_type, $allowed_types)) {
die("خطا: نوع فایل نامعتبر است. تنها فرمتهای JPG، PNG و GIF مجاز هستند.");
}
گام چهارم: بررسی و پاکسازی پسوند فایل (Extension White-listing)
علاوه بر MIME Type، باید بررسی کنیم که پسوند فایل نیز جزو لیست سفید ما باشد. استفاده از لیست سیاه خطرناک است؛ زیرا ممکن است برخی پسوندهای اجرایی مانند phtml, php5 یا exe را فراموش کنید. همیشه از رویکرد لیست سفید (White-list) استفاده کنید:
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif'];
$file_name = $_FILES['uploaded_file']['name'];
// استخراج پسوند فایل
$file_extension = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
if (!in_array($file_extension, $allowed_extensions)) {
die("خطا: پسوند فایل مجاز نیست.");
}
گام پنجم: تغییر نام فایل به شیوه امن
برای جلوگیری از حملات Directory Traversal (پیمایش دایرکتوری) و اوررایت شدن فایلهای همنام، نام اصلی فایل را حذف کرده و یک نام تصادفی و منحصربهفرد تولید کنید:
$upload_dir = 'uploads/';
// تولید یک نام رندوم هش شده به همراه پسوند اصلی
$new_file_name = md5(uniqid(rand(), true)) . '.' . $file_extension;
$destination = $upload_dir . $new_file_name;
if (move_uploaded_file($file_tmp, $destination)) {
echo "فایل شما با موفقیت و به صورت امن آپلود شد!";
} else {
echo "خطا در ذخیرهسازی فایل.";
}
نتیجهگیری استاندارد امنیتی گوگل
با ترکیب سه لایه دفاعی بالا یعنی کنترل دقیق حجم فایل، بررسی بایتهای جادویی با finfo، و تغییر نام تصادفی فایل، ضریب امنیت وبسایت شما طبق موازین و استانداردهای موتورهای جستجو و گوگل به حداکثر خود میرسد. همیشه به یاد داشته باشید که امنیت یک فرآیند مستمر است و باید مداوم بهروزرسانی شود.
پرسش و پاسخ
نظری یافت نشد
برای ارسال نظر ابتدا وارد شوید