Path Traversal Prevention در وردپرس (پیشگیری از پیمایش مسیر) چطور انجام می‌شود؟ Path Traversal (پیمایش مسیر) که با نام‌های Directory Traversal (پیمایش پوشه) یا Dot-Dot-Slash نیز شناخته می‌شود، نوعی آسیب‌پذیری است که در آن مهاجم با استفاده از توالی‌هایی مانند ../ سعی می‌کند از پوشه مجاز خارج شود و به فایل‌های حساس سرور دسترسی پیدا کند. در بستر وردپرس، این آسیب‌پذیری از چند مسیر وارد می‌شود: افزونه‌هایی که مسیر فایل را از ورودی کاربر می‌خوانند، قالب‌هایی که فایل‌های پیکربندی را بارگذاری می‌کنند، endpointهای دانلود فایل که نام فایل را از URL می‌گیرند، و افزونه‌های آپلود که مسیر مقصد را از پارامتر دریافت می‌کنند. پیامدهای موفقیت این حمله می‌تواند از خواندن wp-config.php و نشت اعتبارنامه دیتابیس تا دسترسی به فایل‌های سیستمی مانند /etc/passwd و در نهایت اجرای کد از راه دور متغیر باشد. دفاع اصلی شامل اعتبارسنجی سختگیرانه مسیر، استفاده از whitelist برای فایل‌های مجاز، ترکیب realpath() با بررسی prefix، حذف کاراکترهای خطرناک مانند ../، و غیرفعال‌سازی نمایش لیست پوشه‌ها است. چالش اصلی این است که بسیاری از توسعه‌دهندگان Path Traversal را با File Inclusion (تزریق فایل) اشتباه می‌گیرند، در حالی که تفاوت بنیادین در این است که در Path Traversal فقط فایل خوانده می‌شود، اما در File Inclusion فایل اجرا می‌گردد. در این نوشتار، از ریشه‌های فنی این آسیب‌پذیری تا پیاده‌سازی حرفه‌ای دفاع را بررسی می‌کنیم.

نخستین‌باری که با Path Traversal روبه‌رو شدم، در یک افزونه دانلود فایل بود که نام فایل را مستقیماً از URL می‌گرفت. مهاجم می‌توانست با ارسال ?file=../../../wp-config.php، محتوای فایل پیکربندی را ببیند و اعتبارنامه دیتابیس را استخراج کند. از آن زمان، Path Traversal را به‌عنوان یک تهدید جدی در همه پروژه‌های وردپرسی در نظر می‌گیرم. این نوشتار، حاصل تجربه عملی در پیاده‌سازی دفاع در ده‌ها پروژه است.

Path Traversal چیست و چرا خطرناک است؟

Path Traversal (پیمایش مسیر) که با نام‌های Directory Traversal (پیمایش پوشه)، Dot-Dot-Slash، و Backtracking نیز شناخته می‌شود، نوعی آسیب‌پذیری است که در آن مهاجم با استفاده از توالی‌های خاص در مسیر فایل، از پوشه مجاز خارج می‌شود و به فایل‌های حساس سرور دسترسی پیدا می‌کند. این آسیب‌پذیری در OWASP Top 10 در دسته «Broken Access Control» قرار می‌گیرد و از نظر شدت، در سطح بالا طبقه‌بندی می‌شود.

مسئله اصلی که Path Traversal ایجاد می‌کند، شکستن مرز میان پوشه مجاز و پوشه غیرمجاز است. وقتی یک برنامه به‌جای استفاده از مسیر مطلق و ثابت، مسیر را از ورودی کاربر می‌سازد، مهاجم می‌تواند با توالی‌هایی مانند ../ از پوشه هدف خارج شود. برای درک عمیق‌تر جایگاه این آسیب‌پذیری در دسته‌بندی کلی، انواع آسیب‌پذیری‌های رایج وب را ببینید.

