مشخصات مقاله
-
916
-
0.0
-
2928
-
0
-
0
برقراری امنیت در Angular
امنیت
در این صفحه به بررسی امکانات پیش فرض انگولار جهت مقابله با آسیب پذیری ها و حملات مرسوم نرم افزارهای تحت وب مانند حملات تزریق اسکریت از طریق سایت میپردازیم. این بررسیها امنیت سطح نرم افزار مانند احراز هویت (این کاربر کیست؟) و اختیاردهی (این کاربر بتواند چه کاری انجام دهد؟) را شامل نمیشوند.
برای دریافت اطلاعات بیشتر در رابطه با این حملات و شیوهی مقابله با آنها که در زیر آمده است به پروژهی آموزشی OWASP مراجعه کنید.
میتوانید به Stackblitz بروید، مثال زندهی موجود در آن را دانلود و یا اجرا کنید، همچنین در صورت تمایل کد مخصوص به آن را نیز دانلود کنید.
گزارش دادن آسیب پذیری ها
برای آن که آسیب پذیری های موجود در خود انگولار را گزارش دهید، میتوانید آنها را به آدرس security@angular.io برای ما ایمیل کنید.
برای اطلاعات بیشتر در رابطه با نحوهی مدیریت مشکلات امنیتی توسط گوگل به «فلسفهی امنیت گوگل» مراجعه کنید.
بهترین راهکارها
- همواره آخرین نسخهی کتابخانهی انگولار را استفاده کنید. ما همواره این کتابخانهها را آپدیت میکنیم و همین آپدیتها ممکن است که نواقص موجود در نسخههای قبلی را برطرف کنند. برای یافتن آپدیتهای مربوط به امنیت گزارش تغییرات انگولار را مطالعه کنید.
- هیچ وقت نسخهی کپی انگولار خود را تغییر ندهید. معمولاً نسخههای خصوصی و اختصاصی انگولار، آخرین نسخهها را دریافت نمیکنند و به همین دلیل مشکلات امنیتی آنها برطرف نمیشود. به جای این کار، اصلاحات انگولار خود را با جامعهی انگولار به اشتراک بگذارید و برای آنها pull request ارسال کنید.
- از API هایی که در لیست API های خطرناک است پرهیز کنید. برای اطلاعات بیشتر به بخش «مقادیر امن و مطمئن» در همین صفحه مراجعه کنید.
جلوگیری از تزریق اسکریپت از طریق سایت (XSS)
هکرها با کمک XSS میتوانند کدهای آلوده را داخل صفحات اینترنتی تزریق کنند. از جمله کارهایی که این کد بعد از تزریق شدن میتواند انجام دهد، میتوان به سرقت اطلاعات کاربر (مخصوصاً اطلاعات مربوط به لاگین کردن) و یا جعل هویت کاربر اشاره کرد. این نوع حملات از رایجترین حملات موجود در اینترنت هستند.
برای آن که از حملات XSS جلوگیری کنید، باید مانع ورود این کدهای آلوده به DOM (Document Object Model) شوید. برای مثال اگر هکران بتوانند شما را فریب دهند و یک تگ< script > را در DOM وارد کنند، در این صورت میتوانند کدهای دلخواهشان را در وب سایتتان اجرا کنند. این حمله صرفاً محدود به تگهای < script > نمیشود. المانها و مشخصات زیادی در DOM وجود دارند که امکان اجرای کد را فراهم میکنند. مثلاً < img onerror="..." > و < a href="javascript:..." >. در صورت ورود دادههای کنترل شده توسط هکر به DOM آسیب پذیر شدن امنیت دور از انتظار نخواهد بود.
مدل امنیتی تزریق اسکریپت از طریق سایت در انگولار
انگولار برای آن که به صورت منظم باگهای XSS را مسدود کند، به صورت پیش فرض تمامی مقادیر را نامطمئن در نظر میگیرد. وقتی که مقداری از طریق ویژگی، صفت، استایل، مقید سازی کلاس و یا اینترپولاسیون از یک قالب وارد DOM میشود، انگولار مقادیر نامطمئن را پاک سازی کرده و از آنها رهایی مییابد.
قالبهای انگولار مانند کدهای قابل اجرا هستند: HTML، attribute ها (صفت) و عبارتهای مقید سازی (نه قید مقادیر) در قالبها مطمئن و امن در نظر گرفته میشوند. این یعنی برنامهها باید از مقادیری جلوگیری کنند که هکرها میتوانند آنها را به گونهای کنترل کنند که وارد سورس کد قالب شوند. هیچ وقت با ترکیب ورودی کاربر و قالبها اقدام به تولید سورس کد قالب نکنید. برای جلوگیری از این آسیب پذیری ها بهتر است که از کامپایلر قالب آفلاین که معروف به تزریق قالب است استفاده کنید.
پاک سازی و زمینههای امنیتی
پاکسازی به بررسی یک مقدار نامطمئن و تبدیل آن به مقداری امن برای ورود به DOM گفته میشود. در بسیاری از حالات، در فرآیند پاک سازی به هیچ وجه هیچ مقداری تغییر نمیکند. پاک سازی به زمینه وابته است: مقداری در CSS بی ضرر است، در URL میتواند خطرناک باشد.
انگولار زمینههای امنیتی زیر را تعریف میکند:
- هنگام تفسیر یک مقدار به عنوان HTML از HTML استفاده میشود. مثلاً زمان مقید شدن به innerHtml.
- زمانی از Style استفاده میشود که بخواهیم CSS را به ویژگی style مقید کنیم.
- URL در ویژگیهای URL مثل < a href > کاربرد دارد.
- URL منبع URL ای است که به صورت کد بارگیری و اجرا میشود. مثلاً در< script src >.
انگولار مقادیر ناامن HTLM، style ها، و URL ها را پاک سازی میکند؛ امکان پاک سازی URL های منبع وجود ندارد زیرا این نوع از URL ها شامل کدهای دلخواه هستند. در حالت برنامه نویسی زمانی که انگولار مجبور باشد طی فرآیند پاک سازی مقداری را تغییر دهد، هشداری را در کنسول چاپ میکند.
مثالی برای پاک سازی
قالب زیر مقدار htmlSnippet را یک بار با اینترپولات کردن آن در محتوای یک المان و بار دیگر با مقید کردن آن به ویژگی innerHTML یک المان مقید میکند.
src/app/inner-html-binding.component.html
< h3 >Binding innerHTML< /h3 >
< p >Bound value:< /p >
< p class="e2e-inner-html-interpolated" >{ {htmlSnippet}}< /p >
< p >Result of binding to innerHTML:< /p >
< p class="e2e-inner-html-bound" [innerHTML]="htmlSnippet" >< /p >
همیشه محتوای اینترپولات شده رهایی مییابد. به این صورت که HTML تفسیر نمیشود و مرورگر در محتوای متنی المان کاراکتر < > را نمایش میدهد.
اگر میخواهید HTML را تفسیر کنید باید آن را به یک ویژگی HTML مانند innerHTML مقید کنید. اما مقید کردن مقداری به innerHTML که ممکن است هکر بر روی آن کنترل داشته باشد، میتواند باعث آسیب پذیری XSS شود. برای مثال، کد موجود در تگ< script >اجرا میشود:
src/app/inner-html-binding.component.ts (class)
export class InnerHtmlBindingComponent {
// For example, a user/attacker-controlled value from a URL.
htmlSnippet = 'Template < script >alert("0wned")< /script > < b >Syntax< /b >';
}
Angular این مقدار را به عنوان یک مقدار ناامن میشناسد و بلافاصله آن را پاک سازی میکند. این کار باعث میشود تگ < script > حذف شود؛ اما محتوای داخل آن مانند محتوای متنی این تگ و المان < b > باقی میماند.
استفادهی مستقیم از API های DOM و فراخوانی صریح پاکسازی
API های DOM موجود در خود مرورگر به صورت خودکار شما را از آسیب پذیری های امنیتی مصون نگه نمیدارند. مثلاً document گرهی موجود از طریق ElementRef و بسیاری از API های سوم شخص شامل متدهای ناامن هستند. به همین صورت، اگر با کتابخانههای دیگری که DOM را دست کاری میکنند تعامل کنید، به احتمال زیاد به آن پاک سازی خودکاری دست پیدا نمیکنید که اینترپولاسیون Angular میتواند به شما ارائه کند. از تعامل مستقیم با DOM پرهیز کنید و در عوض تا جایی که امکان دارد از قالبهای Angular استفاده کنید.
در حالتهایی که چارهی دیگری ندارید، از توابع پاک سازی موجود در خود Angular استفاده کنید. به کمک متد DomSanitizer.sanitize و SecurityContext مناسب مقادیر نامطمئن را پاک سازی کنید. همان طور که در زیر آمده است، این تابع مقادیری که با استفاده از توابع bypassSecurityTrust... به عنوان مقادیر مطمئن علامت گذاری شدهاند را نیز میپذیرد و آنها را پاک سازی نمیکند.
سیاست امنیت محتوا
سیاست امنیت محتوا (CSP) روشی شگرف جهت مقابله با XSS است. برای فعال سازی CSP وب سرور خود را به گونهای پیکربندی کنید که یک هِدر HTTP مناسب Content-Security-Policy را برگشت دهد. برای مطالعهی بیشتر در رابطه با CSP به وب سایت HTML5Rocks بروید و مقالهی An Introduction to Content Security Policy را مطالعه کنید.
استفاده از کامپایلر قالب آفلاین
کامپایلر قالب آفلاین، از کل کلاس آسیب پذیری به نام تزریق قالب جلوگیری میکند و تا حد زیادی عملکرد برنامه را بهبود میبخشد. در گسترش تولید از این کامپایلر استفاده کنید و به صورت پویا قالبها را تولید نکنید. Angular به کدهای قالب اعتماد دارد، به همین دلیل تولید قالبها، به ویژه قالبهایی که شامل اطلاعات کاربری هستند، باعث محدود شدن حفاظتهای پیش فرض Angular میشود. برای دریافت اطلاعات بیشتر در رابطه با نحوهی ایجاد پویا و امن فرم به صفحهی آموزش «فرمهای دینامیک» مراجعه کنید.
مقابله با XSS سمت سرور
HTML ای که بر روی سرور ساخته شده باشد، در برابر حملات تزریقی، آسیب پذیر است. تزریق کد قالب در یک برنامهی Angular، تفاوتی با تزریق کد قابل اجرا در برنامه ندارد. در هر دوی این حالات، فرد هکر بر روی برنامه کنترل کامل پیدا میکند. برای جلوگیری از این کار از یک زبان قالب بندی استفاده کنید تا مقادیر به صورت خودکار رهایی یابند تا در نهایت بتوانید از آسیب پذیری سرور در برابر XSS جلوگیری کنید. در سمت سرور با استفاده از یک زبان قالب بندی اقدام به ایجاد قالبهای Angular نکنید؛ چرا که این کار باعث میشود خطر بروز آسیب پذیری های تزریق قالب افزایش پیدا کند.
اعتماد به مقادیر امن
گاهی اوقات برنامهها در اصل باید شامل کدهای قابل اجرا، نمایش دادن یک < iframe >از یکی از URL ها و یا ساختن URL های احتمالی خطرناک باشند. برای آن که از پاک سازی خودکار هر یک از این موقعیتها جلوگیری کنید، میتوانید به Angular بگویید که شما مقداری را بررسی کردهاید، چگونگی تولید آن را چک کردهاید و مطمئن هستید که همیشه این مقدار امن است. اما احتیاط کنید! اگر به یک مقدار اعتماد کنید که این مقدار آلوده باشد، در این صورت امنیت برنامهی خود را در معرض آسیب پذیری قرار خواهید داد. اگر مطمئن نیستید این کار را به کارشناس این زمینه بسپارید.
برای آن که مقداری را به عنوان یک مقدار مورد اعتماد علامت گذاری کنید، DomSanitizer را تزریق کنید و یکی از متدهای زیر را فراخوانی کنید.
- bypassSecurityTrustHtml
- bypassSecurityTrustScript
- bypassSecurityTrustStyle
- bypassSecurityTrustUrl
- bypassSecurityTrustResourceUrl
توجه داشته باشید که امن بودن یک مقدار بستگی به زمینه دارد. به همین دلیل برای کاربرد مورد نظر مقدار خود زمینهی مناسب را انتخاب کنید. فرض کنید قالب زیر باید یک URL را به یک فراخوان javascript:alert(...) مقید کند.
src/app/bypass-security.component.html (URL) < h4 >An untrusted URL:< /h4 > < p >< a class="e2e-dangerous-url" [href]="dangerousUrl" >Click me< /a >< /p > < h4 >A trusted URL:< /h4 > < p >< a class="e2e-trusted-url" [href]="trustedUrl" >Click me< /a >< /p >
به طور معمول، Angular به صورت خودکار این URL را پاک سازی و کد خطرناک را غیرفعال میکند. همچنین در حالت برنامه نویسی گزارش این کار را در کنسول نمایش میدهد. برای جلوگیری از این کار، با استفاده از فراخوان bypassSecurityTrustUrl مقدار URL را به عنوان یک URL مورد اعتماد علامت گذاری کنید:
src/app/bypass-security.component.ts (trust-url)
constructor(private sanitizer: DomSanitizer) {
// javascript: URLs are dangerous if attacker controlled.
// Angular sanitizes them in data binding, but you can
// explicitly tell Angular to trust this value:
this.dangerousUrl = 'javascript:alert("Hi there")';
this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
اگر میخواهید ورودی کاربر را به یک مقدار امن تبدیل کنید میتوانید از یک متد کنترلر استفاده کنید. کاربران با کمک قالب زیر میتوانند آیدی یکی از ویدئوهای یوتیوب را وارد کنند و ویدئوی متناظر را در یک < iframe > بارگیری کنند. صفت < iframe src > یک زمینهی امنیتی URL منبع است. زیرا یک منبع نامطمئن میتواند برای مثال فایلهای دانلودی را به صورت قاچاقی وارد کند به گونهای که کاربران مورد اعتماد بتوانند این فایلها را اجرا کنند. بنابراین برای آن که یک URL مطمئن ویدئویی را بسازید، متدی را در کنترلر فراخوانی کنید تا باعث شود Angular امکان مقیدسازی به < iframe src > را فراهم کند.
src/app/bypass-security.component.html (iframe)
< h4 >Resource URL:< /h4 >
< p >Showing: { {dangerousVideoUrl}}< /p >
< p >Trusted:< /p >
< iframe class="e2e-iframe-trusted-src" width="640" height="390" [src]="videoUrl" >< /iframe >
< p >Untrusted:< /p >
< iframe class="e2e-iframe-untrusted-src" width="640" height="390" [src]="dangerousVideoUrl" >< /iframe >
src/app/bypass-security.component.ts (trust-video-url)
updateVideoUrl(id: string) {
// Appending an ID to a YouTube URL is safe.
// Always make sure to construct SafeValue objects as
// close as possible to the input data so
// that it's easier to check if the value is safe.
this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
this.videoUrl =
this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}
آسیب پذیری های سطح HTTP
Angular به صورت پیش فرض، امکاناتی در اختیار دارد که از دو آسیب پذیری رایج HTTP به نامهای جعل درخواست میان وب سایتی (CSRF یا XSRF) و وارد سازی اسکریپت میان وب سایتی (XSSI) جلوگیری میکند. هر دوی این آسیب پذیری ها در ابتدا باید در سمت سرور حل و فصل شوند. اما Angular امکاناتی کمکی را در اختیار کاربر قرار میدهد که کاربر راحتتر بتواند در سمت کلاینت به یکپارچه سازی بپردازد.
جعل درخواست میان وب سایتی
در CSRF و XSRF فرد هکر کاربر را فریب میدهد تا از صفحهی اینترنتی متفاوتی بازدید کند (مانند evil.com). در این صفحه کد آلودهای وجود دارد که به صورت مخفیانه درخواست آلودهای را به سرور اینترنتی برنامه ارسال میکند (مانند example-bank.com).
فرض کنید که کاربر در آدرس example-bank.com وارد برنامه شده است، کاربر ایمیلی را باز میکند و بر روی لینک evil.com کلیک میکند. بعد از این کار tab جدیدی باز میشود.
بلافاصله صفحهی evil.com در خواست آلودهای را به example-bank.com میفرستد. این درخواست میتواند درخواست ارسال پول از حساب کاربر به حساب هکر باشد. مرورگر به صورت خودکار به همراه این درخواست، کوکیهای example-bank.com (از جمله کوکی احراز هویت) را ارسال میکند.
اگر سرور example-bank.com امکان مقابله با XSRF را نداشته باشد، تفاوتی بین یک درخواست مشروع از برنامه و درخواست تقلبی از evil.com قائل نمیشود.
برای آن که از این کار جلوگیری کنید، برنامه باید تضمین کند که درخواست کاربر از یک برنامهی واقعی (و نه یک سایت دیگر) نشات گرفته است. برای خنثی کردن این حمله سرور و کلاینت باید با یکدیگر همکاری کنند.
در تکنیکهای معمول مقابله با XSRF سرور برنامه یک توکن احراز هویت که به صورت تصادفی تولید شده است را در یک کوکی ارسال میکند. کد کلاینت این کوکی را میخواند و همراه با این توکن در تمامی درخواستهای بعدی یک هدر درخواستی اختصاصی را اضافه میکند. سرور مقدار کوکی دریافتی را با مقدار هدر درخواستی مقایسه میکند و اگر مقادیری موجود نباشند یا با یکدیگر مطابقت نداشته باشند، این درخواست را رد میکند.
دلیل مؤثر بودن این تکنیک این است که تمامی مرورگرها سیاست منشأ یکسان (same origin policy) را پیاده سازی میکنند. تنها کدهایی از وب سایت که در آنها کوکیها تنظیم شده باشند میتوانند کوکیهای آن سایت را بخوانند و هدرهای اختصاصی درخواستهای آن سایت را تنظیم کنند. این یعنی تنها برنامهی ماست که میتواند این توکن کوکی را بخواند و هدر اختصاصی را تنظیم کند و کد آلودهی موجود در evil.com چنین قابلیتی را ندارد.
HttpClient Angular به صورت پیش فرض از نیمی از این تکنیک سمت کلاینت پشتیبانی میکند. برای اطلاعات بیشتر به آموزش HttpClient مراجعه کنید.
برای دریافت اطلاعات بیشتر در رابطه با CSRF در پروژههای امنیت برنامههای تحت وب باز (OWASP) به جعل درخواست میان وب سایتی (CSRF) و برگهی تقلب جلوگیری از جعل درخواست میان وب سایتی (CSRF) مراجعه کنید. مقالهی دانشگاه استنفورد تحت عنوان مقابلهی قوی با جعل درخواست میان وب سایتی، میتواند منبع پرباری برای دریافت اطلاعات جزئی باشد.
همچنین میتوانید به گفتگوی Dave Smith با محوریت XSRF at AngularConnect 2016 که به صورت روان بیان شده است مراجعه کنید.
وارد سازی اسکریپت میان وب سایتی (XSSI)
وارد سازی اسکریپت میان وب سایتی که به آسیب پذیری JSON نیز معروف است، به یکی از وب سایتهای هکر این قابلیت را میدهد تا دادهها را از یک JSON API بخوانند. در مرورگرهای قدیمی این حمله به این صورت عمل میکند که سازندههای شیء جاوا اسکریپت بومی را باطل میکند و با استفاده از یک تگ < script > یک API URL را وارد برنامه میکند.
این حمله تنها در صورتی موفقیت آمیز است که JSON برگشتی به صورت جاوا اسکریپت قابل اجرا باشد. سرورها برای آن که بتوانند از این دست از حملات جلوگیری کنند، باید تمامی پاسخهای JSON را به گونهای پیشوند گذاری کنند که به حالت غیرقابل اجرا در بیاید. به صورت قراردادی این کار از طریق رشتهی معروف ")]}',\n" انجام میشود.
کتابخانهی HttpClient Angular این قرارداد را به رسمیت میشناسد و به صورت خودکار رشتهی ")]}',\n" را قبل از تجزیه سازی بیشتر از پاسخهای دیگر مجزا میکند.
برای اطلاعات بیشتر به بخش XSSI پست Google web security blog مراجعه کنید.
بازبینی برنامههای Angular
برنامههای Angular باید از همان اصول امنیتی پیروی کنند که برنامههای تحت وب عادی پیروی میکنند و بر همین اساس باید بازبینی شوند. API های مختص به Angular که باید در بازبینیهای امنیتی مورد بازبینی قرار گیرند (مانند متدهای bypassSecurityTrust)، در این آموزش به عنوان امنیت حساس علامت گذاری شدهاند.