درود دوستان! یکی از مباحث مهم توی بحث امنیت برنامههای فرانتاندی، نحوهٔ تعامل با اسکریپتهای خارجی یا بهقول معروف Third-party scripts هست. این اسکریپتها وقتی به صفحه اضافه میشن، کنترل کاملی روی همه اطلاعات صفحه دارن. همین موضوع میتونه باعث ایجاد مشکلات امنیتی جدی توی برنامه بشه، که یکی از اونها رو توی این قسمت بررسی میکنیم.
مشکل کجاست؟
خیلی اوقات اسکریپتهای ما از یک CDN لود میشن. مثلاً میخوایم یک اسکریپت خارجی مثل یک پکیج جاوااسکریپتی که خیلی هم معروف هست رو به برنامه اضافه کنیم. به خودمون میگیم این پکیج خیلی معروفه پس چشمبسته اون رو به صفحه اضافه میکنیم:
<script src="https://unpkg.com/vue@3.2.1"></script>
اما اگه این وبسایتی که از اون داریم پکیج رو فراخونی میکنیم هک بشه چطور؟ و هکر کدهای دلخواه خودش رو توی اون اسکریپت قرار بده و اون توی برنامهٔ ما لود بشه چطور؟ چطوری میتونیم از اون جلوگیری کنیم؟ جواب، استفاده از یک تکنیک به اسم Subresource Integrity هست 💪
Subresouce Integrity چیه؟
Subresouce Integrity که بهطور خلاصه به اون میگیم SRI، یک قابلیت امنیتی که توی مرورگرهاست و اجازهٔ لود شدن یک ریسورس رو زمانی میده اون ریسورس هیچ تغییری نکرده باشه. توی این تکنیک، از ریسورس مد نظر یک Hash (رشته منحصر به فرد) ساخته میشه و ما باید اون رو به این شکل موقع فراخونی ریسورس (تگهای <script> یا <link>) ازش استفاده کنیم:
<script src="..." integrity="sha256-abc123..."></script>
توی اتریبیوت integrity هش مربوط به فایل رو قرار میدیم. وقتی مرورگر فایل رو از آدرس مد نظر دریافت میکنه، ابتدا خودش محاسباتی رو انجام میده تا هش فایل رو بدست بیاره، و بعد اون رو با مقدار integrity ارائهداده شده روی اسکریپت مقایسه میکنه. حتی اگه یک بایت از ریسورس تغییر کنه، مقدار هش اون فایل هم تغییر میکنه. بنابراین اگه این هشها با هم برابر باشن، مرورگر اجازهٔ لود اون اسکریپت رو میده. در غیر این صورت مرورگر خطایی میده که به دلیل عدم تطابق مقادیر هش، اسکریپت بلاک شد:
Failed to find a valid digest in the 'integrity' attribute for resource 'https://example.com/script.js' with computed SHA-256 integrity. The resource has been blocked.
برای مثال اگه به برید، میبینید که برای همه ریسورسها اتریبیوت integrity وجود داره.
چطوری مقدار هش یک ریسورس رو بدست بیاریم؟
یک روش بدست آوردن هش یک ریسورس استفاده از دستور زیر توی ترمینال سیستمعامل هست:
openssl dgst -sha384 -binary script.js | openssl base64 -A
توی این روش میبایست اسکریپت رو دانلود کنیم و بعد مسیر اون رو جایگزین script.js توی دستور بالا کنیم. یک روش راحتتر استفاده از وبسایت هست که آدرس ریسورس رو میگیره و هش مد نظر رو برمیگردونه.
چه زمانی استفاده از SRI دردسر ساز میشه؟
همونطور که میدونیم وقتی از CDN هایی مثل یا استفاده میکنیم، میتونیم ورژن ریسورس مد نظر رو توی هم مشخص کنیم. مثلاً:
<script src="https://cdn.example.com/<<lib@latest>>/script.min.js"></script>
گاهی اوقات ورژنهایی که مشخص میکنیم نسبی هستن. مثل latest یا lib@^2.3.0 (که میتونه هر ورژنی باشه از 2.3.0 تا 3.0.0) و یا lib@~2.3.0 (که میتونه هر ورژنی باشه از 2.3.0 تا 2.4.0). بنابراین گرچه آدرس اسکریپت دستنخورده هست، محتویات فایل ممکنه تغییر کنه. اینجاست که هش ریسورس هم تغییر میکنه و در نتیجه مرورگر اون اجازه دانلود اون رو نمیده. توی چنین شرایطی باید حواسمون باشه که باید ورژن دقیق فایل رو مشخص کنیم:
<script src="https://cdn.example.com/lib/<<2.3.4>>/lib.min.js" integrity="sha384-..."></script>
همچنین اگه ریسورسها هنگام درخواستشدن Minify میشن، ممکنه هر بار هش متفاوتی بگیریم. پس استفاده از SRI برای زمانی کاربردی هست که مطمئنیم ریسورسهای ما دستنخورده باقی میمونن.
خب دوستان، امیدوارم از اطلاعاتی که بررسی کردیم استفاده کرده باشین. روزتون خوش. تا یه پست دیگه خدانگهدار 👋😉
