اشتراکها
اشتراکها
SameSite Cookie و فایرفاکس
The new SameSite
behavior has been the default in
Firefox Nightly since Nightly 75 (February 2020). At Mozilla, we’ve
been able to explore the implications of this change. Starting with
Firefox 79 (June 2020), we rolled it out to 50% of the Firefox Beta user base. We want to monitor the scope of any potential breakage.
اشتراکها
Firefox 70 و پیشنهاد کلمهی عبور امن
اشتراکها
فایرفاکس و کار بر روی Sandbox آن
سلام
جایی دیدیم که نوعی از حملات هست که هکر تو یکی از پوشههای سایت (مثلا پوشه Images) یک اسکریپت یا یک صفحه asp قرار میده و کاربر رو به سایت خودش هدایت میکنه، یا اینکه یک عکس نشون میده
ظاهرا این حملات بیشتر برای استفاده از سایت هدف برای تبلیغات به کار میره
راه مقابله با این حملات چی میتونه باشه؟
این حملات به نام حملات CLRF شناخته میشن گویا
جایی دیدیم که نوعی از حملات هست که هکر تو یکی از پوشههای سایت (مثلا پوشه Images) یک اسکریپت یا یک صفحه asp قرار میده و کاربر رو به سایت خودش هدایت میکنه، یا اینکه یک عکس نشون میده
ظاهرا این حملات بیشتر برای استفاده از سایت هدف برای تبلیغات به کار میره
راه مقابله با این حملات چی میتونه باشه؟
این حملات به نام حملات CLRF شناخته میشن گویا
مطالب
ELMAH و حملات XSS
ASP.NET جهت مقابله با حملات XSS بطور پیشفرض از ورود تگهای HTML جلوگیری میکند و در صورتی که ورودی کاربر شامل این تگها باشد، HttpRequestValidationException صادر میگردد. لاگ کردن و بررسی این خطاها جهت آگاهی از وجود حمله بی اهمیت نیست. اما متأسفانه ELMAH که به عنوان معمولترین ابزار ثبت خطاها کاربرد دارد این نوع Exceptionها را ثبت نمیکند. دلیل آن هم این است که ELMAH در رویههای درونی خود اقدام به خواندن ورودیهای کاربر میکند و در این هنگام اگر ورودی کاربر نامعتبر باشد، Exception مذکور صادر میشود و فرصتی برای ادامه روند و ثبت خطا باقی نمیماند. به هر حال ضروری است که این نقیصه را خودمان جبران کنیم. راه حل افزودن یک فیلتر سفارشی برای ثبت خطاها به شکل زیر است (ASP.NET MVC):
فیلتر فوق باید در Global.asax معرفی شود:
به این ترتیب HttpRequestValidationException هم بعد از این در سیستم ELMAH ثبت خواهد شد.
public class ElmahRequestValidationErrorFilter : IExceptionFilter { public void OnException(ExceptionContext context) { if (context.Exception is HttpRequestValidationException) ErrorLog.GetDefault(HttpContext.Current).Log(new Error(context.Exception)); } }
public static void RegisterGlobalFilters (GlobalFilterCollection filters) { filters.Add(new ElmahRequestValidationErrorFilter()); filters.Add(new HandleErrorAttribute()); }
فرم هایی که اطلاعاتی را از یک کاربر دریافت کرده و به سمت سرور Post میکنند، از مهمترین اجزای لاینفک یک وب سایت میباشند. بی شک همهی ما از چنین فرمهایی حتی در یک پروژهی هرچند کوچک استفاده کردهایم. ممکن است هنگام ارسال این فرمها، کاربری شیطنت به خرج داده و درون یکی از فیلدهای فرم، از عبارتهای HTML و یا یک اسکریپت استفاده کرده باشد. در ASP.Net + MVC از مکانیزم ValidationRequest برای مقابله با چنین حملاتی (XSS) استفاده شده است.
یک فرم با یک Textbox در یک صفحه قرار دهید و درون Textbox یک تگ HTML بنویسید و آنرا به سرور ارسال کنید، در حالت پیش فرض اتفاقی که خواهد افتاد اینست که با یک صفحهی خطا روبرو خواهید شد که به شما هشدار میدهد دادههای ارسال شده، دارای مقادیر غیرمجازی میباشند. شما میتوانید این مکانیزم اعتبارسنجی-امنیتی را غیرفعال کنید. برای غیرفعال کردن آن هم در لینکی که در فوق معرفی گردید توضیحات کافی داده شده است. ولی توصیه میشود برای جلوگیری از حملات XSS هیچگاه این مکانیزم را غیرفعال نکنید، مگر اینکه هیچ دادهای را بدون Encode کردن در صفحه نمایش ندهید.
راههای زیادی برای هندل کردن این خطا و مطلع کردن کاربر وجود دارند و معمولا از صفحهی خطای سفارشی برای اینکار استفاده میشود. اما ایدهی بهتری نیز برای مقابله با این خطا وجود دارد!
فرض کنید اطلاعات فرم شما از طریق Ajax به سرور ارسال میشود و نتیجه بصورت Json به مروگر برگشت داده میشود. در حالت معمول در صورت رخ دادن خطای فوق، سرور کد 500 را برگشت میدهد و تنها راه هندل کردن آن در رویداد error شئ Ajax شما میباشد؛ آنهم با یک پیغام ساده. ولی من ترجیح میدهم به جای صادر کردن خطای 500، در صورت وقوع این خطا آنرا بصورت یک خطای ModelState به کاربر نمایش دهم. به نظر من اینکار وجههی بهتری دارد و ضمنا لازم نیست در هر رویدادی این خطا را هندل کنید. برای رسیدن به این هدف هم چندین راه وجود دارد که سادهترین آنها اینست که یک ModelBinder سفارشی ایجاد کنید و با هندل کردن این خطا، یک پیام خطا را به ModelState اضافه کنید و بعد به MVC بگویید که از این ModelBinder برای پروژهی من استفاده کن. با این روش هرگاه کاربر دادهای حاوی کدهای HTML درون فیلدهای فرم وارد کرده باشد، بدون هیچ کار اضافهای وضعیت ModelState شما Invalid میشود و خطای مدل به کاربر نمایش داده خواهد شد.
ابتدا کلاسی برای ModelBinder سفارشی خود ایجاد کنید و از کلاس DefaultModelBinder ارث بری کنید. سپس با بازنویسی متد BindModel آن منطق خود را پیاده سازی کنید:
در این کلاس ابتدا سعی میکنیم بطور عادی کار را به متد BindModel کلاس پایه بسپاریم. اگر دادههای ارسال شده حاوی کد HTML نباشد، بدون هیچ خطایی Model Binding صورت میگیرد. ولی در صورتیکه کاربر در فیلدی، از کدهای HTML استفاده کرده باشد، یک خطای HttpRequestValidationException رخ خواهد داد که با هندل کردن آن هدف خود را تامین میکنیم.
برای اینکار در قسمت catch بلوک مدیریت خطا، ابتدا یک نمونه از کلاس ModelState را میسازیم. بعد پیام خطای مورد نظر خود را به Errorsهای آن اضافه میکنیم. حال باید یک زوج کلید/مقدار برای این ModelState تعریف کنیم و به bindingContext اضافه کنیم. کلید ما در اینجا نام مدل جاری و مقدار آن هم نام فیلدی از فرم است که سبب بروز این خطا شده است.
حالا نهایت کاری که باید انجام دهیم اینست که در رویداد Application_Start این مدل بایندیگ سفارشی را جایگزین مدل بایندیگ پیش فرض کنیم:
کار تمام است. از حالا به بعد در صورتیکه کاربر در فیلدهای هر فرمی از سایت شما از کدهای HTML استفاده کند دیگر خطایی رخ نمیدهد و فقط ModelState در وضعیت Invalid قرار میگیرد که میتوانید با قرار دادن یک ValidationMessage یا ValidationSummary به راحتی خطا را به کاربر نشان دهید.
یک فرم با یک Textbox در یک صفحه قرار دهید و درون Textbox یک تگ HTML بنویسید و آنرا به سرور ارسال کنید، در حالت پیش فرض اتفاقی که خواهد افتاد اینست که با یک صفحهی خطا روبرو خواهید شد که به شما هشدار میدهد دادههای ارسال شده، دارای مقادیر غیرمجازی میباشند. شما میتوانید این مکانیزم اعتبارسنجی-امنیتی را غیرفعال کنید. برای غیرفعال کردن آن هم در لینکی که در فوق معرفی گردید توضیحات کافی داده شده است. ولی توصیه میشود برای جلوگیری از حملات XSS هیچگاه این مکانیزم را غیرفعال نکنید، مگر اینکه هیچ دادهای را بدون Encode کردن در صفحه نمایش ندهید.
راههای زیادی برای هندل کردن این خطا و مطلع کردن کاربر وجود دارند و معمولا از صفحهی خطای سفارشی برای اینکار استفاده میشود. اما ایدهی بهتری نیز برای مقابله با این خطا وجود دارد!
فرض کنید اطلاعات فرم شما از طریق Ajax به سرور ارسال میشود و نتیجه بصورت Json به مروگر برگشت داده میشود. در حالت معمول در صورت رخ دادن خطای فوق، سرور کد 500 را برگشت میدهد و تنها راه هندل کردن آن در رویداد error شئ Ajax شما میباشد؛ آنهم با یک پیغام ساده. ولی من ترجیح میدهم به جای صادر کردن خطای 500، در صورت وقوع این خطا آنرا بصورت یک خطای ModelState به کاربر نمایش دهم. به نظر من اینکار وجههی بهتری دارد و ضمنا لازم نیست در هر رویدادی این خطا را هندل کنید. برای رسیدن به این هدف هم چندین راه وجود دارد که سادهترین آنها اینست که یک ModelBinder سفارشی ایجاد کنید و با هندل کردن این خطا، یک پیام خطا را به ModelState اضافه کنید و بعد به MVC بگویید که از این ModelBinder برای پروژهی من استفاده کن. با این روش هرگاه کاربر دادهای حاوی کدهای HTML درون فیلدهای فرم وارد کرده باشد، بدون هیچ کار اضافهای وضعیت ModelState شما Invalid میشود و خطای مدل به کاربر نمایش داده خواهد شد.
ابتدا کلاسی برای ModelBinder سفارشی خود ایجاد کنید و از کلاس DefaultModelBinder ارث بری کنید. سپس با بازنویسی متد BindModel آن منطق خود را پیاده سازی کنید:
using System.Web; using System.Web.Mvc; using System.Web.Helpers; using System.Globalization; namespace Parsnet { public class ParsnetModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { try { return base.BindModel(controllerContext, bindingContext); } catch (HttpRequestValidationException ex) { var modelState = new ModelState(); modelState.Errors.Add("اطلاعات ارسالی شما دارای کدهای HTML میباشند."); var key = bindingContext.ModelName; var value = controllerContext.RequestContext.HttpContext.Request.Unvalidated().Form[key]; modelState.Value = new ValueProviderResult(value, value, CultureInfo.InvariantCulture); bindingContext.ModelState.Add(key, modelState); } return null; } } }
در این کلاس ابتدا سعی میکنیم بطور عادی کار را به متد BindModel کلاس پایه بسپاریم. اگر دادههای ارسال شده حاوی کد HTML نباشد، بدون هیچ خطایی Model Binding صورت میگیرد. ولی در صورتیکه کاربر در فیلدی، از کدهای HTML استفاده کرده باشد، یک خطای HttpRequestValidationException رخ خواهد داد که با هندل کردن آن هدف خود را تامین میکنیم.
برای اینکار در قسمت catch بلوک مدیریت خطا، ابتدا یک نمونه از کلاس ModelState را میسازیم. بعد پیام خطای مورد نظر خود را به Errorsهای آن اضافه میکنیم. حال باید یک زوج کلید/مقدار برای این ModelState تعریف کنیم و به bindingContext اضافه کنیم. کلید ما در اینجا نام مدل جاری و مقدار آن هم نام فیلدی از فرم است که سبب بروز این خطا شده است.
حالا نهایت کاری که باید انجام دهیم اینست که در رویداد Application_Start این مدل بایندیگ سفارشی را جایگزین مدل بایندیگ پیش فرض کنیم:
ModelBinders.Binders.DefaultBinder = new ParsnetModelBinder();
کار تمام است. از حالا به بعد در صورتیکه کاربر در فیلدهای هر فرمی از سایت شما از کدهای HTML استفاده کند دیگر خطایی رخ نمیدهد و فقط ModelState در وضعیت Invalid قرار میگیرد که میتوانید با قرار دادن یک ValidationMessage یا ValidationSummary به راحتی خطا را به کاربر نشان دهید.