PDA

View Full Version : آموزش: بهترین راه جلوگیری از حملات CSRF در PHP ---------



siavashsay
پنج شنبه 23 آذر 1391, 13:35 عصر
دوستان عزیز همین اول عرض کنم که این تاپیک هم جنبه سوالی داره واسم و هم آموزشی !
---------------
طبق تحقیقاتی که داشتم حملات CSRF یکی از حملاتی هست که هکرها مورد استفاده قرار میدن و نیازی به توضیح دادنشم نیست ! چون تو این فروم بهش اشاره شده !
اما قضیه اینجاس که موثرترین این حملات وقتی هست که ما بیشتر از متغیرهای GET استفاده میکنیم ! چون این متغیرها رو به راحتی میشه تو URL استفاده کرد!
یکی از راههای مفید استفاده از متغیرهای POST هست ! اما قضیه اینجاس که ما نمیگیم میشه کاملا به POST اکتفا کرد ! چرا که فرستادن متغیرهای POST هم روشی هست که هکرها میتونن ازش استفاده کنن !
حالا باز طبق همون تحقیقاتی که داشتم بهترین راه جلوگیری از حملات CSRF این هست که موقع ارسال یک درخواست ( مثل انجام یک تراکنش - فرستادن ایمیل - بروز کردن اطلاعات و ... ) از یک متغیر HIDDEN و یک SESSION استفاده کرد و اونا رو بصورت HASH RANDOM مقدار دهی کرد !
اینکار به خاطر این هست که ما چک کنیم که :
1- اون فرم توسط خود کاربر داره ارسال میشه
2- اون فرم یک بار ارسال میشه و برای هر بار ارسال مقدار جدید میگیره !
3- چک کنیم که اون درخواست و ارسال تنها توسط فرمی که توی سایت ما هست داره اجرا میشه ! نه اینکه مقادیر از سایت دیگری به سایت ما فرستاده شه !
--
حالا در مورد گزینه 3 بنده یه کدی رو نوشتم که میخوام توسط استاتید چک بشه و ببین که موثر هست یا خیر !
این کد :


if(isset($_POST['submit'])){
$serverUrl='http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
$refererUrl=$_SERVER['HTTP_REFERER'];
if($serverUrl!=$refererUrl){
echo "ERROR";
}else{
echo "OK";
}
}


-- همونطور که واقفید این کد آدرس صفحه ای که فرم داخل اون هست و صفحه ای که متغیر ها از اونجا دارن ارسال میشن رو میگیره و چک میکنه که اگر متغیرها اگر از همون صفحه ارسال شدن OK و اگر از صفحه دیگه ای ارسال شدن مقدار ERROR رو بر میگردونه !
دوستان راهنمایی کنند :
--------
1- آیا به همین 1 راه میشه اکتفا کرد و اون حالت Hidden فیلد و Session رو در نظر نگرفت ؟! اگه نه - چرا ؟!
2- آیا این یک راه مکمل هست و اصلا نیازی هست استفاده شه یا خیر ؟!
3- اصلا نیازی نیست که استفاده شه ؟! چرا ؟!
--------
ممنون میشم راهنمایی کنید و اطلاعاتتون رو به اشتراک بگذارید !
با تشکر :)

mamali-mohammad
پنج شنبه 23 آذر 1391, 13:56 عصر
به نظر بهترین روش همون post هست !
چون زمانی به صفحه درخواست دهنده میره اونجا این دستورو داریم :

if(isset($_POST['var']))
در نتیجه متد GET جواب نمیده برای هکر

siavashsay
پنج شنبه 23 آذر 1391, 14:03 عصر
به نظر بهترین روش همون post هست !
چون زمانی به صفحه درخواست دهنده میره اونجا این دستورو داریم :

if(isset($_POST['var']))
در نتیجه متد GET جواب نمیده برای هکر

