امنیت سایت با استفاده از CSP در ASP.Net MVC
چهارشنبه 29 مهر 1394در این مقاله قصد داریم بگوییم CSP چیست ، چگونه کار میکند، کجا استفاده می شود، دستورات آن چگونه است و ... . Content Security Policy یا CSP یک HTTP header جدید بزرگ است که کنترل میکند کجا یک مرورگر اجازه بارگذاری محتوا و چه نوع از محتوایی اجازه بارگذاری دارد.
در این مقاله قصد داریم بگوییم CSP چیست، چگونه کار میکند، کجا استفاده می شود، دستورات آن چگونه است و... .
Content Security Policy یا CSP یک HTTP headerجدید بزرگ است که کنترل میکند کجا یک مرورگر اجازه بارگذاری محتوا و چه نوع از محتوایی اجازه بارگذاری دارد. از یک white-list برای تشخیص مجوز بارگذاری محتواها استفاده میکند، هر محتوایی که در این لیست نباشد اجازه بارگذاری ندارد. یک کنترل دقیق بسیار خوب به ما می دهد و اجازه می دهد تا سایت خود را در sandbox مرورگر کاربران اجرا کنیم.
CSP همه چیز در مورد اضافه کردن یک لایه اضافی امنیتی به سایت شما با استفاده از استراتژی Defence in Depth است. به شناسایی و کاهش Cross Site Scripting و حملات تزریق داده های مختلف (various data injection attacks) مانند SQL injection کمک میکند.
در زیر یک نمونه از CSP HTTP header در کروم نشان داده شده است. شکل زیر یک نمونه پروژه MVC است که CSP درآن اعمال شده است. در اینجا از ASP.NET MVC Boilerplate برای ایجاد یک پروژه استفاده شده است که CSP در آن بکاربرده شده است.
قسمت آبی شده HTTP header را نشان می دهد. اساسا درباره مسدود کردن همه چیز بجز اسکریپتها، تصاویر، فونتها،درخواست های Ajax به فرم یا از فرم دامنه ی ما صحبت میکند و به اسکریپتهای مایکروسافت CDN و گوگل اجازه دسترسی می دهد.
برای مثال می خواهید فقط CSS ها ، JavaScript ها و تصاویر از دامنه بارگذاری شوند و بقیه چیزها مسدود شوند. همچنین اگر بخواهید پلاگین ها (Flash, Silverlight) یا فریم ها را مسدود کنید. با استفاده از این نوع سیاست امنیتی تنها راهی که یک مهاجم می تواند به سایت شما آسیب برساند استفاده از حمله XSS است، مهاجم می تواند به نحوی یک اسکریپت از دامنه را روی صفحات شما در فایل های اسکریپت جداگانه به صورت استایل های درون خط قرار دهد و به صورت پیش فرض توسط CSP مسدود نخواهد شد.
با CSP HTTP header بالا در محل اگر یک مهاجم موفق به تزریق اسکریپت شود، مرورگر خطاهای نقض CSP ارسال میکند و اسکریپتهای مخرب نمی توانند اجرا و حتی دانلود شوند. در زیر می توانید ببینید که در کروم چگونه دیده می شوند.
حتی بهتر آنکه، مرورگر هرگز در وهله اول اسکریپتهای مخرب را دانلود نمیکند. در پایین می توانید دو نمونه از Fiddler را با هم مقایسه کنید. سمت چپ نشان می دهد که فایل Script.js مخرب هرگز درخواست نشده بود اما یک نقض CSP به URL که نشان داده شده وارد شده است. در سمت راست سایتی بدون تاثیر از CSP را نشان می دهد . مرورگر سعی در دانلود اسکریپت مخرب دارد ، این یک نسخه نمایشی است به همین دلیل خطای 404 رخ می دهد.
دستورات CSP
تعدادی از دستورات برای استفاده در CPS وجود دارند.در اینجا Mozilla یک لیست کامل از دستورات و چگونگی استفاده از آنها دارد. هر کنترل دستور دسترسی به یک تابع خاص در مرورگر دارد. مهم ترین آنها را بررسی خواهیم کرد.
دستور default-src
دستور default-src به ما اجازه می دهد محدودیت هایی را به کار ببریم. برای مثال دستور CSP زیر روی انواع محتواهای دامنه سایت ما و همچنین TrustedSite.com تاثیر گذار است.
در حال حاضر Policy بالا بسیار سست است، به مرورگر اجازه بارگذاری Frame ها ، Ajax ، Web Socket ها ،فونت ها ، عکس ها ، صدا ها ، ویدیو ها ،درخواست ها ، Plugin ها ، Style ها و اسکریپتها را می دهد. ممکن است از بسیاری از گزینه های موجود در آن لیست استفاده نکنید. یک Policy بهتر همه چیز را به صورت پیش فرض مسدود میکند و فقط به منابع مطمئن که استفاده کردیده اید به صورت زیر اجازه دسترسی می دهد.
می توانید ببینید که default-src به None فرستاده شده است که به صورت پیش فرض همه چیز را مسدود میکند. سپس دستورات دیگری را اضافه کردیم که به اسکریپتهای TrustedSite.com و سبکها، عکسها، فونت ها، درخواست های Ajax و فرم های ارسالی به دامنه سایت ما اجازه بارگذاری می دهد. این روش امنیت و محدودیت بیشتری دارد اما نیاز است که درباره Policy سایت خود بیشتر فکر کنید.
دستور report-uri
دستور report-uri یک دستورالعمل خاص دیگر است. به مرورگر یک URL می دهد که جزئیات هر نقضی را با فرمت Json به یک CSP policyبفرستد. اهمیت زیادی دارد و به ما اجازه می دهد تا هرکس تلاش برای هک کردن سایت ما کرد متوجه شویم، به ما اجازه می دهد تا منابعی که به اشتباه مسدود شده اند را پیدا کنیم زیرا Policy ما بسیار محدود بوده و به اندازه کافی تست انجام ندادیم. در مثال زیر به مرورگر میگوییم خطای نقض CSP را با فرمت Json به WebResource.axd?cspReport=true بفرستد.
اگر در بالا اسکریپت مخرب بگیریم و با استفاده از CSP Policy آن را به صفحه خود اضافه کنیم، یک خطای نقض CSP رخ خواهد داد و Json بوسیله کروم به ما فرستاده می شود. توجه داشته باشید که مرورگرهای مختلف ، خطاها را با کمی تفاوت ارسال میکنند. بعضی مرورگرها و درواقع ورژنی از مرورگرها اطلاعات بیشتری نسبت به بقیه می دهند.
دستور style-src
همانطور که گفته شد سبک های درون خطی یا in-line styles زمانی که از CSP استفاده می شود اجازه استفاده ندارند زیرا باعث بروز ریسک برای حمله یک مهاجم که می تواند به یک صفحه در معرض خطر in-line style تزریق کند می شود. همه استایل ها باید از یک فایل CSS خارجی استفاده کنند.
یک راه توسعه برای این دستور است که استفاده از استایل های درون خط را مجاز میکند اما باید از آن پرهیز کرد زیرا نا امن است . در واقع در تنظیماتی که برای استایل قرار دادید دستور unsafe-inline را قرار می دهید.
دستور Script-src
همانند دستور style-src است ، باعث می شود به طور پیش فرض اسکریپتهای درون خطی ناشی از حملات XSS مسدود شوند. به غیر از اسکریپتهای درون خطی، تابع جاوا اسکریپت eval() نیز به صورت پیش فرض مسدود می شود.
مانند دستور style-src در اینجا هم یک راه برای فعال کردن اسکریپت درون خط که unsafe-inline نامیده می شود. اینجا یک دستور دیگر نیز با نام unsafe-eval وجود دارد که اجازه دسترسی به تابع eval را می دهد. یکبار دیگر تذکر داده می شود که باید از unsafe ها اجتناب کرد و در اینجا فقط برای آشنایی شما گفته شده است.
اگر تنظیمات بدی برای CSP قرار دهید می تواند بسیار خطرناک باشد. فرض کنید یک کاربر به سایت شما وارد می شود و میخواهد یک ویدیو youtube را از روی سایت شما تماشا کند و CSP ویدیو را مسدود کرده و کاربران فقط یک صفحه خالی میبینند ، مگر اینکه به اندازه کافی باهوش باشند و از ابزارهای مرورگر استفاده کنند. برای مبارزه با این مشکل ، W3C یک Content-Security-Policy-Report-Only HTTP header ایجاد کرده است. این ابزار همانند CSP است اما تنها از نقض های policy گزارش می دهد و موجب مسدود شدن هر چیزی در مرورگر نمی شود.
CSP برای ASP.NET MVC
چگونه می توان CSP را بر روی ASP.Net MVC پیاده سازی کرد. برای شروع نیاز دارید NWebsec.Mvc را در NuGet pakage نصب کنید.
NWebsec.Mvc یک مجموعه بزرگ از فیلترهای MVC است که می تواند به صورت سراسری در همه درخواست ها یا کنترلر ها یا اکشن ها(Actions) بکاربرده شود. NWebsec شامل یک سری از فیلترهای MVC می شود که از CSP پشتیبانی میکند.
در تصویر زیر CSP در ASP.NetMVC Boilerplate بکاربرده شده و کدهای استفاده شده برای ایجاد آن نمایش داده شده است. این Policy در تمام پاسخ های سایت بکاربرده شده است.
// Content-Security-Policy - Add the Content-Security-Policy HTTP header to enable Content-Security-Policy. GlobalFilters.Filters.Add(new CspAttribute()); // OR // Content-Security-Policy-Report-Only - Add the Content-Security-Policy-Report-Only HTTP header to enable logging of // violations without blocking them. This is good for testing CSP without enabling it. // To make use of this attribute, rename all the attributes below to their ReportOnlyAttribute versions e.g. CspDefaultSrcAttribute // becomes CspDefaultSrcReportOnlyAttribute. // GlobalFilters.Filters.Add(new CspReportOnlyAttribute()); // default-src - Sets a default source list for a number of directives. If the other directives below are not used // then this is the default setting. filters.Add( new CspDefaultSrcAttribute() { // Disallow everything from the same domain by default. None = true, // Allow everything from the same domain by default. // Self = true }); // connect-src - This directive restricts which URIs the protected resource can load using script interfaces // (Ajax Calls and Web Sockets). filters.Add( new CspConnectSrcAttribute() { // Allow AJAX and Web Sockets to example.com. // CustomSources = "example.com", // Allow all AJAX and Web Sockets calls from the same domain. Self = true }); // font-src - This directive restricts from where the protected resource can load fonts. filters.Add( new CspFontSrcAttribute() { // Allow fonts from example.com. // CustomSources = "example.com", // Allow all fonts from the same domain. Self = true }); // form-action - This directive restricts which URLs can be used as the action of HTML form elements. filters.Add( new CspFormActionAttribute() { // Allow forms to post back to example.com. // CustomSources = "example.com", // Allow forms to post back to the same domain. Self = true }); // img-src - This directive restricts from where the protected resource can load images. filters.Add( new CspImgSrcAttribute() { // Allow images from example.com. // CustomSources = "example.com", // Allow images from the same domain. Self = true, }); // script-src - This directive restricts which scripts the protected resource can execute. // The directive also controls other resources, such as XSLT style sheets, which can cause the user agent to execute script. filters.Add( new CspScriptSrcAttribute() { // Allow scripts from the CDN's. CustomSources = string.Format("ajax.googleapis.com ajax.aspnetcdn.com"), // Allow scripts from the same domain. Self = true, // Allow the use of the eval() method to create code from strings. This is unsafe and can open your site up to XSS vulnerabilities. // UnsafeEval = true, // Allow inline JavaScript, this is unsafe and can open your site up to XSS vulnerabilities. // UnsafeInline = true }); // style-src - This directive restricts which styles the user applies to the protected resource. filters.Add( new CspStyleSrcAttribute() { // Allow CSS from example.com // CustomSources = "example.com", // Allow CSS from the same domain. Self = true, // Allow inline CSS, this is unsafe and can open your site up to XSS vulnerabilities. // Note: This is currently enable because Modernizr does not support CSP and includes inline styles // in its JavaScript files. This is a security hold. If you don't want to use Modernizr, // be sure to disable unsafe inline styles. For more information see: // http://stackoverflow.com/questions/26532234/modernizr-causes-content-security-policy-csp-violation-errors // https://github.com/Modernizr/Modernizr/pull/1263 UnsafeInline = true });
توجه کنید که چگونه یک فیلتر MVC برای هر دستور CSP است. این واقعیت را باید در نظر گرفت که ممکن است بخواهید Action در یک کنترلر خاص توانایی نمایش ویدیوهای youtube را داشته باشد، توجه داشته باشید که youtube از iframe ها برای قرار دادن ویدیو ها استفاده میکند و mark-up را به صورت زیر قرار می دهد.
با استفاده از CSP policy بالا ، مرورگر کروم با خطای زیر مواجه می شود.
لازم است تا دستورات frame-src و child-srcرا اضافه کنیم تا بتوان در یک کنترلر خاص استفاده کرد. توجه داشته باشید که child-src یک دستور CSP 2.0 است و frame-src در CSP 2.0 منسوخ شد اما هنوز از آن برای مرورگرهای قدیمی استفاده میکنیم .
گرچه اگر بخواهیم به یک ویدیوی youtube برای یک Action نسبت به همه اکشن هادر یک کنترلر اجازه دهیم ، به سادگی صفتی را برای آن اکشن بجای کنترلر قرار می دهیم .
تنظیم کردن گزارش های نقض CSP کمی پیچیده است. لازم است تا فیلتر CspReportUriAttribute اضافه شود و یک تابع خاص در فایل Global.asax.cs برای رسیدگی به نقض اضافه شود که به صورت زیر نشان داده شده است.
CspViolationReport یک نماینده Json CSP Violation است که مرورگر برای شما ارسال میکند. شامل خاصیتهای متعددی می شود که درباره URL مسدود شده توضیح می دهد (دستور نقض ، عامل کاربری و ... ) .
پشتیبانی مرورگر
FireFox 23+ ، Chorme 25+ ، Safari 7+ مرورگرهای و Opera 15+ و ورژن بعدی IE از CSP HTTP header پشتیبانی میکنند.
تعدادی از مرورگرهای قدیمی از CSP با استفاده از X-Content-Security-Policy یا X-Webkit-CSP پشتیبانی می کردند اما این پیاده سازی های قدیمی مشکلاتی داشتند و نباید استفاده می شدند.
Content Security Policy (CSP) 2.0
یک Editors Draft در CSP 2.0 به وسیله استاندارهای W3C نوشته شد. هدف این ورژن پر کردن شکاف ها و اضافه کردن دستورات جدید برای کنترل کاربران وب ، فریم های جاسازی شده ، برنامه های کاربردی آشکار ، سندهای HTML بر پایه URL ، جایی که فرم ها ارسال می شوند و انواعی از پلاگین های مرورگر می توانند بارگذاری شوند. NWebsec از بیشتر این دستورات جدید پشتیبانی میکند.
CSP 1.0 دستورات unsafe-inline داشت که اجازه می داد از Style های درون خط و برچسب های اسکریپت استفاده شود اما بسیار خطرناک بود و CSP را تا اندازه ای بی معنی می کرد. این موضوع به مهاجمان توانایی می داد تا کدهایی را به سایت شما تزریق کنند و به سمت حمله های XSS کشیده شوند. استفاده از CSP 1.0 به معنای بارگذاری styleها و اسکریپتها از فایل های CSS وjavaScript جداگانه بود. CSP 2.0 دو راه جدید برای استفاده از in-line style ها و اسکریپتها معرفی کرد.
Nonces
Nonces کمی شبیه به Anti-forgery Token در ASP.net MVC کار میکند. یک رشته تصادفی رمزنگاری است که به سمت کلاینت در CSP HTTP header تولید و ارسال می شود و همچنین در HTML به همراهStyle یا برچسب اسکریپت مانند :
مرورگر فقط CSP 1.0 را پشتیبانی میکند و دستورات Nonce را نمی فهمد و اسکریپتهای درون خطی را مسدود خواهد کرد. برای حل این مسئله nonce را با دستورات unsafe-inline ترکیب کردیم .مرورگر CSP 1.0 اسکریپتهای درون خطی را مانند قبل اجرا میکند اما مرورگر CSP 2.0 دستورات unsafe-inline را نادیده می گیرد تا زمانی که nonce را مشاهده کند و فقط اسکریپتهای درون خطی را با استفاده از تنظیمات nonce اجرا میکند. یک مسیر ارتقاء در اختیار سایتهای موجود قرار می دهد که بتوانند از CSP 2.0 بدون نیاز به بازنویسی های انبوه برای خلاص شدن از in-line style ها و اسکریپتها بهره مند شوند.
Nonces به راحتی می توانند با استفاده از HTML helper اجرا شوند .
بزرگترین ضرر این روش آن است که Nonce برای هر پاسخ به سمت کلاینت، متفاوت است. به این معناست که هیچ صفحه ای را با استفاده از Nonce نمی توان cache کرد. اگر برای هر کاربر صفحه منحصر به فردی در نظر داشته باشید این مسئله مهمی نخواهد بود ، در غیر این صورت استفاده از nonce غیرممکن است.
Hashes
استفاده از Hashes راه حلی برای cache کردن در nonce است. سرور، Hash را به عنوان سبک خاص(style) یا محتوای برچسب اسکریپت (script tage contents) به حساب می آورد:
دیگر پشتیبانی های CSP
تا اینجا دریافتیم که استفاده از in-line style ها و اسکریپتها راه درستی نیست. CSP آنها را مسدود میکند ، همچنین نمی توانید با استفاده از ASP.net MVC آنها را کوچک و نامفهوم کنید. پس حرکت دادن اسکریپتها به فایل CSS و Java خارجی می تواند به این معنا باشد که می توانید از CSP استفاده کنید. CSP در حال حاضر درچند کتابخانه بزرگ پشتیبانی نمی شود.
پشتیبانی Modernizrبرای CSP
Modernizr دراستایل های in-line برای تست قابلیت های مرورگر وب استفاده می شود و به دستورات in-inline ناامن نیاز است. کتابخانه AngularJS یک CSP compatible mode دارد که از یک فایل Css خارجی استفاده می کند که خیلی ساده تنظیم می شود. جایگزین دیگر ، NWebSec است که از Hashes پشتیبانی میکند ، ما می توانیم کار کردن Hashes را از هر اسکریپتی که از Modernizr استفاده میکند و شامل آن می شود را در داخل CSP HTTP header اضافه کنیم.
پشتیبانی لینک جستجو برای CSP
Browser Link یکی از خصوصیت های جالب Visual Studio است که اجازه به روزرسانی یک View در MVC هنگام اشکال زدایی را می دهد به همراه یک دکمه refresh که هر مرورگری که از آن صفحه استفاده میکرده به روزرسانی شود. متاسفانه این خصوصیت دستی با CSP سازگار نیست زیرا Visual Studio یک اسکریپت in-line به دکمه همان صفحه ای که در حال اشکال زدایی بود اضافه میکند. البته این باعث بروز خطای نقض (CSP Violation Errors) می شود.
اتخاذ جریان CSP
تاکنون وب سایتهای زیادی از CSP استفاده نکرده اند. می تواند دلایل زیر را داشته باشد (تا کنون):
1. عدم پشتیبانی مرورگر
2. عدم اطلاع توسعه دهندگان
3. توسعه دهندگان Framework مانند مایکروسافت و ASP.net MVC به توسعه دهندگان وب راهی برای پیاده سازی CSP نداده اند. (NWebSec برای پر کردن این شکاف ایجاد شد)
4. رواج استفاده از استایل های درون خط و اسکریپتها و عدم تمایل به سوئیچ کردن به فایل های جداگانه
5. عدم پشتیبانی کتابخانه های عمومی CSS/Javascript ازCSP
CSP .6 ، لایه های بیشتری از امنیت با استفاده از استراتژی <a href=”http://en.wikipedia.org/wiki/Defense_in_depth_%28computing%29″>Defence in Depth</a> می دهد. بعضی از توسعه دهندگان وب تا زمانی که هک نشوند به حد کافی امنیت را جدی نمیگیرند.
7. ورژن قبلی CSP اشکالات زیادی داشت.(X-Content-Security-Policy یا X-Webkit-CSP )
8. توسعه دهندگان استفاده مناسب از توانایی گزارش نقض به CSP را با استفاده از دستورات report-uri ایجاد نکرده اند. اگر یک تخلف پیدا شود می توانید به سرعت بفهمید که کسی در حال حمله به سایت شماست و CSP شما معتبر نیست یا اشکالاتی در سایت شما وجود دارد.
9. توسعه دهندگان وب از تفکیک سایت خود می ترسند. ( اغلب به این دلیل است که CSP به یک Spider مجهز است )
چه کسانی از CSP استفاده میکنند
عمده مرورگرها اکنون از CSP HTTP header پشتیبانی میکنند. NWebSec استفاده از آن را در پروژه های MVC آسان کرده است. اکنون سایت های بزرگ از CSP استفاده میکنند. اگر به سایتهای بزرگ مانند فیسبوک ،CNN، BBC،Google، Huffington Post ، Youtube، Twitter و GitHub سر بزنید و HTTP response آنها را چک کنید متوجه این موضوع خواهید شد.
افزونه های مرورگر و ISP
افزونه های مرورگر یا Extension ها و حتی ISP ها اسکریپتهایی را به صفحات وارد می کنند، که سبب گزارش نقض CSP میشوند.CSP ممکن است بعضی از extension های مرورگر که در صفحات کد هایی را وارد کرده اند را شکسته یا تفکیک کند. اما آیا می توان به افزونه های مرورگر اعتماد کرد که در کدها تغییری ایجاد کنند ؟
شما میتوانید از SSL/TSL که بیشتر فرم های ISP را با کدهای شما متوقف میکند استفاده کنید. پس CSP امنیت بیشتری به ما میدهد.
CSP و تبلیغات
تبلیغات می تواند یک مشکل برای CSP باشد. بعضی ارائه دهندگان تبلیغات بهتر از دیگران هستند. بعضی ها از منابعی استفاده میکنند که به طور مداوم در حال تغییر هستند که می تواند موجب خطای نقض CSP شود . CNN تمام آگهی ها را درون Frame قرار می دهد که خبرها را یا حداقل آنهایی که قابل توجه هستند را بدون محدودیت CSP نشان می دهد.
ایجاد خودکار CSP
خزنده های خاص وب وجود دارند که ساخته شده اند برای خزیدن روی تمام لینکهای روی دامنه ، که برای تولید یک CSP policy به صورت خودکار تلاش میکنند. CSP Tools یک لیست از URLهایی که می توانند روی صفحات وب بخزند و CSP تولید کنند را گردآوری کرده است. روش دیگر این ابزار آن است که به گزارش خطای نقض CSP نگاه میکند و قوانینی بر اساس آنها می سازد.
بهترین راه آن است که هنگامی که سایت خود را می سازید، CSP خود را از پایه ایجاد کنید و سپس برای اطمینان از آن تست انجام دهید. می توانید CSP policy را روی حالت گزارش تنظیم کنید، پس مرورگر چیزی را مسدود نمیکند اما گزارش های خطای نقض را می دهد ، زمانی که از نبودن خطای نقض مطمئن شدید می توانید Policy خود را بکار ببرید.
تست کردن CSP policy ها
افزونه CSP Tester کروم یک نمونه از ابزارهایی است که می توانید با استفاده از آن CSP policy خود را در سایتتان بکار ببرید و تاثیر آن را در پنجره کنسول مرورگر ببینید. همانطور که گفته شد بهترین راه ، ایجاد CSP درون سایتتان است. از دستور report-uri برای پیدا کردن نقض ها و درست کردن آنها استفاده می شود. همچنین در سطح تست اگر از کار انجام شده اطمینان ندارید می توانید از Content-Security-Policy-Report-Only HTTP header بجای Content-Security-Policy برای متوقف کردن هر چیز توسط مرورگر استفاده کنید.
- ASP.net MVC
- 4k بازدید
- 2 تشکر