PDA

View Full Version : جلوگیری از حملات RFI و LFI



engmmrj
شنبه 23 دی 1391, 11:53 صبح
چطوری میشه از حملات RFI،LFI جلوگیری کرد
چطوری یک هکر از این روش نفوذ میکنه
جستجو کردم چیزی پیدا نکردم البته همه رو آقای eshpilen بیخود توصیف کرده بودند

mamali-mohammad
شنبه 23 دی 1391, 11:56 صبح
با این دو باگ هکر میتونه روی سرور شما فایل خودشو لود کنه
فرض کن شما اینه :

if(isset($_GET['page'])) {
include $_GET['page'].'.php';
}

اینجا شما اومدی دستور دادی که اگر عنوان صفحه رو گرفتی ، اون صفحه رو لود کن
درست ؟
طرف میاد مسیر یه شل رو میزاره ، شل خودش آپلو میشه

این یه روش حمله است

engmmrj
شنبه 23 دی 1391, 12:03 عصر
چه طوری میتونم جلو این حمله رو بگیرم؟

siavashsay
شنبه 23 دی 1391, 12:41 عصر
چند روش هست !
1- اینکه شما فایلی رو که دارید include میکنید چک کنید ببینید در سرور خودتون موجود هست یا نه ! با استفاده از تابع file_exists
نمونه کد سایت php :


<?php
$filename = '/path/to/foo.txt';

if (file_exists($filename)) {
echo "The file $filename exists";
} else {
echo "The file $filename does not exist";
}
?>

با این کار شما چک میکنید که فایلی که داره ضمیمه میشه فایل خودی هست یا نه ! اگر نبود اجازه include رو نمیدید !
2- استفاده از رگولار اکسپرشن برای چک کردن نام فایل :

$page = preg_replace('/\W/si', '', $_GET['page']); include('./'.$page.'.php');
3- استفاده از htaccess :

<files ~ "\.inc$"> Order allow,deny Deny from all </files>
موفق باشید :)

mamali-mohammad
شنبه 23 دی 1391, 12:57 عصر
siavashsay عزیز این روش به تنهایی جواب گو نیست و میشه دورش زد

engmmrj
شنبه 23 دی 1391, 13:16 عصر
اگه میشه راه حل مناسب رو در ا ین جا درج کنید:خجالت:

siavashsay
شنبه 23 دی 1391, 13:17 عصر
siavashsay عزیز این روش به تنهایی جواب گو نیست و میشه دورش زد
به هر حال شما هم اگر نظری بدی که دوستمون راهنمایی بشن بد نیست !
در هر صورت !
فراخوانی فایل در حالت عادی هیچ مشکلی پیش نمیاره مگر اینکه در 2 حالت باشه !
1- اینکه مسیر ضمیمه شدن فایل قابل دسترسی باشه !
2- وقتی که نام فایل فراخوانی شده متغیر باشه ! ( مثل همین GET )
خوب مورد اول رو که حتی المقدور سعی میکنم از سرور خودمون باشه !
در مورد دوم هم چند تا مثال زدم !اما باز هم برای اینکه URL شما متغیر هست باید اون رو فیلتر کنید !
برای این کار یکی از راه ها این هست که از تابع basename استفاده کنید !
مثال :


$file = basename($_GET['name']);
include('include/' . $file . '.php');

در اینجا تابع basename باعث میشود که ورودی فقط نام یک فایل باشه نه یک آدرس یا فولدر !
همچنین محدود کردن پسوند .php در آخر include باعث میشه که تنها فایل php ضمیمه بشه نه فایل با پسوند دیگه ای :)
موفق باشید !

mamali-mohammad
شنبه 23 دی 1391, 16:05 عصر
خب این برای RFI هست
برای LFI چه تصمیمی دارید ؟
به نظرم استفاده از نام حقیقی بهترین روش باشه
مثال :

$file = $_GET['page']; //The page we wish to display

// Only allow include.php
if ( $file != "include.php" ) {
echo "ERROR: File not found!";
exit;
}

البته اینارو بر اساس برنامه dvwa گفتم و کمی تجربه شخصی

