امنیت در ASP.Net MVC

دوشنبه 26 مرداد 1394

در این مقاله قصد داریم، ویژگی های امنیت در MVC را بررسی کنیم. تلاش ما بر این بوده که این مقاله هم برای افراد مبتدی و هم برای متخصصین در این زمینه مفید و مناسب باشد.

امنیت در ASP.Net  MVC

تیتر مطالبی که خواهیم گفت:

1. Cross Site Scripting >> XSS

2. Cross Site Request Forgery << CSRF

3. Authentication

   الف- Windows

   ب- Forms

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

در ادامه به هر یک از این تهدید ها و روش های جلوگیری از آنها می پردازیم:

Cross Site Scripting یا XSS:

XSS نوعی حمله است که در آن، کاربر مخرب سعی می کند به فیلدهای ورودی مانند Textbox و یا textarea، اسکریپت تزریق کند. این حمله می تواند سایت ما را با اجرای اسکریپت های ناخواسته تحت تاثیر قرار دهد. بنابراین باید، جلوی این حمله را بگیریم و به راه های به وجود آمدن آن توجه کنیم. از آنجا که XSS یک حمله متداول است، مایکروسافت امکاناتی را از پیش برای کنترل این اسکریپت ها در تگ های ورودی HTML تعبیه کرده است.

مثال زیر را در نظر بگیرید که در آن دو Textbox استفاده کرده ایم و می خواهیم اسکریپتی را به جای داده ورودی وارد کنیم.

زمانی که روی Ok کلیک کنیم، متد SaveData اجرا می شود و یک aspx view برمی گرداند.

public ActionResult Savedata(Customer c)  
{  
   //Save logic  
   return View("SavedataAspx",c);  
} 

زمانی که سعی کردیم تگ <b> را وارد کنیم، با این خطا مواجه شدیم. که این خطا می گوید، فردی سعی دارد، اسکریپت خطرناکی وارد کند. این تهدید به سادگی توسط Net Framework. مدیریت می شود.

اما حالتی را در نظر بگیرید که بخواهیم از این تگ ها برای استایل دادن به متن ورودی استفاده کنیم. یعنی می خواهیم به این تگ ها اجازه وارد شدن بدهیم اما به عنوان داده و نه به عنوان یک کد قابل اجرا.

در این مورد، باید این تگ ها را اعتبارسنجی نکرده و بعد از رمزگذاری چاپ کنیم. که این کار با تنظیم صفت متد SaveData امکان پذیر است.

    [ValidateInput(false)]
    public ActionResult Savedata(Customer c)  
    {  
       return View("SavedataAspx",c);  
    }  

توجه داشته باشید که این کار می تواند در سطح سراسری هم انجام شود، به عبارت دیگر با تنظیم در webconfig انجام شود.

    <httpRuntime requestValidationMode="2.0"/>  

بعد از تنظیم این صفت، خطای قبلی دیگر رخ نمی دهد. اما به جای آن سعی می کند اسکریپت های وارد شده در Textbox را اجرا کند. این تنها زمانی درست است که view ما از نوع aspx. باشد.

 

خروجی:

                                  

برای چاپ خروجی به شکل بالا، نیاز داریم که از متد ()Server.HtmlEncode به صورت زیر استفاده می کنیم.

<%=Server.HtmlEncode(Model.CustomerAddr) %>  

خروجی:

اما اگر Razor View Engine را بازگردانیم به صورت اتوماتیک به وسیله ی متد Html helper برای نوع ورودی رمزگذاری می شود.

خروجی:

                             

به یاد داشته باشید زمانی که از Razor Engine استفاده می کنید با کد گذاری داده ها به عنوان یک رفتار پیش فرض از حمله  Cross Site Scripting جلوگیری می شود. اما با Aspx engin حمله Cross Site Scripting به عنوان یک رفتار پیش فرض ممکن است.

  درمواردی که می خواهید اسکریپتی را درRazor اجرا کنید می توانید از

.@Html.Raw(Model.CustomerAddr) استفاده کنید

CSRF که مخفف عبارت Cross site request forgery است، دومین تهدید مهم در برنامه تحت وب می باشد و همچنین یک اشکال امنیتی در برنامه نویسی وب می باشد.

 CSRF

حمله  CSRF رایج ترین حمله ای است که امروزه شناخته شده است. ممکن است آگهی هایی را که به طور ناگهانی روی برخی از صفحات وب ظاهر می شود دیده باشید. زمانی که روی پنجره آگهی کلیک می کنیم. ما را به یک سری URL هدایت می کند و دوباره به وب سایت اصلی برمی گرداند.فکر می کنیم که این فقط یک پنجره آگهی است در حالی که تصور ما غلط است.در واقع این لینک ها برای هک داده های ما یا قرار دادن برخی از داده های نامعتبر در وب سایت ما است. جایی که ما بدون اطلاع به وب سایت های دیگر هدایت می شویم و داده های ما هک می شود، به آن Cross Site Request Forgery  گفته می شود.

 

 