سه ویژگی کلیدی این آسیب‌پذیری:

  • سادگی اجرا: فقط با توالی ../ در URL یا پارامتر.
  • عدم نیاز به احراز هویت: در بسیاری از موارد، بدون لاگین قابل اجرا است.
  • عدم ثبت در لاگ‌ها: درخواست شبیه درخواست عادی به‌نظر می‌رسد.
  • پیامد سنگین: دسترسی به فایل‌های حساس و در نهایت نفوذ کامل.

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

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

تفاوت Path Traversal و File Inclusion

بسیاری از توسعه‌دهندگان Path Traversal و File Inclusion را با هم اشتباه می‌گیرند، در حالی که این دو آسیب‌پذیری متفاوت‌اند:

ویژگیPath TraversalFile Inclusion
هدفخواندن فایلاجرای فایل
توابع درگیرfile_get_contents, readfileinclude, require
نیاز به اجرای PHPخیربله (LFI) یا منبع خارجی (RFI)
سطح خطرخواندن فایل حساساجرای کد دلخواه
روش دفاعاعتبارسنجی مسیرwhitelist و غیرفعال‌سازی allow_url_include

نکته مهم این است که Path Traversal می‌تواند به File Inclusion منجر شود، اگر مهاجم بتواند فایل اجرایی را از مسیر غیرمجاز بارگذاری کند. برای درک عمیق‌تر، File Inclusion Prevention در وردپرس را ببینید.

مسیرهای ورود Path Traversal در وردپرس

وردپرس در چندین نقطه از مسیر فایل پویا استفاده می‌کند. هر یک از این نقاط، یک سطح حمله بالقوه است:

  • افزونه‌های دانلود فایل: نام فایل از URL خوانده می‌شود.
  • افزونه‌های گالری: بارگذاری تصویر بر اساس پارامتر مسیر.
  • افزونه‌های قالب: بارگذاری فایل قالب بر اساس ورودی.
  • افزونه‌های پشتیبان‌گیری: ذخیره بکاپ در مسیر دریافت‌شده از کاربر.
  • افزونه‌های آپلود: ذخیره فایل در مسیر دلخواه.
  • قالب‌های سفارشی: استفاده از include با مسیر پویا.
  • کرون‌ها و WP-CLI: بارگذاری فایل پیکربندی از پارامتر.

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

مکانیزم فنی حمله Path Traversal

یک payload ساده Path Traversal برای خواندن فایل /etc/passwd:

https://victim.com/download.php?file=../../../../etc/passwd

اگر کد به این شکل باشد:

$file = $_GET['file'];
readfile( '/var/www/uploads/' . $file );

مهاجم می‌تواند با ../../../etc/passwd از پوشه uploads خارج شود و فایل سیستمی را بخواند. برای فایل wp-config.php:

https://victim.com/download.php?file=../../../wp-config.php

نوع پیشرفته‌تر، استفاده از encoding برای دور زدن فیلترها:

..%2f..%2f..%2fetc%2fpasswd
%2e%2e%2f%2e%2e%2fetc%2fpasswd
....//....//....//etc/passwd

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

روی Windows

در سرورهای Windows، مهاجم می‌تواند از ..\ یا ../ استفاده کند و به فایل‌هایی مانند C:\Windows\System32\config\SAM دسترسی پیدا کند. برای درک عمیق‌تر، تفاوت سرور لینوکس و ویندوز را ببینید.

پیامدهای واقعی در پروژه‌های وردپرسی

سطحپیامد
نشت فایل پیکربندیخواندن wp-config.php و اعتبارنامه دیتابیس
نشت فایل سیستمیخواندن /etc/passwd، /etc/shadow
نفوذ کاملدسترسی به کلیدهای SSH، توکن‌های API
اجرای کدترکیب با File Inclusion
افشای داده کاربراندسترسی به فایل‌های آپلودی دیگران

