در این دوره آموزشی، بررسی کاملی روی روش های مختلف برای استفاده از آسیب پذیری LFI و شرایط مختلف، در برخورد با این آسیب پذیری را به صورت عملی آموزش خواهیم داد. اگر علاقه مند به مطالعه این آسیب پذیری هستید، در این دوره با ما همراه باشید تا آسیب پذیری LFI را بدون خفه شدن قورت دهیم! 😊
این آسیب پذیری یکی از چندین آسیب پذیری معروف است که در جاهای مختلف با اسم های مختلف، انسان را غافل گیر کرده و حس پیدا کردن آسیب پذیری جدید برای یادگیری را به ما میدهد! 😉 LFI در واقع معادل Local File Inclusion است و برخی با اسامی زیر نیز این آسیب پذیری را نامگذاری میکنند.
- Directory Traversal
- Path Traversal
البته ذکر این نکته شاید بد نباشد که در گذشته واقعاً این 3 نوع نامگذاری مختلف، تفاوتهای اندکی با هم داشتهاند امّا در روزگار فعلی تفاوت چندانی بین آنها نیست!
این آسیب پذیری میتواند در خیلی از جاها رخ دهد و در حالت کلی تشخیص آن ساده است. هر جایی که متغیرهای موجود در آدرس و یا در بدنه ی درخواست، شبیه نام یک فایل یا یک مسیر بود ممکن است بتوانید در آن جا این آسیب پذیری خوش خط و خال را پیدا کنید.
اگر بخواهیم کمی به زبان فنی صحبت کنیم میتوان گفت که LFI زمانی رخ میدهد که در یک فایل، فایل دیگری را include میکنیم و آدرس آن را با استفاده از متغیرهای GET یا POST دریافت میکنیم. کد موجود در مثال زیر، کد صفحه اصلی یک وبسایت آسیب پذیر به LFI است که در ادامه آن را بررسی خواهیم کرد.
<?php
if (isset($_GET['page'])){
$page = $_GET['page'];
include 'header.php';
include '$page';
include 'footer.php';
} else {
include 'header.php';
echo '<p>welcome to index page</p>';
include 'footer.php';
}
همانطور که در کد بالا مشاهده میکنید در ابتدای کد بررسی میشود که آیا متغیر page در URL مقداردهی شده است یا نه و در صورتی که مقداردهی شده بود محتوای این متغیر را include میکند. این نمونه کد به دلیل بررسی نکردن محتوای متغیر page و include کردن آن، آسیب پذیر به LFI شده است. اما اگر می خواستیم این کد را به صورت امن پیاده سازی کنیم همانطور که اشاره کردیم میتوانستیم ورودی متغیر page را مانند مثال زیر بررسی کنیم و فقط تعدادی از مقادیر خاص را به عنوان ورودی صحیح در محتوای این متغیر بپذیریم.
<?php
if (isset($_GET['page'])){
$page = $_GET['page'];
if ($page == "about.php")
include 'about.php';
elseif ($page == "contact.php")
include 'contact.php';
elseif ($page == "store.php")
include 'store.php';
} else {
include 'header.php';
echo '<p>welcome to index page</p>';
include 'footer.php';
}
همانطور که در مثال بالا مشاهده میکنید تنها مقادیری که برای متغیر page قابل قبول هستند about.php، contact.php
و store.php
هستند و در صورتی که هر مقدار دیگری در این متغیر قرار دهید صفحه index عادی برای شما نمایش داده خواهد شد. بنابراین متغیر page در حال include شدن است اما به صورت امن و غیر قابل دست کاری. به این روش در اصطلاح whitelist کردن ورودی گفته میشود که میتواند در رفع آسیب پذیری های مختلف دیگر مانند XSS و ... هم کمک کند. البته توجه داشته باشید که این روش مناسب زمانی است که انواع مقادیری که یک متغیر میتواند داشته باشد محدود و کم باشد در غیر این صورت باید از روش های پاک سازی ورودی استفاده کنیم که در بخشهای آتی این دوره به آن خواهیم پرداخت. در حالت کلی روش های زیادی برای جلوگیری از این آسیب پذیری وجود دارد و مدل اشاره شده در مثال بالا تنها یک نمونه ساده برای درک بهتر ماهیت این آسیب پذیری است.
بنابراین دریافت تمام یا بخشی از آدرس یک فایل، با استفاده از متغیرهای GET یا POST بدون فیلتر کردن ورودی و include کردن آن میتواند منجر به دسترسی هکر به فایلهای غیر مجاز شود. نمونهای از این فرایند میتواند با وارد کردن آدرس فایلهای حساسی مانند etc/passwd/
که یک فایل پیکربندی حاوی اطلاعات حساس است، انجام شود و در مواردی دیگر حتی میتواند منجر به اجرای کد در داخل سرور شود. حالت ها و روش های مختلفی برای این نوع حمله وجود دارد که در قسمتهای بعد به توضیح آنها خواهیم پرداخت.
حالت ساده LFI
به عنوان حالت ساده کد موجود در مثال زیر را که قبلا بررسی کردیم در نظر بگیرید.
<?php
if (isset($_GET['page'])){
$page = $_GET['page'];
include 'header.php';
include '$page';
include 'footer.php';
} else {
include 'header.php';
echo '<p>welcome to index page</p>';
include 'footer.php';
}
در این حالت متغیر page که آدرس یک فایل را مشخص میکند در URL قابل دسترسی است و شما میتوانید با دادن آدرس فایل دلخواه خود محتویات فایل مورد نظر را ببینید. برای مثال آدرس زیر را در نظر بگیرید.
https://example.com/index.php?page=aboutus.php
در آدرس بالا میتوانیم با قرار دادن آدرس etc/passwd/ در متغیر page، مشخصات کاربران سرور وبسایت را دریافت کنیم! 😉 بسته به این که برنامهنویس کد سمت سرور را چگونه نوشته باشد ممکن است با دادن آدرس کامل (absolute) فایل بتوانیم به آن دسترسی پیدا کنیم و یا نیاز داشته باشیم که آدرس نسبی(relative) فایل را پیدا کنیم.
نمونه آدرس کامل:
https://example.com/index.php?page=/etc/passwd
نمونه آدرس نسبی:
https://example.com/index.php?page=../../../etc/passwd
برای بهتر متوجه شدن مثال بالا باید بدانید که در سیستمعامل لینوکس /.
معادل دایرکتوری فعلی و /..
معادل دایرکتوری قبلی است. مثلا اگر در آدرس /etc/apache2/
باشیم در واقع /.
معادل etc/apache2/
است و /..
معادل etc/
است. در واقع با گذاشتن هر /..
در ابتدای آدرس یک دایرکتوری، از دایرکتوری اصلی که برنامهنویس در حال include کردن فایل از آن است یک دایرکتوری به عقب میرویم تا به دایرکتوری /
برسیم و بتوانیم وارد etc
شده و فایل passwd
را بخوانیم. نکته جالب اینجاست که اگر به طور مثال با عبارتی مانند etc/passwd/../../..
بتوانیم فایل passwd
را بخوانیم، گذاشتن /..
های بیشتر هیچ مشکلی پیش نمیآورد و میتوانیم هر چقدر دیگر که بخواهیم /..
به این عبارت اضافه کنیم. دلیل این موضوع، رسیدن به /
است که دایرکتوری ریشه است و قبل از آن هیچ دایرکتوری دیگری نداریم، بنابراین اگر /../../..
معادل دایرکتوری /
باشد، /../../../../../../../../..
هم معادل دایرکتوری ریشه میشود!
در این نقطه به پایان قسمت اول این دوره میرسیم و زمان خداحافظی است! در این بخش از دوره آموزشی LFI با هم یاد گرفتیم که LFI چیست و مفاهیم ابتدایی لازم برای درک آن را آموختیم. در ظاهر با این آسیب پذیری میتوان فقط محتوای فایل ها را خواند، اما اگر منتظر اتفاق های خطرناک تر هستید در بخشهای بعدی این دوره با ما همراه باشید. منتظر سؤالات چالشی و نظرات ارزشمند شما هستیم! تا قسمت بعدی دوره شما را به خداوند بزرگ می سپاریم! 😊