امن سازی درخواستهای ایجکسی برنامههای ASP.NET MVC 5.x در مقابل حملات CSRF
نویسنده: اختیاری
تاریخ: ۱۳۹۶/۰۷/۲۰ ۱۹:۳۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
طی مقاله چک لیست تولید برنامه Asp.net mvc و بررسی امنیتی ایجکس هنگام استفاده در مورد چک لیست امنیتی
سایت سرفصلهای مهم عنوان و بررسی شده است که یکی از موارد، مقاوم ساختن وب اپلیکشن در برابر حملات CSRF میباشد. اینگونه حملات بر پایه این استراتژی شکل میگیرند که با
ارسال درخواستی به نیابت از سمت سیستم/مرورگر کاربر تایید هویت شده، سایت مقصد را مجبور
به انجام عملی کند. برای مثال اگر شما در سایت a.com یک
کاربر تایید شده باشید و هم اکنون در سایت فوق نیز لاگین باشید، مهاجم با ارسال یک برنامه/صفحه یا موارد مشابه و در قالب src یک
عکس یا با ترغیب شما با کلیک بر روی یک لینک با href آلوده یا موارد
مشابه، از سمت مرورگر شما درخواستی را به سمت سایت a.com ارسال میکند .
این درخواست ممکن است شامل حذف اطلاعات، تغییر مشخصات، پرداخت هزینه یا موارد مشابه باشد. جهت مقابله با این حمله، یکی از موارد مهم، استفاده همیشگی از Html.AntiForgeryToken() در تمامی فرمهای ورود اطلاعات است. همچنین استفاده همیشگی از متد Post و بررسی تایید مبدا درخواستهای ایجکسی، بررسی http referrer ، محدود کردن طول عمر کوکی، استفاده از کپچهای قوی مانند کپچای گوگل میتواند تا حد زیادی وب اپلیکیشن را در مورد اینگونه حملات، مصون کند.
در این بین یکی از موارد دیگر، اضافه کردن AntiForgeryToken به درخواستهای ایجکسی سایت میباشد. جهت حصول این منظور، راههای مختلفی موجود است. یکی از راه حلها استفاده از یک هلپر جهت تولید توکن مورد نظر است.
ساختار
هلپر مورد نظر به شرح زیر است :
public static class AntiForgeryToken
{
public static MvcHtmlString AntiForgeryTokenForAjaxPost(this HtmlHelper helper)
{
var antiForgeryInputTag = helper.AntiForgeryToken().ToString();
// Above gets the following: <input name="__RequestVerificationToken" type="hidden" value="some value" />
var removedStart = antiForgeryInputTag.Replace(@"<input name=""__RequestVerificationToken"" type=""hidden"" value=""", "");
var tokenValue = removedStart.Replace(@""" />", "");
if (antiForgeryInputTag == removedStart || removedStart == tokenValue)
throw new InvalidOperationException("Oops! The Html.AntiForgeryToken() method seems to return something I did not expect.");
return new MvcHtmlString($@"{"__RequestVerificationToken"}:""{tokenValue}""");
}
} function AddToCart(pid) {
$.ajax({
url: '@Url.Action("AddToBasket","Shop")',
data: { 'pid': pid,@Html.AntiForgeryTokenForAjaxPost() },
type: 'post',
success:function(e) {
//do something
}
});
} function addToken(data) {
data.__RequestVerificationToken = $("input[name=__RequestVerificationToken]").val();
return data;
} $.ajax({
// .....
data: addToken({ postId: postId }), // اضافه کردن توکن
dataType: "html", // نوع داده مهم است
// .....
}); data: { "pid": pid, "__RequestVerificationToken": $('[name=__RequestVerificationToken]').val() }, $(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$('body').bind('ajaxSend', function (elm, xhr, s) {
if (s.type == 'POST' && typeof securityToken != 'undefined') {
if (s.data.length > 0) {
s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
else {
s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
}
});
}); function addToken(data) {
data.__RequestVerificationToken = $("input[name=__RequestVerificationToken]").val();
return data;
} data: addToken ( { postId: postId } ) , // اضافه کردن توکن function addToken(data) {
data.__RequestVerificationToken = $("input[name=__RequestVerificationToken]").val();
data.postId=postId;
return data;
}