در پروژه‌ای که بررسی کردیم، یک افزونه دانلود فایل، نام فایل را از URL می‌گرفت و هیچ اعتبارسنجی نداشت. مهاجم می‌توانست با ?file=../../../wp-config.php، محتوای فایل پیکربندی را ببیند و اعتبارنامه دیتابیس را استخراج کند. برای مرور آسیب‌پذیری‌های مشابه در افزونه‌ها، آسیب‌پذیری افزونه‌های وردپرس را ببینید.

دفاع مؤثر در برابر Path Traversal

دفاع در چند لایه انجام می‌شود. هیچ لایه‌ای به‌تنهایی کافی نیست.

لایه ۱: حذف کاراکترهای خطرناک

$file = str_replace( ['..', '\\', '/'], '', $file );
// یا
$file = basename( $file );

تابع basename() فقط نام فایل را برمی‌گرداند و مسیر را حذف می‌کند. این تابع، ساده‌ترین و مؤثرترین دفاع در برابر Path Traversal است. برای درک عمیق‌تر، نوشتن کد PHP امن برای وردپرس را ببینید.

لایه ۲: اعتبارسنجی با whitelist

$allowed = ['report.pdf', 'invoice.pdf', 'terms.pdf'];
$file = basename( $_GET['file'] );
if ( ! in_array( $file, $allowed, true ) ) {
    wp_die( 'فایل نامعتبر' );
}
$path = WP_CONTENT_DIR . '/uploads/' . $file;

این الگو، مطمئن‌ترین روش است. حتی اگر مهاجم بتواند مسیر را دستکاری کند، فقط فایل‌های مجاز بارگذاری می‌شوند.

لایه ۳: ترکیب realpath با بررسی prefix

$base_dir = realpath( WP_CONTENT_DIR . '/uploads' );
$requested = realpath( $base_dir . '/' . basename( $_GET['file'] ) );

if ( $requested === false || strpos( $requested, $base_dir ) !== 0 ) {
    wp_die( 'دسترسی غیرمجاز' );
}
readfile( $requested );

این ترکیب، از خروج از پوشه مجاز جلوگیری می‌کند، حتی در برابر symlink.

نقش realpath و بررسی prefix

تابع realpath() یک مسیر را به مسیر مطلق و واقعی تبدیل می‌کند و symlinkها را حل می‌کند. اما این تابع به‌تنهایی کافی نیست، زیرا مسیر ../../../etc/passwd را به /etc/passwd تبدیل می‌کند. برای دفاع، باید نتیجه را با prefix پوشه مجاز بررسی کنید:

$base = realpath( '/var/www/uploads' ); // /var/www/uploads
$target = realpath( '/var/www/uploads/../../../etc/passwd' ); // /etc/passwd

if ( strpos( $target, $base ) !== 0 ) {
    // رد دسترسی
}

نکته مهم: باید از strpos() با مقدار 0 استفاده کنید، نه strpos() !== false. زیرا در حالت دوم، مسیر /var/www/uploads-other هم پذیرفته می‌شود. برای درک عمیق‌تر ساختار پوشه، فایل‌های ضروری قالب وردپرس را ببینید.

الگوی whitelist در مسیر فایل

الگوی whitelist را می‌توان در همه جا پیاده کرد:

function myplugin_safe_read( $key ) {
    $map = [
        'invoice' => WP_CONTENT_DIR . '/uploads/invoices/',
        'report' => WP_CONTENT_DIR . '/uploads/reports/',
    ];
    if ( ! isset( $map[ $key ] ) ) {
        return false;
    }
    return $map[ $key ];
}

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

دفاع در سطح وب‌سرور

علاوه بر دفاع در سطح کد، می‌توان در سطح وب‌سرور هم محافظت اضافه کرد:

در Apache

# غیرفعال‌سازی نمایش لیست پوشه
Options -Indexes

# محدودسازی دسترسی به فایل‌های حساس
<FilesMatch "^(wp-config\.php|\.htaccess|\.htpasswd)$">
    Require all denied
