File Upload Security در وردپرس چرا نادیده گرفته می‌شود؟ File Upload Security (امنیت آپلود فایل) مجموعه اقداماتی است که از سایت در برابر آپلود فایل‌های مخرب، اجرای کد از راه دور، و نفوذ از طریق فایل‌های آلوده محافظت می‌کند. در بستر وردپرس، این موضوع از اهمیت بالایی برخوردار است، زیرا قابلیت آپلود فایل در هسته، افزونه‌ها، و قالب‌ها به‌طور گسترده استفاده می‌شود. برخلاف آنچه تصور می‌شود، وردپرس به‌طور پیش‌فرض محافظت جامعی در این زمینه ندارد و بسیاری از آسیب‌پذیری‌ها از همین نقطه وارد می‌شوند. تهدیدات اصلی شامل آپلود shell PHP، حمله double extension (مانند image.jpg.php)، سوءاستفاده از MIME Type، و اجرای فایل‌های SVG آلوده است. پیامدهای موفقیت این حمله می‌تواند از اجرای کد دلخواه و نصب backdoor تا نفوذ کامل به سرور متغیر باشد. دفاع اصلی شامل اعتبارسنجی نوع MIME، بررسی محتوای فایل، محدودسازی پسوندهای مجاز، غیرفعال‌سازی اجرای PHP در پوشه uploads، و استفاده از کتابخانه‌های امن است. چالش اصلی این است که بسیاری از توسعه‌دهندگان، آپلود فایل را یک قابلیت ساده می‌دانند و ابعاد امنیتی آن را نادیده می‌گیرند. در این نوشتار، از ریشه‌های فنی آسیب‌پذیری آپلود فایل تا پیاده‌سازی حرفه‌ای و نکات پیشرفته را بررسی می‌کنیم.

نخستین‌باری که با یک حمله از طریق آپلود فایل روبه‌رو شدم، در یک پروژه بود که در آن یک افزونه فرم‌ساز، فایل‌های آپلودی را در پوشه uploads ذخیره می‌کرد و اجرای PHP در آن پوشه فعال بود. مهاجم می‌توانست با آپلود یک shell PHP ساده، کنترل کامل سایت را به دست بگیرد. از آن زمان، File Upload Security به یکی از موضوعات اصلی من در بازبینی امنیتی تبدیل شده است. در این نوشتار، تجربه‌های عملی را با شما به اشتراک می‌گذارم.

File Upload Security چیست و چه مسئله‌ای را حل می‌کند؟

File Upload Security (امنیت آپلود فایل) مجموعه اقداماتی است که از سایت در برابر آپلود فایل‌های مخرب محافظت می‌کند. این موضوع در دسته «Unrestricted File Upload» در OWASP Top 10 قرار می‌گیرد و از نظر شدت، در سطح بالا طبقه‌بندی می‌شود. حمله آپلود فایل می‌تواند به اجرای کد، نفوذ کامل، و آلودگی سرور منجر شود.

مسئله اصلی که File Upload Security حل می‌کند، اعتماد به ورودی کاربر در قالب فایل است. برخلاف متن که می‌توان آن را پاک‌سازی کرد، فایل می‌تواند کد اجرایی، اسکریپت مخرب، یا payload‌های پیچیده داشته باشد. همین ویژگی، آپلود فایل را به یک سطح حمله جدی تبدیل می‌کند. برای درک عمیق‌تر، انواع آسیب‌پذیری‌های رایج وب را ببینید.

سه ویژگی کلیدی امنیت آپلود:

  • اعتبارسنجی نوع فایل: بررسی MIME Type و پسوند.
  • بررسی محتوا: اطمینان از اینکه فایل واقعاً همان چیزی است که ادعا می‌کند.
  • ذخیره‌سازی امن: جداسازی فایل‌ها از کد اجرایی.
  • محدودسازی دسترسی: اجرای PHP در پوشه uploads غیرفعال شود.

برای درک عمیق‌تر اصول امنیتی، اصول امنیت وب را ببینید.

هر فایل آپلودی، یک «بسته ناشناخته» است: تا زمانی که محتوای آن بررسی نشود، نمی‌توان به آن اعتماد کرد. آپلود فایل بدون اعتبارسنجی، یک درِ باز برای مهاجم است.

چرا امنیت آپلود فایل در وردپرس نادیده گرفته می‌شود؟