siavashsay
شنبه 23 دی 1391, 16:31 عصر
خب این برای RFI هست
برای LFI چه تصمیمی دارید ؟
فرقی نمیکرد ! فرق LFI - RFI توی نوع آدرس فایل هست ( محلی بودن فایل یا آدرس راه دور )
ما با اینکار جلو هر 2 رو گرفتیم !
حالا اگر هم از تابع basename استفاده شه و هم از تابع file_exists بسیار عالی هست !
2 راه دیگر هم بازم عنوان میکنم !
استفاده از تابع strpos


<?php
if(strpos($_GET['filename'], '..')
{
echo 'File not found';
}
else
{
include $_GET['filename'];
}
?>

این راه خوبی هست اما به تنهایی کافی نیست ! چون ممکن هست که هکر با دادن آدرس مطلق سایت رو به خطر بندازه !
راه بعدی که در آموزشات جناب یعقوبیان بود - به کد زیر توجه کنید:


<?php
/*** the array of allowed pages ***/
$allowed_pages = array('index', 'contact', 'tutorials');
/*** check if file name is in array ***/
if(!in_array($_GET['filename']), $allowed_pages)
{
echo 'File not found';
}
else
{
/*** assign the file name ***/
$file = $_GET['filename'];
if(!file_exists($file))
{
echo 'File error';
}
else
{
/*** include the file ***/
include $file;
}
}
?>

روش بالا باز بهتر هست نسبت به بقیه راهها ! چون عملا توی چند فرآیند دارین سیستم رو چک و فیلتر میکنید !

soroush.r70
شنبه 23 دی 1391, 18:09 عصر
این روشم بد نیست.

$MySQLConnectFile = 'inc/function.php';
if ( is_dir ( 'inc/' ) )
{
$IncIsDir == TRUE;
}
if ( file_exists ( $MySQLConnectFile ) )
{
$MySQLFileExists == TRUE;
}
if ( $IncIsDir && $MySQLFileExists )
{
require_once ($MySQLConnectFile);
}
else
{
echo '<b>Error:</b> <i>Could not read the MySQL Connection File. Please try again later.';
exit();
}

رضا قربانی
شنبه 23 دی 1391, 20:58 عصر
دیدم طالب زیاده گفتم یه تابع ساده در عین حال مقاوم و امن بنویسم برای بچه ها جیگرشون حال بیاد : (البته ما کسی نیستیم ، کوچیک همه هستیما)



function FilterGhorbani($VALUE)
{
$symbol = array(',', ')', '(', "'", '"','!', '?', '/', '[', ']', '+', '=', '#', '\x00','\x7F','\xC0','\xFD', '\n', '\r','\t', '\x1a', '$', 'order by', 'order+by', 'select', 'union', 'delete', '..');
$A = preg_replace("/<.*?>/", "",$VALUE);
$B =str_replace($symbol,"",$A);
echo $B;
}

FilterGhorbani($_POST["TEST"]);//نحوه فرلخوانی
//OR
$Famili=FilterGhorbani($_POST["Fam"]);


مقاوم در RFI-و-LFI و Injection و Script و ... خلاصه کسی از داخل ورودی های سایت Get || Post نمی تونه وارد بشه. (قول صد در صد از جانب شخص بنده :لبخند: )
بیا اینم امضاش ♪┌îّ`

eshpilen
شنبه 23 دی 1391, 21:49 عصر
این روشم بد نیست.

$MySQLConnectFile = 'inc/function.php';
if ( is_dir ( 'inc/' ) )
{
$IncIsDir == TRUE;
}
if ( file_exists ( $MySQLConnectFile ) )
{
$MySQLFileExists == TRUE;
}
if ( $IncIsDir && $MySQLFileExists )
{
require_once ($MySQLConnectFile);
}
else
{
echo '<b>Error:</b> <i>Could not read the MySQL Connection File. Please try again later.';
exit();
}

این چیه دیگه :متفکر:
عزیزم متغییری که محتواش رو خودت تعیین کردی رو که نمیخواد چک کنی :لبخند:
فقط موقعی که بخشی از آدرس از طریق متغییرهایی که از سمت کلاینت میان ست میشه نیاز هست یجوری چک یا محدود کنی.

eshpilen
شنبه 23 دی 1391, 21:54 عصر
دیدم طالب زیاده گفتم یه تابع ساده در عین حال مقاوم و امن بنویسم برای بچه ها جیگرشون حال بیاد : (البته ما کسی نیستیم ، کوچیک همه هستیما)



function FilterGhorbani($VALUE)
{
$symbol = array(',', ')', '(', "'", '"','!', '?', '/', '[', ']', '+', '=', '#', '\x00','\x7F','\xC0','\xFD', '\n', '\r','\t', '\x1a', '&', '$', 'order by', 'order+by', 'select', 'union', 'delete', '..');
$A = preg_replace("/<.*?>/", "",$VALUE);
$B =str_replace($symbol,"",$A);
echo $B;
}

FilterGhorbani($_POST["TEST"]);//نحوه فرلخوانی
//OR
$Famili=FilterGhorbani($_POST["Fam"]);


مقاوم در RFI-و-LFI و Injection و Script و ... خلاصه کسی از داخل ورودی های سایت Get || Post نمی تونه وارد بشه. (قول صد در صد از جانب شخص بنده :لبخند: )
بیا اینم امضاش ♪┌îّ`
اه اه حالم بهم خورد.
خدایی اینا چیه درمیارید شماها :متعجب:

رضا قربانی
شنبه 23 دی 1391, 22:10 عصر
خدایی اینا چیه درمیارید شماها مگه شما در نمیارید
می دونستم پیدات میشه . نمیخواد یک صفحه در مورد این تابعی که نوشتم بنویسی. می تونی نفوذ کن؟
کاری ندارم بعضی از کاراکترها رو فیلتر کردم(select union delete) ، ولی اگر می تونید نفوذ کنید در غیر این صورت (همین حال به هم زن شما) مشکل دوستان تازه وارد که هک میشن رو به طور 99.5% از Get o Post بر طرف می کنه . شما خودتون استادید و در این شکی نیست . ما به بچه های تازه وارد کمک کردیم تا جریان بیاد توی دستشون.
نیازی نیست دو تا پست ، پشت هم بزنید . می تونید توی یک پست دو تاش رو ارسال کنید.

colors
شنبه 23 دی 1391, 23:29 عصر
function FilterGhorbani

:قهقهه: ‍‍‍‍‍‍‍...

Unique
یک شنبه 24 دی 1391, 00:34 صبح
راستش بحث های جالبی انجام میشه !
به نظر من کسانی دچار حملات RFI و LFI میشوند که از include غیر اصولی استفاده میکنند ! کلا includeنیاز نیست به هیچ وجهی از روی get یا post به صورت مستقیم انجام بشه !

در مورد filter کردن هم با نهایت احترم آقا رضا عزیز ! اصلا به این کارا نیاز نیست ! شما میخوای جلوی xss و sql injection را بگیرین ! اولی با دو تا بع htmlspecialchars و htmlentities و در صورت نیاز به پذیرفتن تگ ها از htmlpurifier و برای دومی هم کافیه escape کنین یا اصلا با pdo بیاین parametrized query بدین ! اصلا نیاز به ابداعات شخصی نیست چون خودتون را محدود میکنین !

رضا قربانی
یک شنبه 24 دی 1391, 01:15 صبح
یا اصلا با pdo بیاین parametrized query بدین یه چیزی بگید کاربرای تازه وارد هم که سوال پرسیدن بفهمن جریانش چیه.
مشکل eshpilen هم همینه دیگه . کاربر تازه می خواد خودش رو بکشه بالا باید از چیزایی ابتدایی که آسونتره بهشون یاد بدیم تا فعلا کارشون رو راه بندازن و به هدفشون برسن ، یواش یواش کدهاشون بهینه میشه .بهتر و بهتر - حرفه ای تر - و...

خلاصه بازم در خدمت بچه ها هستیم . همین قدری که در توان هست در اختیار شما


پ.ن : مشکل شما با نام تابعی که ایجاد می کنمه :ی

engmmrj
یک شنبه 24 دی 1391, 01:44 صبح
کلا includeنیاز نیست به هیچ وجهی از روی get یا post به صورت مستقیم انجام بشه !
چطوری؟
میشه یه مثال بزنید؟:قلب:

siavashsay
یک شنبه 24 دی 1391, 10:26 صبح
چطوری؟
میشه یه مثال بزنید؟:قلب:
نمیدونم دقیقا منظورشون چیه ! اما خوب با یک کار کوچیک میتونید امنیت رو بالا ببرید !
مثلا اگر شما متغیر GET = login گرفتید اینطوری عمل کنید :


$pageID=$_GET['pageID'];
if($pageID=='login'){
include("login.php");
}
if($pageID=='register'){
include("register.php");
}
//...

البته یکم خلاقیت بهتره ! بنده خواستم ساده عنوان کنم ! شما میتونید از آرایه ها و حتی function نویسی هم برای خلاصه نویسی استفاده کنید !
درسته که شاید یکم طولانی بشه اما در هر صورت امنیت بیشتری دارید و خیالتون راحته دیگه ورودی توسط کاربر آنالیز نمیشه !

eshpilen
یک شنبه 24 دی 1391, 10:42 صبح
آره این روش White list هست که امن ترین روشه اگر بشه در جایی استفاده کرد (بعضی جاها ممکنه استفاده ازش ممکن نباشه یا صرف نداشته باشه).
یعنی فقط مقادیر مجاز رو مشخص میکنید و بقیه رو رد میکنید.
و البته این روش خاص یک مورد هست و یک تابع و لیست کلی برای تمام کاربردها وجود نداره.

حالا اگر تعداد گزینه هاتون زیاد بود میتونید به این شکل هم عمل کنید که کار رو خیلی ساده تر میکنه:

$pageID=$_GET['pageID'];
$valid_values=array('login', 'register', 'logout', 'update', 'delete', 'add', 'admin');
if(!in_array($pageID, $valid_values)) exit('Invalid pageID value!');
include "$pageID.php";

soroush.r70
یک شنبه 24 دی 1391, 12:38 عصر
این فانکشن هم برای include بدنیست


function includeFile($file_name){

$dir = array('./', 'lib/', 'db/', 'student/'); //<-- put here your website directory you want to include
$level = array('', '/', '../', '../../'); //<-- you can add more deep level in this array
$ini_path = array();

foreach($dir as $p){

foreach($level as $l){
$file = $l.$p.$file_name;
if(file_exists($file)){
include_once($file);
return;
}
}
}
} //end function includeFile

includeFile('html.php');
includeFile('libpage.php');

Unique
یک شنبه 24 دی 1391, 22:40 عصر
یه چیزی بگید کاربرای تازه وارد هم که سوال پرسیدن بفهمن جریانش چیه.
راستش parametrized queries یا prepared statements موضوع جدیدی نیست ، اینجا خیلی مثال زده براش شروع خوبه (http://php.net/manual/en/pdo.prepared-statements.php)

اما اگه کسی هم نخواد استفاده کنه اتفاق خاضی نمیفته کافیه درست escape کنه کا تا حالا توی این انجمن کلی در موردش بحث شده و باید جستجو کنند دوستانی که کمتر آشنایی دارند.

engmmrj
دوشنبه 25 دی 1391, 12:26 عصر
از pdo استفاده کنم دیگه احتیاج به فیلتر کردن ورودی ها نیست؟

Unique
دوشنبه 25 دی 1391, 17:21 عصر
زمانی که با pdo کار میکنید باید prepared statements بنویسین در این صورت باید از parameter ها استفاده کنید از این رو بهشون میگن parametrized البته در زمان استفاده از stored procedure ها هم دقیقا همین موضوع هست.

زمانی که شما parameter میدین به query در واقع parameter در زمان اجرای query شما evaluate نمیشه و مثل یک مقدار باهاش برخورد میشه ! پس نمیشه inject کرد. اما خطرات xss وجود داره که باید اونها را باهاشون مقابله کنید.