عذر میخوام ! اما بنده کاملا متوجه حرفای شما نشدم !
یعنی چی بهترین روش پست هست و متد GET برای هکر جواب نمیده ؟!
یعنی هکر ها از متد POST بهتر استفاده میکنن تا از متد GET ؟!
میشه توضیح کاملتری بدید ؟!
ممنون میشم ! :)

mamali-mohammad
پنج شنبه 23 آذر 1391, 14:51 عصر
نه دقیقا برعکس متوجه شدید
یعنی متد post بهتره برای امنیت !
البته منظور من کلی بود و اینطور نیست که post رو نمیشه دور زد
اما اصولا برای ثبت تماس ، ثبت خرید و یا ... از post استفاده بشه بهتره
برای نمایش و جستجو مطالب و ... هم از get استفاده بشه
هر کدوم هم زمان دریافت توسط سرور از نظر امنیتی بررسی بشن مشکلی دیگه ایجاد نمیشه

siavashsay
پنج شنبه 23 آذر 1391, 15:12 عصر
آهان - بله حق با شماست !
اما در کل قضیه TOKEN برای CSRF با تحقیقاتی که من کردم دقیقا همون CPATCHA هست ! اما چون ما میخوایم سایت حالت Friendly داشته باشه و مدام CAPTCHA استفاده نکنیم میایم و از SESION TOKEN استفاده میکنیم !
در هر صورت CSRF موقعی صورت میگیره که شما روی یک لینک کلیک کنی و اون لینک حاوی فرمی باشه که مقادیر رو به صفحه مخصوص ( لاگین ) شده شما بفرسته !
حالا میخوام نظر شما رو در مورد اون کدی که دادم بدونم ! چون وقتی اون کد رو استفاده میکنیم اون فرم موقعی فعال میشه و مقادیر رو ارسال میکنه که --- فقط و فقط -- از همون صفحه و همون فرم مقادیر ارسال بشه !
نه از صفحه ای دیگه که تو سایت دیگس !
پس گمونم اگه اون رو بذاریم خیلی ساده بشه جلو CSRF رو گرفت !
درسته یا نه ؟!

mamali-mohammad
پنج شنبه 23 آذر 1391, 15:20 عصر
فکر نکنم !
شما یه فایل جاوا اسکریپت رو در نظر بگیر

page.php?id=<script type="text/javascript" src="http://yourname.com/file.js"></script>
ادرس از سایت شماست اما فایل js رو میشه تزریق کرد

siavashsay
پنج شنبه 23 آذر 1391, 15:28 عصر
بله اما این بر میگرده به JS INJECTION - شما باید جلو JS INJECTION رو بگیری که نتونن جاوا تزریق کنن ! اونم به راحتی قابل حله ! به اینصورت که در قسمت ACTION فرم بجای PHP_SELF فقط اسم اون صفحه موجود رو بدید !
مثلا اگر در صفحه process.php هستید در قسمت ACTION فرم process.php رو بنویسید تا صفحه از URL کد جاوا قبول نکنه و نگیره !
نظر شما چیه ؟!

mamali-mohammad
پنج شنبه 23 آذر 1391, 15:37 عصر
اگه متد get باشه قبول میکنه
برای اینکه تزریق نشه از mysql_real_escape_string و htmlspecialchars به نظرم باید استفاده بشه
در از preg_match هم میشه استفاده کرد

siavashsay
پنج شنبه 23 آذر 1391, 15:43 عصر
بله اما در اینجا بحث بنده گزینه 3 مطالبم بود ! یعنی متد POST ! در اون صورتی که صفحه ما اصلا GET رو قبول نمیکنه چطور ؟!

mamali-mohammad
پنج شنبه 23 آذر 1391, 15:58 عصر
وقتی قرار هست post بشه هکر چطوری میتونه کدشو تزریق کنه ؟