حال یک نسخه ی نمایشی کوچک از اینکه  چگونه forgery (هک شدن داده ها) رخ می دهد را نشان می دهیم.

1. برنامه فعلی http://localhost:44247/Home/Index را اجرا کنید.

2. روی صفحه راست کلیک کنید و گزینه ی view source را انتخاب کنید.

3.تنها تگ form را کپی کنید و آن را در در یک صفحه جدید HTML ذخیره کنید. توجه داشته باشیدکه این صفحه ی جدیدی که ایجاد کردید نیاز نیست حتما در همان پروژه باشد در برنامه های مختلف دیگری می تواند ایجاد شود.همه ی صفت ها وتگ های اضافی را حذف کنید و تنها کنترل های input را نگه دارید، action باید آدرس کامل باشد مثل  

URL : http://localhost:44247/Home/SaveData 

همانطور که در کد زیر نشان داده شده است.

<form action=" http://localhost:44247/Home/SaveData" method="post" style=”display:none;”><input name="CustomerId" type="text" value="1000" /> <br />   
    <input id="CustomerName" name="CustomerName" type="text" value="HACK" /> <br />   
    <textarea cols="20" id="CustomerAddr" name="CustomerAddr" rows="2">  
    HACK   
    </textarea>   
</form> 

کد جاوا اسکریپت زیر را به صفحه خود اضافه کنید.

<script type="text/javascript">  
function fnCall() {  
   window.setTimeout(function(){ window.document.getElementById("btnok").click();   
   }, 2000);  
}  
window.onload = fnCall();  
</script> 

4. به طور دلخواه یک متنی را داخل TextBox قرار دهید. برای مخفی کردن فرم از دیگران تگ استایل را display:none قرار دهید .

فایل HTML را با هر نامی مانند Ad.html ذخیره کنید.

5.فایل HTML را اجرا کنید.

در حال حاضر چون متد Post را روی وب سایت اصلی خود مشخص کرده ایم،  به وب سایت خودمان هدایت می شود و متد SaveData  را اجرا خواهد کرد.

خروجی به شکل زیر خواهد شد.

                     

در حال حاضر ما می توانیم  به وب سایت شما دسترسی پیدا کنیم و برخی از داده های مخرب را به آن ارسال کنیم. حالتی را در نظر بگیرید که شما یک عبارت منطقی در این متد ذخیره کرده باشید که شامل یک فیلد باشد که مقداری را می پذیرد. این یک حمله  Cross Site Request Forgery نامیده می شود. از این حمله با استفاده از یک توکن به نام  AntiForgeryToken در MVC مقابله شده است.

زمانی که داده ها را به سرور ارسال می کنیم. یک token key کنار داده هایی که همیشه اعتبار سنجی خواهند شد نگه می دارد.این کار در MVC در دو مرحله ساده صورت می گیرد.

1.متد Htmlhelper را در تگ فرم به شکل  @Html.AntiForgeryToken().

اضافه می کنیم. این تکه کد یک Token key روی View اضافه می کند.

2. صفت ValidateAntiForgeryToken روی متد Savedata  اضافه کنید.این صفت، کلیدی که در Post ارسال شده اعتبار سنجی می کند.

[ValidateInput(false)]  
[ValidateAntiForgeryToken]  
public ActionResult Savedata(Customer c)  
{  
   // return View("SavedataAspx",c);  
   return View("Savedata", c);  
}  

در کد زیر مشاهده می کنید که token key چطور به نظر می رسد.

 

اگر فایل Ad.html اجرا کنیم با خطای زیر مواجه می شویم.

 

Authentication(احراز هویت)

مورد سومی که ما به طور معمول در وب سایت خود نیاز داریم احراز هویت می باشد.

احراز هویت در MVC شبیه به احراز هویت در ASP.Net می باشد. اما نحوه نگارش آن ها متفاوت است.روش های مختلفی برای احراز هویت وجود دارد.در ادامه درباره ی هریک از این ها صحبت می کنیم.

1..احراز هویت ویندوز

این به طور  عمده برای برنامه های کاربردی اینترانت استفاده می شود.

در زیر روشی برای فعال کردن احراز هویت ویندوز ارائه می دهیم.

1.به فایل webconfig می رویم و Authentication mode را برابر windows  قرار می دهیم.

