PDA

View Full Version : سوال: چطور می تونم یه رشته هش امن برای جلوگیری از crf ایجاد کنم؟



idocsidocs
پنج شنبه 13 بهمن 1390, 01:38 صبح
البته راه ساده اینه که این یه رشته هش ایجاد کنم و توی سسشن قرار بدم. اما اگر بخوام از این رشته برای همه فرمها استفاده کنم، هکر می تونه به راحتی رشته هش رو بدست بیاره.

لطفا راهنمایی کنید.

Keramatifar
پنج شنبه 13 بهمن 1390, 12:03 عصر
دوست عزیز
لازم نیست حتما از یک رشته ثابت استفاده کنی؟ می تونی یک رشته Random بسازی و در Session قرار بدی، بعنوان مثال:
ابتدا یک Form Token ایجاد می کنید

$token = md5(uniqid(rand(), true));
در فرم های خود یک HiddenField قرار می دهید که حاوی TF باشد:

<form action="process.php" method="post">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="text" name="amount" />
<input type="text" name="destination_card_number" />
<input type="submit" name="submit" value="Transfer" />
</form>
و زمانیکه Request ارسال شد می تونید به این شکل Compare کنید:


if ( (!empty($_SESSION['token'])) && (!empty($_POST['token'])) ) {
if ($_SESSION['token'] == $_POST['token']) {
//process the form
}
}
البته راه حل بهتر اینه که از تکنیک Time Frame هم استفاده کنی
تکنیک Time Frame بر اساس مقایسه زمان رندر شدن فرم و زمان ارسال Request آن به سرور است
با استفاده از این تکنیک هم میشه جلوی خیلی از حملات مثل CSRF گرفت هم جلوی Spam ها و Bot ها رو.
برای اجرای این تکنیک در هر فرم بر اساس تعداد فیلدها یک بازه زمانی (شامل یک حداقل زمان و یک حداکثر زمان) رو برای تکمیل فرم و ارسال Request به سرور در نظر میگیری.
بعنوان مثال تکمیل یک فرم با 5 فیلد و ارسال آن به سرور در کمتر از 3 ثانیه غیر طبیعی است
برای پیاده سازی این تکنیک ابتدا یک Time Session ایجاد می کنید:

$_SESSION['time'] = time();
هنگام دریافت Reuqest نیز باید به این صورت Compare کنید:

$min_allowed_time = 20;
$max_allowed_time = 60;

if ( (time() - $_SESSION['time']) < $min_allowed_time ) {
echo 'form discarded';
}

if ( (time() - $_SESSION['time']) > $max_allowed_time ) {
echo 'form timeout';
}

idocsidocs
پنج شنبه 13 بهمن 1390, 14:13 عصر
لازم نیست حتما از یک رشته ثابت استفاده کنی؟ می تونی یک رشته Random بسازی و در Session قرار بدی، بعنوان مثال:
مشکل این روش اینه که اگر کاربر چندیدن فرم ایجاد کنه. مقدار ذخیره شده توی سسشن هم تغییر می کنه و فرم ارسال نمی شه. برای این موضوع باید چیکار کنم؟

Keramatifar
پنج شنبه 13 بهمن 1390, 15:06 عصر
مگه کاربر فرم ایجاد میکنه؟ کاربر از فرم یا فرم های شما استفاده میکنه که هر کدام یک TF جداگانه دارند، اگر فرمی به غیر از فرم های شما بیاد یعنی Attack

idocsidocs
پنج شنبه 13 بهمن 1390, 16:25 عصر
مگه کاربر فرم ایجاد میکنه؟ کاربر از فرم یا فرم های شما استفاده میکنه که هر کدام یک TF جداگانه دارند، اگر فرمی به غیر از فرم های شما بیاد یعنی Attack

مگه نباید رشته رندم رو توی سسشن قرار بدیم؟

Keramatifar
پنج شنبه 13 بهمن 1390, 19:44 عصر
می تونید به ازای هر فرم یک session به نام فرم ایجاد کنید و یا یک آرایه از Token ها در session قرار دهید