siavashsay
پنج شنبه 23 آذر 1391, 16:06 عصر
از طریق فرمی که خودش ساخته و مقادیر رو به سایت شما میفرسته ! واسه همین باید از یه متغیر نامرئی که مقدار اون قابل تغییر هست !
این قضیه که خیلی ساده تو همین فروم توضیح داده شده ! از پست هم میشه !
در این تاپیک ببینید (http://barnamenevis.org/showthread.php?281805-%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D8%AD%D9%85%D9%84%D9%87-%D9%87%D8%A7%DB%8C-%D9%86%D9%81%D9%88%D8%B0-%D9%88-%D8%B3%D9%88%D8%A1%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D 8%AF%D9%87-%D8%A7%D8%B2-%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%D9%88%D8%A8)
اما بحث من سر اینه که فرم از طرف خود سایت ارسال بشه !

mamali-mohammad
پنج شنبه 23 آذر 1391, 16:11 عصر
متوجه نشدم
توضیح بیشتر میدید ؟

eshpilen
پنج شنبه 23 آذر 1391, 17:49 عصر
اونا رو بصورت HASH RANDOM مقدار دهی کرد !
HASH RANDOM چیه دیگه؟ :متفکر:


3- چک کنیم که اون درخواست و ارسال تنها توسط فرمی که توی سایت ما هست داره اجرا میشه ! نه اینکه مقادیر از سایت دیگری به سایت ما فرستاده شه !
از این مورد نمیشه جلوگیری کرد. فقط میشه سخت ترش کرد/هزینه رو بالا برد.
چون یه برنامه میتونه مثل مرورگرها اول درخواست بده واسه صفحهء فرم شما، تمام کوکی ها و توکن ها و خلاصه هرچیزی رو که برای سابمیت کردن فرم لازمه بخونه، و فرم رو با همین مقادیر و کوکی سابمیت کنه.
طبیعتا میتونه User agent رو هم ست کنه و خودش رو بجای مرورگر جا بزنه.


این کد :
[PHP]
if(isset($_POST['submit'])){
$serverUrl='http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
$refererUrl=$_SERVER['HTTP_REFERER'];
if($serverUrl!=$refererUrl){
echo "ERROR";
}else{
echo "OK";
}
}

-- همونطور که واقفید این کد آدرس صفحه ای که فرم داخل اون هست و صفحه ای که متغیر ها از اونجا دارن ارسال میشن رو میگیره و چک میکنه که اگر متغیرها اگر از همون صفحه ارسال شدن OK و اگر از صفحه دیگه ای ارسال شدن مقدار ERROR رو بر میگردونه !

دوستان راهنمایی کنند :
--------
1- آیا به همین 1 راه میشه اکتفا کرد و اون حالت Hidden فیلد و Session رو در نظر نگرفت ؟! اگه نه - چرا ؟!
خیر.
چون HTTP_REFERER هم چیزی نیست جز یک هدر که کلاینت در درخواست ارسال میکنه؛ بنابراین برنامهء هکر هم میتونه مقدارش رو ست کنه.
ضمنا در HTTPS این هدر وجود نداره (توسط مرورگرها ست نمیشه) و به مشکل میخوره این کد.


2- آیا این یک راه مکمل هست و اصلا نیازی هست استفاده شه یا خیر ؟!
3- اصلا نیازی نیست که استفاده شه ؟! چرا ؟!
بنظرم نیازی نیست.
چون روشهای موثرتری وجود دارن مثل همون توکن. هرچند اونم نمیتونه 100% جلوگیری کنه و فقط کار رو دشوارتر میکنه و هزینه رو بالا میبره. البته در عمل چون خیلی برنامه ها اینقدر کامل نیستن و خیلی کسانی هم که میخوان این کارها رو بکنن اونقدر دانش و انگیزه نداره، همین روشها شاید آمار رو به صفر یا نزدیک صفر برسونه.

siavashsay
پنج شنبه 23 آذر 1391, 18:39 عصر
با تشکر از شما دوست عزیز ! توضیحات کاملی بود ! :)