در بازبینی ده‌ها پروژه وردپرسی، چند دلیل اصلی برای نادیده گرفتن File Upload Security دیده‌ام:

  • تصور سادگی: بسیاری از توسعه‌دهندگان آپلود فایل را یک قابلیت ساده می‌دانند.
  • اتکای صرف به توابع وردپرس: wp_handle_upload() محافظت‌های خوبی دارد اما کامل نیست.
  • نادیده گرفتن MIME Type: فقط پسوند بررسی می‌شود و MIME نادیده گرفته می‌شود.
  • فعال بودن اجرای PHP در uploads: در برخی هاست‌ها این پوشه قابل اجرا است.
  • اعتماد به افزونه‌های شخص‌ثالث: بسیاری از افزونه‌ها امنیت آپلود را رعایت نمی‌کنند.
  • عدم درک حمله double extension: فایل image.jpg.php توسط برخی سرورها به‌عنوان PHP اجرا می‌شود.
  • نادیده گرفتن SVG: SVG می‌تواند حاوی JavaScript باشد.
  • عدم محدودسازی اندازه: آپلود فایل‌های بزرگ می‌تواند DoS ایجاد کند.

نکته مهم این است که وردپرس هسته از توابع امن مانند wp_check_filetype_and_ext() استفاده می‌کند، اما این محافظت به‌طور خودکار به افزونه‌ها و قالب‌های شخص‌ثالث منتقل نمی‌شود. برای درک عمیق‌تر ساختار افزونه، ساختار استاندارد افزونه وردپرس را ببینید.

تهدیدات رایج در آپلود فایل

چند تهدید رایج در آپلود فایل وجود دارد که هر توسعه‌دهنده باید بشناسد:

تهدیدروشپیامد
آپلود shell PHPفایل .php با کد مخرباجرای کد، نفوذ کامل
Double Extensionفایل image.jpg.phpاجرا در برخی سرورها
MIME SpoofingMIME جعلیدور زدن بررسی نوع
SVG آلودهSVG با JavaScriptXSS در مرورگر
Path Traversalنام فایل شامل ../ذخیره در مسیر غیرمجاز
Null Byteimage.jpg%00.phpدور زدن پسوند
Zip Bombفایل زیپ فشرده بزرگDoS سرور

هر کدام از این تهدیدات، نیازمند دفاع مشخصی است. برای درک عمیق‌تر، حمله تزریق کد را ببینید.

محافظت‌های پیش‌فرض وردپرس

وردپرس به‌طور پیش‌فرض چند محافظت در آپلود فایل فراهم می‌کند:

  • توابع امن: wp_handle_upload() و media_handle_upload() اعتبارسنجی انجام می‌دهند.
  • لیست پسوندهای مجاز: بر اساس MIME Type مجاز.
  • ذخیره‌سازی در پوشه uploads: به‌طور پیش‌فرض، فقط فایل‌های رسانه‌ای در آن ذخیره می‌شوند.
  • بررسی دسترسی: فقط کاربران مجاز می‌توانند آپلود کنند.
  • حذف فایل‌های اجرایی: وردپرس فایل‌های .php را در آپلود رد می‌کند.

اما این محافظت‌ها کامل نیستند. به‌طور مثال، وردپرس فایل .php را رد می‌کند اما فایل .phtml یا .php5 ممکن است پذیرفته شوند. همچنین، وردپرس محتوای فایل را بررسی نمی‌کند و یک تصویر آلوده به PHP ممکن است پذیرفته شود. برای درک عمیق‌تر، امنیت وردپرس را ببینید.

اعتبارسنجی نوع MIME

اعتبارسنجی نوع MIME (Multipurpose Internet Mail Extensions) یکی از لایه‌های اصلی دفاع است. MIME Type نشان می‌دهد فایل از چه نوعی است. اما این نوع می‌تواند جعل شود، بنابراین نباید به آن به‌تنهایی اعتماد کرد.

یک نمونه اعتبارسنجی:

$allowed_mimes = [
    'jpg|jpeg|jpe' => 'image/jpeg',
    'png' => 'image/png',
    'gif' => 'image/gif',
    'pdf' => 'application/pdf',
];

$file_type = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $allowed_mimes );
if ( ! $file_type['ext'] || ! $file_type['type'] ) {
    wp_die( 'نوع فایل مجاز نیست' );
}

تابع wp_check_filetype_and_ext() هم پسوند و هم MIME واقعی را بررسی می‌کند و امن‌ترین گزینه در وردپرس است. برای درک عمیق‌تر، نوشتن کد PHP امن برای وردپرس را ببینید.

محدودسازی پسوندها

محدودسازی پسوندهای مجاز، یک لایه دفاعی ساده اما مؤثر است. لیست پسوندهای خطرناک:

  • .php, .php3, .php4, .php5, .php7, .phtml
  • .pl, .py, .cgi, .asp, .aspx, .jsp
  • .sh, .bash, .exe, .dll, .com
  • .htaccess, .htpasswd
  • .svg (اگر با احتیاط مدیریت نشود)