mbf5923
پنج شنبه 13 بهمن 1390, 21:12 عصر
می تونید به ازای هر فرم یک session به نام فرم ایجاد کنید
چطور باید این کار رو انجام داد؟

Reza1607
پنج شنبه 13 بهمن 1390, 23:33 عصر
چطور باید این کار رو انجام داد؟
خوب براي هر فرمتون يك اسم در نظر بگيريد مثلا براي ثبت نام register براي ورود login بعد هر زماني خواستي روي داده اون فرم پردازش كني سشن نام فرمي رو كه خودتون گذاشتين رو بررسي مي كنيد

idocsidocs
جمعه 14 بهمن 1390, 00:33 صبح
می تونید به ازای هر فرم یک session به نام فرم ایجاد کنید و یا یک آرایه از Token ها در session قرار دهید

می شه این قسمت "یا یک آرایه از Token ها در session قرار دهید " رو بیشتر توضیح بدید؟

Keramatifar
جمعه 14 بهمن 1390, 10:08 صبح
شما می تونید هر چیزی رو در Session قرار دهید، حتی یک Object رو (البته با استفاده از تکنیک های Serialize)
یک آرایه (ترجیحا از نوع Associative) به نام Tokens ایجاد کنید که هر Index آن نام Token و Value آن رشته ایجاد شده باشد و سپس آنرا در سشن قرار دهید.

MMSHFE
جمعه 14 بهمن 1390, 10:23 صبح
برای مثال، میتونید توی یک فرم (مثلاً فرم ثبت نام) این کد رو بگذارین:


$token = md5(uniqid(rand(), true));
$_SESSION['token']['register_form'] = $token;

و توی فرم دیگه (مثلاً فرم درج پست جدید) از کد زیر استفاده کنید:


$token = md5(uniqid(rand(), true));
$_SESSION['token']['add_post'] = $token;

حالا توی صفحه پردازش فرم ثبت نام از کد زیر:


