۱۰ نکته امنیتی برای توسعه دهندگان فرانت اند | راهنمای کاربردی
امنیت وب موضوعی است که غالباً از سوی توسعهدهندگان فرانت نادیده گرفته میشود. زمانی که کیفیت یک وبسایت را ارزیابی میکنیم غالباً معیارهایی مانند عملکرد، سازگاری با اصول سئو و دسترسپذیری را بررسی میکنیم، در حالی که ظرفیت وبسایت برای مقاومت در برابر حملههای خرابکارانه غالباً مغفول واقع میشود. در این راهنما با 10 نکته امنیتی برای توسعه دهندگان فرانت اند آشنا خواهیم شد.
با این که دادههای حساس کاربران در سمت سرور ذخیره میشود و توسعهدهندگان بکاند میبایست تدابیر شدیدی برای حفاظت از سرورها انجام دهند، اما مسئولیت امنسازی دادهها در هر حال موضوع تشریک مساعی بین بکاند و فرانتاند است. اگرچه دادههای حساس را میتوان در بکاند تحت مراقبت نگهداری کرد، اما فرانتاند نیز کلیدهای بکاند را نگهداری میکند که به سرقت رفتن آنها غالباً سادهترین روش برای کسب دسترسی به بکاند محسوب میشود.
چندین نوع حمله وجود دارند که کاربران خرابکار میتوانند برای به مخاطره انداختن اپلیکیشنهای فرانتاند ما مورد استفاده قرار دهند، اما خوشبختانه میتوانیم یک چنین حملاتی را با رعایت چند نکته ساده مانند پیکربندی صحیح هدرهای پاسخ تا حدود زیادی کاهش دهیم. در ادامه این مقاله 10 توصیه امنیتی را مطالعه میکنید که به شما کمک میکنند تا امنیت وباپلیکیشنهای خود را تقویت کنید.
اندازهگیری نتایج
پیش از بهبود امنیت وبسایت، باید برخی بازخوردها در مورد اثربخشی این تغییراتی که میخواهیم اعمال کنیم داشته باشیم. با این که کمّیسازی موضوعی مانند رویههای مناسب توسعه وب کار دشواری است، اما استحکام هدرهای امنیتی را میتوان به صورت کاملاً دقیق اندازهگیری کرد. همان طور که از Lighthouse برای اندازهگیری نمرات عملکرد، SEO و دسترسپذیری بهره میگیریم، میتوانیم از سرویس آنلاین SecurityHeaders.com نیز برای بررسی نمرههای امنیتی هدرهای پاسخ کنونی وبسایتمان استفاده کنیم. در صورتی که نمره پایینی به دست آوریم این وبسایت برخی نکات در مورد چگونگی بهبود نمرات و در نتیجه تقویت امنیت نیز ارائه میکند:
بالاترین نمره وبسایت SecurityHeaders.com برابر با A+ است و ما همواره باید در جهت کسب این نمره بکوشیم.
نکاتی در مورد هدرهای پاسخ
کار کردن با «هدرهای پاسخ» (response headers) عموماً وظیفه بخش بکاند است، اما امروزه ما غالباً وباپلیکیشنهای خود را به روش «بدون سرور» (serverless) و روی پلتفرمهای ابری مانند Zeit یا Netlify منتشر میکنیم و از این رو پیکربندی آنها برای بازگشت هدرهای پاسخ مناسب به یکی از مسئولیتهای فرانتاند تبدیل شده است. شما باید طرز کار هاستینگ ابری خود با هدرهای پاسخ را بشناسید تا بتوانید آنها را بر این اساس پیکربندی کنید.
تدابیر امنیتی
در این بخش تدابیر امنیتی که لازم است برای تقویت امنیت وباپلیکیشن خود رعایت کنید را به صورت تفصیلی مورد بررسی قرار میدهیم.
از سیاست امنیت محتوای قوی استفاده کنید
«سیاست امنیت محتوا» (CSP)-ی معقول، سنگ بنای امنیت در اپلیکیشنهای فرانتاند است. CSP استانداردی است که در مرورگرها معرفی شده تا انواع خاصی از حملههای تزریق کد را شناسایی و کاهش دهد که شامل اسکریپتنویسی بین سایتی (cross-site scripting) و کلیکدزدی (clickjacking) میشود.
وجود CSP قوی میتواند جلوی اجرای کد درونخطی مخرب را گرفته و دامنههایی که منابع بیرونی از آنها لود میشوند را محدود سازد. شما میتوانید با تعیین هدر Content-Security-Policy روی یک لیست از دایرکتیوهایی که با نقطهویرگول از هم جدا میشوند، CSP را فعال کنید. اگر وبسایت شما نیازی به دسترسی به منابع بیرونی ندارد، بهترین مقدار برای شروع استفاده از این امکان میتواند چیزی مانند زیر باشد:
Content-Security-Policy: default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self'; connect-src 'self';
در کد فوق ما دایرکتیوهای script-src ،img-src ،style-src و connect-src را روی مقدار self تنظیم کردیم تا نشان دهیم که همه اسکریپتها، تصاویر، استایلشیتها و فراخوانیهای واکشی باید محدود به همان مبدائی باشند که سند HTML از آن عرضه شده است. هر دایرکتیو CSP دیگر که به صورت صریح تعیین نشده باشد به عنوان جایگزین مقدار تعیین شده از سوی دایرکتیو default-src مورد استفاده قرار میگیرد. ما آن را روی مقدار None تنظیم کردیم تا نشان دهیم که رفتار پیشفرض، رد کردن اتصالها از هر URL دیگر است.
با این حال این روزها به ندرت میتوان وباپلیکیشنی را یافت که کاملاً مستقل باشد، از این رو ممکن است بخواهید این هدر را طوری تنظیم کنید که دامنههای مورد اعتماد دیگر مانند Google Fonts یا AWS S3 buckets نیز بتوانند مورد استفاده قرار گیرند. اما همواره بهتر است که کار را با سختترین سیاست آغاز کنید و سپس در موارد نیاز آن را کمی آسانتر بگیرید.
برای مشاهده فهرست کامل دایرکتیوهای CSP به وبسایت MDN (+) سر بزنید.
فعالسازی حالت حفاظت XSS
اگر کد خرابکارانه در نتیجه ورودی کاربر تزریق شده باشد، با ارائه هدر زیر میتوانیم به مرورگر دستور بدهیم که پاسخ را مسدود سازد:
"X-XSS-Protection": "1; mode=block"
با این که حالت حفاظت XSS به صورت پیشفرض در اغلب مرورگرهای مدرن فعال است و ما نیز میتوانیم از سیاست امنی محتوا برای غیر فعالسازی استفاده از جاوا اسکریپت درونخطی بهره بگیریم، اما همچنان پیشنهاد میشود که هدر X-XSS-Protection را نیز بگنجانیم تا از امنیت بالاتر روی مرورگرهای قدیمی که از هدرهای CSP پشتیبانی نمیکنند، مطمئن شویم.
ممانعت از حملههای کلیکدزدی با غیر فعال کردن جاسازی iframe
«کلیکدزدی» (Clickjacking) حملهای است که در آن کاربر وبسایت الف وانمود میکند که کاری را روی وبسایت ب انجام میدهد. به این منظور کاربر خرابکار وبسایت ب را درون یک iframe ناپیدا جاسازی میکند که زیر کرسر کاربر معمولی روی وبسایت الف قرار میگیرد. زمانی که کاربران کلیک میکنند، تصورشان این است که روی چیزی در وبسایت الف کلیک میکنند، اما در واقع روی چیزی روی وبسایت ب کلیک کردهاند.
برای جلوگیری از وقوع چنین حملاتی باید از هدر X-Frame-Options استفاده کنیم که از رندر شدن وبسایت در یک فریم جلوگیری میکند:
"X-Frame-Options": "DENY"
همچنین میتوانیم از دایرکتیو CSP به صورت frame-ancestors استفاده کنیم که کنترل دقیقتری روی والدینی که میتوانند صفحه را در iframe جاسازی کنند، فراهم میسازد.
محدودسازی دسترسی به قابلیتهای مرورگر و API-ها
بخش مهمی از یک رویه خوب امنیتی آن است که دسترسی به هر چیزی که در جهت مقاصد وبسایت نیست را محدود سازیم. ما همین الان با استفاده از CSP برای محدودسازی تعداد دامنههایی که وبسایت مجاز به اتصال به آنها است از این اصل استفاده میکنیم، اما این مورد را میتوانیم به قابلیتهای مرورگرها نیز تسری ببخشیم. به این ترتیب میتوانیم به مرورگر اعلام کنیم که دسترسی به برخی قابلیتهای خاص و API-ها را در اپلیکیشن ما انکار کند و به این منظور از هدر Feature-Policy استفاده میکنیم.
برای نمونه میتوانیم مقدار هدر Feature-Policy را روی یک رشته از قواعد تنظیم کنیم که با نقطهویرگول از هم جدا شدهاند و هر قاعده نام قابلیتی است که نام سیاست نیز در ادامهاش آمده است:
"Feature-Policy": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; encrypted-media 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vr 'none';"
برای کسب اطلاعات بیشتر در مورد هدر Feature-Policy میتوانید به این مقاله (+) مراجعه کنید، اما در غالب موارد باید آن را برای همه قابلیتهایی که استفاده نمیکنید، روی none تنظیم کنید.
مقدار referrer را فاش نکنید
زمانی که روی یک لینک کلیک میکنید که موجب میشود از وبسایت خارج شوید، وبسایت مقصد URL آخرین مکان کاربر را روی وبسایت شما در یک هدر referrer (ارجاعدهنده) دریافت میکند. این URL ممکن است شامل دادههای حساس و نیمه حساسی (مانند توکنهای نشست و ID-های کاربر) باشد که هرگز نباید افشا شوند. برای جلوگیری از نشت مقدار referrer باید هدر Referrer-Policy را مانند زیر روی مقدار no-referrer تنظیم کنیم:
"Referrer-Policy": "no-referrer"
این مقدار در اغلب موارد مناسب است، اما اگر منطق اپلیکیشن شما نیازمند این است که "Referrer-Policy": "no-referrer" را در برخی موارد حفظ کنید، میتوانید از دستورالعملهایی که در این مقاله (+) ارائه شده است استفاده کنید تا با همه مقادیر ممکن برای این هدر و زمانی که باید از آنها استفاده کنید، آشنا شوید.
مقدار innerHTML را بر اساس ورودی کاربر تنظیم نکنید
حملههای اسکریپتنویسی بین سایتی که در آن کد مخرب در یک وبسایت تزریق میشود از طریق برخی API-های مختلف DOM قابل اجرا هستند، اما در غالب موارد از innerHTML استفاده میشود.
هرگز نباید innerHTML را بر مبنای ورودی فیلتر نشده کاربر تنظیم کنید. هر مقداری که امکان دستکاری مستقیم آن از سوی کاربر وجود داشته باشد، چه متنی از یک فیلد ورودی و چه یک پارامتر URL یا مدخل local storage باید به دقت escape و پاکسازی شود. بهترین حالت این است که به جای innerHTML از textContent استفاده کنید تا کلاً از تولید خروجی HTML جلوگیری کنید. اگر نیاز به ارائه امکان ویرایش متن با امکانات زیاد دارید، از کتابخانههای کاملاً تثبیت شده استفاده کنید که به جای تهیه لیست سیاه برای تگهای مجاز HTML از لیست سفید به این منظور بهره میگیرند.
متأسفانه innerHTML تنها نقطه ضعف DOM API نیست و شناسایی کدهای مشکوک به تزریقهای XSS میتواند همچنان دشوار باشد. به همین دلیل است که همواره باید سیاست امنیت محتوای سختگیرانهای اعمال کنید که امکان اجرای کد درونخطی (inline) را نمیدهد.
در آینده با معرفی «مشخصات انواع مورد اعتماد» (+) از همه انواع حملههای مبتنی بر DOM و اسکریپتنویسی بین سایتی جلوگیری میشود.
از فریمورکهای UI استفاده کنید
فریمورکهای UI مدرن مانند ریاکت، ویو و انگولار سطح خوبی از امنیت را ارائه میکنند و میتوانند بسیاری از ریسکهای حملههای XSS را از بین ببرند. این فریمورکها به صورت خودکار خروجی HTML را انکود میکنند و نیاز به استفاده از DOM API-های مشکوک XSS را حذف میکنند. همچنین نامهای غیر مبهم و هشداردهندهای به متدهای بالقوه خطرناک مانند dangerouslySetInnerHTML ارائه کردهاند.
وابستگیها را بهروز حفظ کنید
با نگاهی گذرا به درون پوشه node_modules میتوان تأیید که وباپلیکیشن در واقع یک پازل لگویی است که از صدها (و بلکه هزاران) وابستگی ساخته شده است. تضمین این که این وابستگیها شامل هیچ نوع آسیبپذیری امنیتی نیستند، موجب میشود که امنیت کلی وبسایت نیز تأیید شود.
بهترین روش برای این که مطمئن شویم وابستگیها امن و بهروز هستند این است که بررسی آسیبپذیریها را به بخشی از رویه توسعه خود تبدیل کنیم. به این منظور میتوانیم از ابزارهایی مانند Dependabot و Snyk استفاده کنیم که درخواستهای pull را برای وابستگیهای بالقوه آسیبپذیر و یا قدیمی ایجاد کرده و به اعمال سریعتر اصلاحیهها کمک میکنند.
پیش از افزودن سرویسهای شخص ثالث به خوبی تأمل کنید
سرویسهای شخص ثالث مانند Google Analytics ،Intercom ،Mixpanel و صدها مورد دیگر میتوانند یک راهکار به صورت «یک کد خط» برای نیازهای بیزینسی شما فراهم کنند. اما آنها همزمان میتوانند کاری کنند که وبسایت شما آسیبپذیر شود، زیرا اگر یک سرویس شخص ثالث به مخاطره بیفتد، وبسایت شما نیز در معرض خطر قرار خواهد گرفت.
پیش از آن که در مورد ادغام یک سرویس شخص ثالث تصمیم بگیرید، مطمئن شوید که قویترین سیاست CSP را که امکان کارکرد نرمال آن سرویس را فراهم میسازد، تعیین کردهاید. اغلب سرویسهای محبوب دایرکتیوهای CSP که برای کارکرد خود نیاز دارند را مشخص ساختهاند و از این رو میتوانید از خطوط راهنمایی که ارائه شده بهره بگیرید.
در زمان استفاده از Google Tag Manager ،Segment یا دیگر ابزارها که به هر فردی در سازمان شما امکان میدهند که سرویسهای بیشتری را در وبسایت ادغام کند، باید مراقبت خاصی به خرج بدهید. افرادی که به چنین ابزارهایی دسترسی دارند باید اهمیت امنیتی اتصال سرویسهای اضافی را درک کنند و چه بهتر که این موضوع را با تیم توسعه به مشورت بگذارند.
از Subresource Integrity برای اسکریپتهای ثالث استفاده کنید
در مورد همه اسکریپتهای شخص ثالث که استفاده میکنید، مطمئن شوید که در موارد ممکن خصوصیت integrity ارائه شده است. مرورگرها یک قابلیت به نام «یکپارچهسازی زیرمنابع» (Subresource Integrity) دارند که میتواند هش رمزنگاری اسکریپت را که بارگذاری میشود بررسی کرده و مطمئن شود که دستکاری نشده است. به این ترتیب تگ اسکریپت شما میتواند به صورت زیر باشد:
1<script src="https://example.com/example-framework.js"
2 integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
3 crossorigin="anonymous"></script>
لازم به ذکر است که این تکنیک برای کتابخانههای شخص ثالث مفید است، اما در مورد سرویسهای شخص ثالث نیز تا حدود کمتری مفید است. در اغلب موارد زمانی که یک اسکریپت را به یک سرویس شخص ثالث اضافه میکنید، آن اسکریپت تنها برای بارگذاری اسکریپت وابسته دیگر استفاده میشود. امکان بررسی یکپارچگی اسکریپت وابسته وجود ندارد، زیرا میتواند در هر زمانی ویرایش شود. از این رو در این مورد باید از روش جایگزین سیاست امنیت محتوای صریح استفاده کنیم.
سخن پایانی
حفظ تجربه کاربر در مرورگر بخشی مهم از هر وباپلیکیشن مدرن محسوب میشود. کاربران میخواهند مطمئن باشند که دادههای شخصیشان امن و محرمانه باقی میماند. با این که این دادهها در سمت بکاند ذخیره میشوند، اما مسئولیت امنسازی دادهها در سمت کلاینت اپلیکیشنها نیز وجود دارد.
انواع بسیار دیگری از حملههای اول-UI نیز وجود دارند که کاربران خرابکار میتوانند از آنها بهره بگیرند، اما شما با رعایت 10 نکتهای که در این راهنما مورد اشاره قرار گرفتند، میتوانید امنیت وباپلیکیشن خود را تا حدود بسیار زیادی ارتقا ببخشید.