یک نمونه لیست سفید:

add_filter( 'upload_mimes', function( $mimes ) {
    return [
        'jpg|jpeg|jpe' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
        'pdf' => 'application/pdf',
    ];
} );

این رویکرد، همه پسوندهای دیگر را رد می‌کند. برای درک عمیق‌تر، خطای دسترسی به فایل‌ها را ببینید.

بررسی محتوای فایل

اعتبارسنجی MIME و پسوند کافی نیست، زیرا مهاجم می‌تواند یک فایل PHP را با پسوند .jpg و MIME image/jpeg آپلود کند. برای دفاع، باید محتوای فایل بررسی شود:

$content = file_get_contents( $file['tmp_name'] );
if ( strpos( $content, '<?php' ) !== false ) {
    wp_die( 'فایل حاوی کد PHP است' );
}

// بررسی header تصویر
$image_info = getimagesize( $file['tmp_name'] );
if ( $image_info === false ) {
    wp_die( 'فایل تصویر معتبر نیست' );
}

تابع getimagesize() بررسی می‌کند که فایل واقعاً یک تصویر معتبر است. برای درک عمیق‌تر، خطای آپلود فایل در وردپرس را ببینید.

غیرفعال‌سازی اجرای PHP در پوشه uploads

یکی از مهم‌ترین لایه‌های دفاعی، غیرفعال‌سازی اجرای PHP در پوشه wp-content/uploads است. اگر مهاجم بتواند یک فایل PHP را آپلود کند، این تنظیم از اجرای آن جلوگیری می‌کند.

در Apache

# در فایل wp-content/uploads/.htaccess
<FilesMatch "\.php$">
    Require all denied
</FilesMatch>

# یا
<Files ".php">
    Order Deny,Allow
    Deny from all
</Files>

در Nginx

location ~* /wp-content/uploads/.*\.php$ {
    deny all;
    return 403;
}

این تنظیم، حتی اگر فایل PHP در پوشه uploads ذخیره شود، از اجرای آن جلوگیری می‌کند. برای درک عمیق‌تر، افزایش امنیت سرور را ببینید.

خطر SVG و نحوه امن‌سازی

SVG (Scalable Vector Graphics) یک فرمت تصویری است که می‌تواند شامل JavaScript باشد. آپلود SVG بدون پاک‌سازی، می‌تواند به XSS (Cross-Site Scripting - اسکریپت‌نویسی میان‌سایتی) منجر شود. دو رویکرد برای مدیریت SVG:

  • غیرفعال‌سازی کامل: SVG را از لیست پسوندهای مجاز حذف کنید.
  • پاک‌سازی محتوا: با کتابخانه‌هایی مانند DOMPurify یا SVG-Sanitizer.

یک نمونه پاک‌سازی:

function sanitize_svg( $file_path ) {
    $content = file_get_contents( $file_path );
    $content = preg_replace( '#<script[^>]*>.*?</script>#is', '', $content );
    $content = preg_replace( '#on\w+\s*=\s*"[^"]*"#i', '', $content );
    file_put_contents( $file_path, $content );
}

برای درک عمیق‌تر، راهنمای پیشگیری از حملات XSS را ببینید.

پیاده‌سازی حرفه‌ای امنیت آپلود

یک پیاده‌سازی حرفه‌ای شامل چند لایه است:

function myplugin_handle_upload( $file ) {
    // 1. بررسی اندازه
    $max_size = 5 * 1024 * 1024; // 5MB
    if ( $file['size'] > $max_size ) {
        return new WP_Error( 'too_large', 'فایل بزرگ‌تر از حد مجاز است' );
    }
    
    // 2. بررسی MIME و پسوند
    $allowed = [
        'jpg|jpeg|jpe' => 'image/jpeg',
        'png' => 'image/png',
        'pdf' => 'application/pdf',
    ];
    $check = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $allowed );
    if ( ! $check['ext'] || ! $check['type'] ) {
        return new WP_Error( 'invalid_type', 'نوع فایل مجاز نیست' );
    }
    
    // 3. بررسی محتوا (برای تصاویر)
    if ( strpos( $check['type'], 'image/' ) === 0 ) {
        if ( getimagesize( $file['tmp_name'] ) === false ) {
            return new WP_Error( 'invalid_image', 'تصویر معتبر نیست' );
        }
    }
    
    // 4. بررسی نام فایل
    if ( preg_match( '/[^a-zA-Z0-9._-]/', $file['name'] ) ) {
        return new WP_Error( 'invalid_name', 'نام فایل نامعتبر است' );
    }
    
    // 5. ذخیره امن
    return wp_handle_upload( $file, ['test_form' => false] );
}