همانند کد زیر

 

<system.web>  
   <authentication mode="Windows"></authentication>  
</system.web>  

2.به طور پیش فرض Windows Authentication غیر فعال می باشد. به properties پروژه بروید و آن را enable کنید

 

3. این، احراز هویت ویندوز شما را فعال می کند. بنابراین زمانی که سعی می کنید، از طریق URL به متدی دسترسی پیدا کنید. یک پنجره احراز هویت مانند شکل زیر نشان داده خواهد شد.

اعتبار ویندوز خود را وارد کنید  هرچیزی برای شما کار می کند.

احراز هویت در فرم ها:

حال، درباره احراز هویت در فرم ها بحث می کنیم. این نوع از احراز هویت معمولا در برنامه های کاربردی اینترنتی استفاده می شود. روال زیر را دنبال کنید.

Authentication mode .1 را در webconfig تنظیم کنید. همچنین URL پیش فرض لاگین را نیز تنظیم کنید. این URL باید نام controller و یا Action Method باشد.

<system.web>  
   <authentication mode="Forms">  
      <forms loginUrl="Account/Index" timeout="2000"></forms>  
   </authentication>  
</system.web>  

2. یک کلاس مدل به نام LoginDetail ایجاد نمایید.

public class LoginDetail  
{  
   Required]  
   public string UserName { get; set; }  
  
   [Required]  
   public string Password { get; set; }  
}  

3. یک  controller به نام AccountController و یک متد به نام Index ایجاد کنید و View برای نشان دادن صفحه ورود به سیستم از نوع LoginDetail اضافه کنید.

صفت [AllowAnonymous] را به کنترل کننده کلاس همچنین می توانید در سطح (actionmethod ) اضافه کنید.

namespace SecurityProj.Controllers  
{  
    [AllowAnonymous]  
    public class AccountController : Controller  
    {  
  
          
        public ActionResult Index()  
        {  
            return View();  
        }  
  
        public ActionResult Login(LoginDetail user)  
        {  
            if (user.UserName == "pradeep" && user.Password == "123")  
            {  
                System.Web.Security.FormsAuthentication.SetAuthCookie(user.UserName, false);  
                return RedirectToAction("Index", "Home");  
            }  
            return View("Index");  
              
        }  
  
    }  
}  

همانطور که در کد  متد Login می بینید، فقط برای نام کاربری و رمز عبور خاص که تنها جنبه نمایشی دارد، این اعتباررا چک کردیم. چرا نیاز داریم که کوکی ها را تنظیم کنیم؟

هنگامی که این کوکی تنظیم شود، درخواست دوباره احراز هویت نمی شود و معتبر در نظر گرفته خواهد شد.

4. صفت [Authorize] را فقط برای متدهایی که از Authentication استفاده می کنند، تنظیم نمایید.

5. پروژه را اجرا کنید و به مسیر Home/Index بروید. مشاهده خواهید کرد که به صفحه Account/Login هدایت می شوید. این به این دلیل می باشد که متد یا Home controller خود را روی Authorize تنظیم کرده اید. پس تلاش می کند تا آن را تصدیق کند. هنگامی که به درستی از Login/Index احراز هویت شد، می توانید صفحه سایت را مشاهده کنید.

به یاد داشته باشید که هر کدام از متدهایی که نمی خواهید تحت پروسه احراز هویت باشند، می توانید به وسیله اضافه کردن صفت [AllowAnonymous] آن ها را مشخص کنید.

اگر شما می خواهید کوکی هایی که توسط فراخوانی FormsAuthentication.SetAuthCookie ایجاد می شوند را بررسی کنید، می توانید از متد ASPXAUTH که در زیر نشان داده شده است استفاده کنید

به همین روش، برای حذف کردن کوکی شما می توانید بر روی گزینه logoff کلیک کنید.

همانطور که مشاهده نمودید، ما نیاز به صفت Authorize در سطح controller داریم. اما این کار را انجام نمی دهیم زیرا کل وب سایت ما به احراز هویت نیاز دارد، بنابراین با منطق خود و طبق نیازمان کلاسی می نویسیم که فیلترهای سفارشی دارد و در آن از کلاس AuthorizeAttribute ارث بری می کنیم.

public class MyCustomAuth : AuthorizeAttribute  
{  
   public override void OnAuthorization(AuthorizationContext filterContext)  
   {  
      //Check over here  
      base.OnAuthorization(filterContext);  
   }  
}  

این کلاس را در Global.asax ثبت کنید.

اکنون  authentication، سراسری برای همه ی درخواست های ActionMethod عملی خواهد شد.

 

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید