جلوگیری از حملات CSRF و XSS
بسم الله الرحمن الرحیم
جلوگیری از حملات CSRF و XSS
CSRF و XSS چیست
مثل همیشه با یک مثال این موضوع را بررسی خواهیم کرد، تصور کنید قرار است یک کد ساده برای ویرایش اطلاعات بنویسیم
public class UserProfileController : Controller
{
public ViewResult Edit() { return View(); }
public ViewResult SubmitUpdate()
{
// Get the user's existing profile data (implementation omitted)
ProfileData profile = GetLoggedInUserProfile();
// Update the user object
profile.EmailAddress = Request.Form["email"];
profile.FavoriteHobby = Request.Form["hobby"];
SaveUserProfile(profile);
ViewData["message"] = "Your profile was updated.";
return View();
}
}
در کد بالا ما ابتدا یک View را برای کاربر برمی گردانیم که قرار است اطلاعات آن را ویرایش کند، تصور کنید این View تغییر اطلاعات کاربری باشد. طبیعتا کاربر هنگامی که فرم اطلاعاتی را تکمیل کرد آن را Submit می کند. در این جا هیچ مشکلی نیست، البته به نظر می رسد!.
بسم الله الرحمن الرحیم
جلوگیری از حملات CSRF و XSS
CSRF و XSS چیست
مثل همیشه با یک مثال این موضوع را بررسی خواهیم کرد، تصور کنید قرار است یک کد ساده برای ویرایش اطلاعات بنویسیم
public class UserProfileController : Controller
{
public ViewResult Edit() { return View(); }
public ViewResult SubmitUpdate()
{
// Get the user's existing profile data (implementation omitted)
ProfileData profile = GetLoggedInUserProfile();
// Update the user object
profile.EmailAddress = Request.Form["email"];
profile.FavoriteHobby = Request.Form["hobby"];
SaveUserProfile(profile);
ViewData["message"] = "Your profile was updated.";
return View();
}
}
در کد بالا ما ابتدا یک View را برای کاربر برمی گردانیم که قرار است اطلاعات آن را ویرایش کند، تصور کنید این View تغییر اطلاعات کاربری باشد. طبیعتا کاربر هنگامی که فرم اطلاعاتی را تکمیل کرد آن را Submit می کند. در این جا هیچ مشکلی نیست، البته به نظر می رسد!.
فکر کنید یک فرد مبتدی بخواهید سایت شما را هک کند، در تست امنیت یک وب سایت می بایست ابتدا نقاط ضعف وب سایت ها را بررسی کرد. یکی از پر آسیب پذیرترین اشتباهات همین دستور بالا است که توسط ما نوشته شده است.
کد زیر را در نظر بگیرید:
<body onload="document.getElementById('fm1').submit()">
<form id="fm1" action="http://yoursite/UserProfile/SubmitUpdate" method="post">
<input name="email" value="hacker@somewhere.evil" />
<input name="hobby" value="Defacing websites" />
</form>
</body>
این کد یک کد ساده است که فرم اطلاعات را برای سرور ما ارسال می کند، اگر این اطلاعات ارسال شود چه اتفاقی می افتد ما آن را در پایگاه داده خود ثبت می کنیم! خیلی ساده به نظر می رسد اما همین دلیل ساده باعث می شود سایت های زیادی روزانه hack شوند.
یکی از راه های ساده و معمولی که MVC برای جلوگیری از حملات CSF پیشنهاد می کند استفاده از تگ AntyForgeryToken است. معمولا در تمامی مثال هایی که توسط مایکروسافت ارائه می شود این تگ قرار داده می شود، شما نیز تاکنون باید این تگ را مشاهده کرده باشید.
در ASP.NET MVC تنها درخواست های POST توسط AntiForgeryToken محافظت می شود.
@using(Html.BeginForm())
{
<p>
@@Html.AntiForgeryToken()
</p>
}
نتیجه اضافه شدن دستورات بالاتگ های زیر است که باعث می شود وقتی Form ایی برای یک کاربر ارسال می شود آن فرم منحصر به فرد باشد در نتیجه وقتی شما دستور هک بالا را بخواهید اجرا کنید خطای زیر را دریافت خواهید کرد.
A required anti-forgery token was not supplied or was invalid.
این خطا بدین معنا است که سرور چنین فرمی را برای کاربران ارسال نکرده است پس شما نمی توانید این فرم را برای سرور مجددا POST کنید
<form ..>
...
<input type="hidden"
name="__RequestVerificationToken">
value="d1Hh28W3uTpdZcEG0VhEkYg7D5XqFM9Sm4iA2e/cXgrOIIpPDENi1lVBg6mYLBAAoGk0q5RA/EPE2o6W5VAqd
ziURtyqcdFrEcDmSID4vtOF+Nm2Zgf5EJRoRCTUzWvEgcffCvWgfATcznKjnZExjGcbMYQKLhkWBKydzzi4/UE="
</form>
و همچنین در بالای Action هاباید به صورت زیر به کار گرفته شود:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(Model model)
{
...
}
اگر بخواهید در برنامه خود فرم های مختلف را از یکدیگر محافظت کنید، یعنی حتی فرم های مختلف یک برنامه قابلیت دریافت توسط Action دیگری را نداشته باشند کافی است که به صورت زیر عمل کنید:
@Html.AntiForgeryToken("someArbitraryString")
و در قمست Action کد خود باید دستور زیر را بنویسید.
[ValidateAntiForgeryToken(Salt="someArbitraryString")]
public ViewResult SubmitUpdate()
{
// ... etc
}
همانطور که مشخص است همه چیز مانند حالت پیش فرض است با این تفاوت که تنها یک String با عنوان someArbitraryString اضافه شده است. به این رشته Salt گفته میشود.
Salt چیز خاصی نیست بلکه تنها یک String است که شما آن را برای کاربر ارسال و سپس آن را مجددا دریافت می کنید.
neda
ممنون
اسماعیلشیدایی
باعرض سلام
بر اساس خطای رخ داده مشخصا، شما مقدار کلید ValidateAntiForgeryToken را مقدار ثابتی قرار داده اید به همین دلیل خطای مشخص شده رخ داده است.
سعی خواهم کرد انشالله تا چند روز آتی، آموزش ساخت Dynamic salt را بروی سایت قرار خواهم داد
موفق باشید
neda
وقتی از salt برای AntiForgeryToken استفاده میکنم خطا دارم
همیشه از AntiForgeryToken برای فرم ها استفاده می کردم
ولی از salt نه
اسماعیلشیدایی
با عرض سلام
لطفا خطای خود را در اینجا قرار دهید، تا بتوانیم مشکل را بررسی کنیم.
موفق باشید