if ( (!empty($_SESSION['token'])) && (is_array($_SESION['token'])) && (!empty($_POST['token'])) ) {
if ((isset($_SESSION['token']['register_form']) && $_SESSION['token']['register_form'] == $_POST['token']) {
//process the form
}
}

و توی صفحه پردازش فرم درج پست جدید از این کد:


if ( (!empty($_SESSION['token'])) && (is_array($_SESION['token'])) && (!empty($_POST['token'])) ) {
if ((isset($_SESSION['token']['add_post']) && $_SESSION['token']['add_post'] == $_POST['token']) {
//process the form
}
}

استفاده کنید.
موفق باشید.

mbf5923
جمعه 14 بهمن 1390, 11:37 صبح
آقا من یه سوال برام پیش اومده در مورد Session:
فرض کنید ما 2تا صفحه مجزا داریم که هرکدوم باید Session خاص خودشون رو داشته باشن مثلا 2تا اسکریپت مجزای از هم که هرکدم لاگین متفاوتی دارن
اما برای اینکه مشخص بشه کاربر لاگین کرده هر رد در Session یک عبارت رو درج میکنن مثلا :

$_SESSION['Login']='true';
خوب توی لوکال وقتی من وارد یکی از اسکریپت ها میشم اون یکی هم میگه وارد شدید!!!
میخواستم ببینم این مشکل چطور حل میشه و آیا روی هاست هم که بره همین مشکل وجود خواهد داشت.
راستی آقایان شهرکی و کرامتی عزیز لطفا فکری به حال ادیتور PHP بکنید

idocsidocs
جمعه 14 بهمن 1390, 12:09 عصر
$token = md5(uniqid(rand(), true));$_SESSION['token']['add_post'] = $token;
این کد هم همون مشکل رو داره چون فقط یک مقدار توی سسشن ذخیره می شه. برای روشی که شما می گید برای هر فرم باید بتونم چندین مقدار توی سسشن ذخیره کنم.

MMSHFE
جمعه 14 بهمن 1390, 12:27 عصر
اگه دقت کنید، مشکلی که گفتین توی این کد وجود نداره چون هر فرم، token$ خودش رو داره که با استفاده از فرم و بکمک تگ مخفی ارسال میشه و توی Session هم یک Token براش درنظر گرفته میشه که منحصر به فرم خودش هست. اینطوری، token ارسال شده توسط فرم، با token موجود در سشن همون فرم مقایسه میشه و میتونید فرمها رو جداگانه پردازش کنید. موفق باشید.

MMSHFE
جمعه 14 بهمن 1390, 12:33 عصر
آقا من یه سوال برام پیش اومده در مورد Session:
فرض کنید ما 2تا صفحه مجزا داریم که هرکدوم باید Session خاص خودشون رو داشته باشن مثلا 2تا اسکریپت مجزای از هم که هرکدم لاگین متفاوتی دارن
اما برای اینکه مشخص بشه کاربر لاگین کرده هر رد در Session یک عبارت رو درج میکنن مثلا :

$_SESSION['Login']='true';
خوب توی لوکال وقتی من وارد یکی از اسکریپت ها میشم اون یکی هم میگه وارد شدید!!!
میخواستم ببینم این مشکل چطور حل میشه و آیا روی هاست هم که بره همین مشکل وجود خواهد داشت.

برای رفع این مشکل، باید هر اسکریپت سشن خودش رو ایجاد کنه و اسم اندیسها رو متفاوت بگذارین و موقع چک کردن هم سشن مربوط به همون بخش رو چک کنید. مثال:


$_SESSION['script1_login'] = true;
$_SESSION['script2_login'] = true;

اگه این مورد رو رعایت نکنید، توی هاست واقعی هم همین مشکل رو خواهید داشت چون ایراد در روش طراحی هست نه نوع هاست.

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

idocsidocs
جمعه 14 بهمن 1390, 13:20 عصر
اگه دقت کنید، مشکلی که گفتین توی این کد وجود نداره چون هر فرم، token$ خودش رو داره که با استفاده از فرم و بکمک تگ مخفی ارسال میشه و توی Session هم یک Token براش درنظر گرفته میشه که منحصر به فرم خودش هست. اینطوری، token ارسال شده توسط فرم، با token موجود در سشن همون فرم مقایسه میشه و میتونید فرمها رو جداگانه پردازش کنید. موفق باشید.


ببینید وقتی یه فرم رو چندبار باز می کنیم مقدار سسشن در هر بار باز شدن فرم تغییر می کنه و این موضوع باعث ایجاد مشکل می شه. چون سسشن های هر فرم دارای چندین مقدار متفاوت می شن و در نتیجه دستورات شرطی اجرا نمی شن.

برای حل این مشکل بنظرم باید سسشن هر فرم رو توی آرایه ذخیره کرد.

MMSHFE
جمعه 14 بهمن 1390, 14:22 عصر
بله راههای زیادی وجود داره. یکی از اونها استفاده از آرایه هست. یکی دیگه، استفاده از نام فایل صفحه مربوط به فرم بجای اسم فرم هست. مثلاً ممکنه کاربر همزمان بخواد در چند تاپیک پست بزنه و همزمان توی همه تاپیکها فرم درج پست جدید رو باز کنه. در این حالت کد فرمها یکی هست ولی آدرس صفحات فرق میکنه و میتونید سشن هر صفحه رو جداگانه بررسی کنید. البته در این مواقع، بخاطر ایجاد سشنهای زیاد، بهتره هرموقع پردازش فرم تمام شد، سشنهای بکار رفته رو هم ازبین ببرید تا حافظه آزاد بشه.
موفق باشید.

idocsidocs
شنبه 15 بهمن 1390, 16:39 عصر
بله راههای زیادی وجود داره. یکی از اونها استفاده از آرایه هست. یکی دیگه، استفاده از نام فایل صفحه مربوط به فرم بجای اسم فرم هست. مثلاً ممکنه کاربر همزمان بخواد در چند تاپیک پست بزنه و همزمان توی همه تاپیکها فرم درج پست جدید رو باز کنه. در این حالت کد فرمها یکی هست ولی آدرس صفحات فرق میکنه و میتونید سشن هر صفحه رو جداگانه بررسی کنید. البته در این مواقع، بخاطر ایجاد سشنهای زیاد، بهتره هرموقع پردازش فرم تمام شد، سشنهای بکار رفته رو هم ازبین ببرید تا حافظه آزاد بشه.
فرض کنید که سسشن ها رو توی آرایه قرار دادم. طبیعی هست که باید سسشن رو توی فرم قرار بدم تا به همراه سایر اطلاعات به سمت سرور فرستاده بشه.
چطور باید این کار رو انجام بدم؟

MMSHFE
شنبه 15 بهمن 1390, 16:41 عصر
عزیز سشن رو نمیخواد توی فرم قرار بدین چون توی هر کدی که از session_start استفاده کنه، در اختیار صفحه خواهد بود و نیاز نیست اون رو همراه فرم ارسال کنید. فقط کافیه token مخصوص هر فرم رو که تولید میکنید، توسط تگ input مخفی ارسال کنید. موفق باشید.

idocsidocs
شنبه 15 بهمن 1390, 17:07 عصر
عزیز سشن رو نمیخواد توی فرم قرار بدین چون توی هر کدی که از session_start استفاده کنه، در اختیار صفحه خواهد بود و نیاز نیست اون رو همراه فرم ارسال کنید. فقط کافیه token مخصوص هر فرم رو که تولید میکنید، توسط تگ input مخفی ارسال کنید.
مگه نباید سسشن رو تولید کرد و بعد توی فیلد مخفی قرار داد؟

سسشن همونطور که گفتید یه آرایه هست و ایندکسش هم متفاوته، از کجا باید بدونم که چه مقداری رو توی فیلد مخفی فرم قرار بدم؟

MMSHFE
شنبه 15 بهمن 1390, 17:23 عصر
ایندکس هر Session برابر با آدرس صفحه ای هست که فرم توش بوده. موقع پردازش فرمها در صفحه نهایی هم میتونید با استفاده از Referer بفهمید از چه فرمی وارد صفحه مقصد شدین. درنتیجه اندیس رو دارین. فرم هم که مقدار token خودش رو با فیلد مخفی فرستاده. خوب همه چیز معلومه که! :چشمک:

idocsidocs
شنبه 15 بهمن 1390, 18:19 عصر
مهندس نشد !

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

حالا می خوام بدونم که وقتی یه آرایه ایجاد کردیم چطور باید سسشن مربوط به اون فرم رو توی فیاد مخفی قرار بدیم؟

MMSHFE
شنبه 15 بهمن 1390, 18:24 عصر
جان من یعنی انصافه دوباره Demo درست کنم؟ :چشمک: یکم روش فکر کنید اگه به نتیجه نرسیدین بگین دست بکار بشم. موفق باشید.

idocsidocs
شنبه 15 بهمن 1390, 18:37 عصر
بنظرم باید یه متغیر ایجاد کنم برابر با سسشن قرار بدم و این متغیر رو توی فیلد مخفی فرم نمایش بدم تا این مشکل هم برطرف بشه.

دوستان مرسی از راهنماییتون.

بحث خوبی بود.

MMSHFE
شنبه 15 بهمن 1390, 18:46 عصر
اگه نهایتاً به نتیجه نرسیدین، لطفاً خبر بدین تا یک نمونه درست کنم. امیدوارم از لحن پاسخ قبلی بنده ناراحت نشده باشین (شوخی بود، :چشمک: رو هم واسه همین گذاشتم).

idocsidocs
شنبه 15 بهمن 1390, 20:45 عصر
اگر همین روش که توضیح دادم درست باشه دیگه به نمونه کد نیازی ندارم.


امیدوارم از لحن پاسخ قبلی بنده ناراحت نشده باشین (شوخی بود، :چشمک: رو هم واسه همین گذاشتم).


چرا ناراحت بشم؟