</FilesMatch>

در Nginx

location ~ /\.ht {
    deny all;
}

location ~* /(wp-config\.php|\.env)$ {
    deny all;
}

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

اشتباهات رایج در دفع Path Traversal

  • اتکای صرف به حذف ../: مهاجم از encoding استفاده می‌کند.
  • استفاده از str_replace بدون حلقه: ....// بعد از یک بار حذف به ../ تبدیل می‌شود.
  • اتکای صرف به realpath(): باید با prefix بررسی شود.
  • استفاده از strpos() !== false: باید strpos() !== 0 باشد.
  • نادیده گرفتن symlink: realpath() آن را حل می‌کند، اما باید بررسی شود.
  • اعتماد به basename() به‌تنهایی: در برخی سیستم‌ها، basename() کاراکترهای خاص را حذف نمی‌کند.
  • نادیده گرفتن Windows path: ..\ و ../ هر دو باید بررسی شوند.
  • عدم غیرفعال‌سازی نمایش لیست پوشه: مهاجم می‌تواند ساختار پوشه را ببیند.
  • اعتماد به افزونه‌های شخص‌ثالث: بسیاری از افزونه‌ها Path Traversal دارند.
  • عدم تست در محیط staging: آسیب‌پذیری بدون تست کشف نمی‌شود.

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

پرسش‌های پرتکرار درباره Path Traversal

Path Traversal چیست و چرا خطرناک است؟ نوعی آسیب‌پذیری که در آن مهاجم با توالی ../ از پوشه مجاز خارج می‌شود و به فایل‌های حساس دسترسی پیدا می‌کند.

تفاوت Path Traversal و File Inclusion چیست؟ در Path Traversal فقط فایل خوانده می‌شود، در File Inclusion فایل اجرا می‌شود. برای مرور، File Inclusion Prevention را ببینید.

آیا basename() کافی است؟ در بیشتر موارد بله، اما برای امنیت حداکثری باید با whitelist ترکیب شود.

چطور از Path Traversal در افزونه دانلود جلوگیری کنم؟ با whitelist نام فایل و ترکیب realpath() با بررسی prefix.

آیا Path Traversal روی Windows هم کار می‌کند؟ بله، با ..\ یا ../.

چطور بفهمم افزونه‌ای Path Traversal دارد؟ کد را جست‌وجو کنید. هر جا file_get_contents یا readfile با متغیر پویا باشد، یک نقطه خطر است.

آیا افزونه‌های امنیتی Path Traversal را دفع می‌کنند؟ برخی افزونه‌ها WAF دارند که می‌تواند payloadهای شناخته‌شده را مسدود کند، اما دفاع اصلی باید در کد باشد. برای مرور گزینه‌ها، بهترین افزونه‌های امنیتی وردپرس را ببینید.

آیا محدودسازی مسیر با open_basedir کافی است؟ این تنظیم یک لایه اضافی است، اما نباید جایگزین دفاع در کد شود.

برای مطالعه بیشتر درباره Path Traversal، صفحه Directory traversal attack در ویکی‌پدیا مفید است.

خط پایان

Path Traversal Prevention در وردپرس یکی از آن لایه‌های امنیتی است که در سایه XSS و SQL Injection کمتر دیده می‌شود، اما پیامدهای آن می‌تواند از نشت فایل پیکربندی تا نفوذ کامل به سرور متغیر باشد. در بستر وردپرس، استفاده گسترده از مسیر پویا در افزونه‌ها و قالب‌ها، سطح حمله را بزرگ می‌کند. دفاع مؤثر نیازمند ترکیب چند لایه است: حذف کاراکترهای خطرناک، whitelist، ترکیب realpath() با بررسی prefix، و محافظت در سطح وب‌سرور. اگر سایت شما فرم دانلود یا مسیر پویا دارد، همین امروز بازبینی کنید.

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