15-01-1395، 10:45 ق.ظ
در این مدت کوتاه که از ارائه آموزش تصویری Yii2 میگذره، دوستان زیادی تقاضا داشتن که بخشهای مختلف رو با توضیحات بیشتری تکمیل کنیم. در همین راستا آموزشهای جدید درحال تدوین هست که خریداران محترم میتونن بدون هزینه اضافه اونها رو با شناسه خریدشون دانلود کنن.
یکی از این مباحث، موضوع بسیار مهمی در زمینه امنیت تحت عنوان جلوگیری از حملات Cross-Site Request Forgery یا به اختصار CSRF هست. این نوع حمله یکی از آسیبپذیریهای رایج در حوزه وب هست. در این نوع حمله، فرض بر این هست که کاربر ازطریق یک سایت قانونی واردشده. بعد این کاربر سایت هکر رو بازدید میکنه درخواستهایی رو به سایت اصلی ازطریق جاوااسکریپت، فرم، تگ <img src=" یا هر روش دیگه، ارسال میکنه. در این روش، نفوذگر میتونه بعنوان مثال رمز کاربر رو Reset کنه یا پول رو از حساب بانکی کاربر جابجا کنه (البته اگه سایت بانک امنیت نداشته باشه).
یکی از راههای جلوگیری از این نوع حملات، استفاده از یک شناسه (توکن) خاص برای اعتبارسنجی منبع درخواستهاست. Yii بطور پیشفرض این قابلیت رو داره. میتونید اون رو با ساخت یک فرم ساده و ارسالش تست کنید:
خطای زیر رو دریافت خواهید کرد:
علت این خطا اینه که توی هر درخواست، Yii یک شناسه خاص غیرتکراری تحت عنوان توکن میسازه که شما باید اون رو همراه دادههای درخواستتون بفرستین. بنابراین وقتی یه درخواست ارسال میکنید، Yii شناسه ارسالشده و تولیدشده رو با هم مقایسه میکنه. اگه با هم یکی باشن Yii به بررسی درخواست ادامه میده وگرنه خطای فوق تولید خواهد شد.
توکن تولیدشده، در درسترس سایت نفوذگر نیست و درنتیجه نمیتونه همراه درخواستهاش بفرسته.
یک نکته مهم اینه که چککردن توکن توی درخواستهای Get بررسی نمیشه. مثال:
با ارسال فرم بالا، خطایی رخ نمیده. علت این موضوع اینه که جلوگیری از CSRF فقط برای درخواستهای خطرناک مثل Put و Post و Delete کار میکنه. علت اینکه عملیات مهم مثل حذف رکوردها و... رو نباید با درخواست Get مدیریت کنید هم همین موضوعه.
غیرفعال کردن CSRF Protection
گاهی اوقات لازمه که این قابلیت رو غیرفعال کنید (برای مثال موقع بازگشت از درگاه بانکی و دریافت نتایج بانک که بصورت Post ارسال میشه). برای این کار باید فیلد خاصی به اسم $enableCsrfProtection رو با مقدار false تنظیم کنید:
گاهی اوقات هم فقط توی یه اکشن خاص از یک کنترلر (نه همه اکشنها) نیاز هست که CSRF Protection رو غیرفعال کنید (هیچوقت این قابلیت رو بطور کامل غیرفعال نکنید). برای اینکار باید بصورت زیر عمل کنید:
اضافهکردن CSRF Protection به فرم
این قابلیت بطور پیشفرض فعاله و شما فقط نیاز دارین که شناسه توکن مربوطه رو به فرم اضافه کنید. برای اینکار کافیه یک عنصر مخفی به فرمتون اضافه کنید:
البته با کمک کلاس yiihelpersHtml زندگی خیلی قشنگتر میشه:
البته اگه از ActiveForm برای تولید فرم استفاده کرده باشین، نیازی به این کار نیست و توکن بطور خودکار به فرم اضافه خواهد شد.
یکی از این مباحث، موضوع بسیار مهمی در زمینه امنیت تحت عنوان جلوگیری از حملات Cross-Site Request Forgery یا به اختصار CSRF هست. این نوع حمله یکی از آسیبپذیریهای رایج در حوزه وب هست. در این نوع حمله، فرض بر این هست که کاربر ازطریق یک سایت قانونی واردشده. بعد این کاربر سایت هکر رو بازدید میکنه درخواستهایی رو به سایت اصلی ازطریق جاوااسکریپت، فرم، تگ <img src=" یا هر روش دیگه، ارسال میکنه. در این روش، نفوذگر میتونه بعنوان مثال رمز کاربر رو Reset کنه یا پول رو از حساب بانکی کاربر جابجا کنه (البته اگه سایت بانک امنیت نداشته باشه).
یکی از راههای جلوگیری از این نوع حملات، استفاده از یک شناسه (توکن) خاص برای اعتبارسنجی منبع درخواستهاست. Yii بطور پیشفرض این قابلیت رو داره. میتونید اون رو با ساخت یک فرم ساده و ارسالش تست کنید:
<form method="POST"> <input type="submit" value="ok!"> </form>
خطای زیر رو دریافت خواهید کرد:
نقل قول:Bad Request (#400)
Unable to verify your data submission.
علت این خطا اینه که توی هر درخواست، Yii یک شناسه خاص غیرتکراری تحت عنوان توکن میسازه که شما باید اون رو همراه دادههای درخواستتون بفرستین. بنابراین وقتی یه درخواست ارسال میکنید، Yii شناسه ارسالشده و تولیدشده رو با هم مقایسه میکنه. اگه با هم یکی باشن Yii به بررسی درخواست ادامه میده وگرنه خطای فوق تولید خواهد شد.
توکن تولیدشده، در درسترس سایت نفوذگر نیست و درنتیجه نمیتونه همراه درخواستهاش بفرسته.
یک نکته مهم اینه که چککردن توکن توی درخواستهای Get بررسی نمیشه. مثال:
<form method="GET"> <input type="submit" value="ok!"> </form>
با ارسال فرم بالا، خطایی رخ نمیده. علت این موضوع اینه که جلوگیری از CSRF فقط برای درخواستهای خطرناک مثل Put و Post و Delete کار میکنه. علت اینکه عملیات مهم مثل حذف رکوردها و... رو نباید با درخواست Get مدیریت کنید هم همین موضوعه.
غیرفعال کردن CSRF Protection
گاهی اوقات لازمه که این قابلیت رو غیرفعال کنید (برای مثال موقع بازگشت از درگاه بانکی و دریافت نتایج بانک که بصورت Post ارسال میشه). برای این کار باید فیلد خاصی به اسم $enableCsrfProtection رو با مقدار false تنظیم کنید:
class MyController extends Controller { public $enableCsrfProtection = false;
گاهی اوقات هم فقط توی یه اکشن خاص از یک کنترلر (نه همه اکشنها) نیاز هست که CSRF Protection رو غیرفعال کنید (هیچوقت این قابلیت رو بطور کامل غیرفعال نکنید). برای اینکار باید بصورت زیر عمل کنید:
class MyController extends Controller { public function beforeAction($action) { if (in_array($action->id, ['incoming', 'callback'])) { $this->enableCsrfValidation = false; } return parent::beforeAction($action); }
اضافهکردن CSRF Protection به فرم
این قابلیت بطور پیشفرض فعاله و شما فقط نیاز دارین که شناسه توکن مربوطه رو به فرم اضافه کنید. برای اینکار کافیه یک عنصر مخفی به فرمتون اضافه کنید:
<form action="..." method="POST"> <input id="form-token" type="hidden" name="<?= Yii::$app->request->csrfParam ?>" value="<?= Yii::$app->request->csrfToken ?>"/> <input type="submit" value="ok!"> </form>
البته با کمک کلاس yiihelpersHtml زندگی خیلی قشنگتر میشه:
<?= Html::beginForm(['controller/action']) ?> <?= Html::hiddenInput(Yii::$app->request->csrfParam, Yii::$app->request->csrfToken) ?> <?= Html::submitButton('ok!') ?> <?= Html::endForm() ?>
البته اگه از ActiveForm برای تولید فرم استفاده کرده باشین، نیازی به این کار نیست و توکن بطور خودکار به فرم اضافه خواهد شد.