این الگو، چند لایه دفاعی را ترکیب می‌کند و احتمال موفقیت حمله را به حداقل می‌رساند. برای درک عمیق‌تر، نوشتن کد PHP امن را ببینید.

اشتباهات رایج در امنیت آپلود فایل

  • اتکای صرف به پسوند: مهاجم می‌تواند پسوند را جعل کند.
  • اتکای صرف به MIME: MIME قابل جعل است.
  • فعال بودن اجرای PHP در uploads: خطای پیکربندی سرور.
  • نادیده گرفتن محتوا: بررسی نکردن header فایل.
  • محدودسازی نکردن اندازه: DoS با فایل بزرگ.
  • نادیده گرفتن SVG: SVG می‌تواند JavaScript داشته باشد.
  • اعتماد به نام فایل: نام فایل باید پاک‌سازی شود.
  • عدم استفاده از wp_check_filetype_and_ext: استفاده از توابع ضعیف‌تر.
  • نادیده گرفتن path traversal: نام فایل شامل ../.
  • ذخیره فایل با مجوز اجرایی: مجوز باید ۶۴۴ باشد، نه ۷۵۵.
  • عدم استفاده از HTTPS: فایل در مسیر افشا می‌شود.
  • نادیده گرفتن backdoor در فایل تصویر: ترکیب تصویر و PHP.

برای مرور خطاهای مشابه، اشتباهات امنیتی رایج در وردپرس را ببینید.

پرسش‌های پرتکرار درباره File Upload Security

File Upload Security چیست و چرا مهم است؟ مجموعه اقدامات برای محافظت از سایت در برابر آپلود فایل‌های مخرب. در صورت نادیده گرفتن، می‌تواند به اجرای کد و نفوذ کامل منجر شود.

وردپرس به‌طور پیش‌فرض آپلود فایل را امن می‌کند؟ وردپرس محافظت‌های خوبی دارد، اما کامل نیست. برای امنیت حداکثری، باید لایه‌های اضافی اضافه کنید.

چطور اجرای PHP در پوشه uploads را غیرفعال کنم؟ با .htaccess در Apache یا location در Nginx. برای مراحل کامل، افزایش امنیت سرور را ببینید.

آیا SVG امن است؟ نه به‌طور پیش‌فرض. SVG می‌تواند JavaScript داشته باشد و باید پاک‌سازی شود.

چطور فایل PHP را با پسوند JPG شناسایی کنم؟ با بررسی محتوا با getimagesize() یا جست‌وجوی <?php در محتوا.

آیا افزونه‌های امنیتی آپلود را امن می‌کنند؟ برخی افزونه‌ها مانند Wordfence لایه‌های محافظتی دارند، اما دفاع اصلی باید در کد باشد. برای مرور گزینه‌ها، بهترین افزونه‌های امنیتی وردپرس را ببینید.

آیا محدود کردن اندازه فایل کافی است؟ نه، اندازه فقط یک لایه است. باید MIME، محتوا، و پسوند را هم بررسی کنید.

چطور فایل آپلودی را در پوشه غیرقابل دسترس ذخیره کنم؟ با ذخیره در پوشه خارج از public_html یا استفاده از Content-Disposition: attachment.

برای مطالعه بیشتر درباره امنیت آپلود، صفحه File upload vulnerability در ویکی‌پدیا مفید است.

خط پایان

File Upload Security در وردپرس یکی از آن لایه‌های امنیتی است که در سایه XSS و SQL Injection کمتر دیده می‌شود، اما پیامدهای آن می‌تواند از اجرای کد تا نفوذ کامل به سرور متغیر باشد. در بستر وردپرس، آپلود فایل در هسته، افزونه‌ها، و قالب‌ها به‌طور گسترده استفاده می‌شود و همین سطح حمله را بزرگ می‌کند. دفاع مؤثر نیازمند چند لایه است: اعتبارسنجی MIME، بررسی محتوا، محدودسازی پسوند، غیرفعال‌سازی اجرای PHP در uploads، و پاک‌سازی SVG. اگر سایت شما فرم آپلود دارد یا افزونه‌ای با این قابلیت نصب کرده‌اید، همین امروز بازبینی کنید.

اگر در پروژه‌ای با حمله از طریق آپلود فایل روبه‌رو شده‌اید یا راهکار دفاعی متفاوتی پیاده کرده‌اید، تجربه خود را در دیدگاه‌ها بنویسید؛ به‌خصوص اگر افزونه یا روش خاصی برای امن‌سازی استفاده کرده‌اید، این اطلاعات برای خواننده بعدی بسیار ارزشمند است.