Friday, December 09, 2011

چگونه در یک فرم MVC مانع حملات از نوع CSRF شویم؟

هنگامی که در MVC فرمی را برای عملیاتی مثل ذخیره سازی یا ویرایش به سرور ارسال می کنید، در صورتی که کاربر در فرم از تگهای Html یا کدهای JavaScript  استفاده کرده باشد ، کنترلر بصورت پیش فرض آن تگ یا کد را خطرناک تشخیص می دهد و خطای زیر را ارسال می کند :

A potentially dangerous Request.Form value was detected from the client

حتی اگر کد Html شما خطرناک هم نباشد ، باز هم این خطا داده می شود، مثلا در شکل زیر تنها یک تگ B وجود دارد که متن را توپر می کند ولی باز هم خطا صادر می شود :






این خطا از لحاظ امنیتی به ما کمک می کند تا جلو کدهای احیانا مخربی را که هکرها وارد می کنند ، بگیریم ولی گاهی اوقات لازم است که ما کد Html را دریافت کنیم ، مثلا اگر شما می خواهید به کاربر اجازه درج محتویات یک صفحه خبر و یا ارسال یک ایمیل را بدهید که معمولا یک ویرایشگر متنی در اختیار کاربر قرار می گیرد که کد html تولید می کند

برای حل این مشکل از عبارت  (ValidateInput(false استفاده می شود که باعث می شود ، اعتبارسنجی روی تگهای Html یا کدهای دریافت شده صورت نگیرد. در این حالت کنترلر بصورت زیر در می آید:


  [ValidateInput(false)]
        public ActionResult NewEmail(FormCollection form)
        {
اما با اینکار عملا راه را برای حمله های امنیتی از نوع Cross Site Request Forgery باز کرده ایم . این حمله ها به این صورت انجام می شود که هکر با ارسال فرمی که خودش ساخته است و قرار دادن کدهایی در آن ،  باعث ربوده شدن اطلاعاتی مثل Session از کامپیوتر کاربر می شود .

برای پیشگیری از این نوع حملات شما باید یک token از نوع encrypted تولید می کند که تنها توسط کنترلر قابل اعتبار سنجی است . بنابراین شما در ابتدای فرم خود ،  آن token را بصورت زیر تولید می کنید  :
 @using (Html.BeginForm("NewEmail""Emails"FormMethod.Post))
    {
        @Html.AntiForgeryToken()
و سپس در کنترلر خود آن را با عبارت [ValidateAntiForgeryToken] بررسی می کنید تا مطمئن شوید که مقادیر این فرم توسط برنامه خود شما تولید شده است. 

  [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        public ActionResult NewEmail(FormCollection form)
        {

No comments: