سیستم برنامه افزودنی Chrome یک خطمشی امنیت محتوای پیشفرض نسبتاً سختگیرانه (CSP) را اعمال میکند. محدودیتهای خطمشی ساده هستند: اسکریپت باید خارج از خط به فایلهای جاوا اسکریپت جداگانه منتقل شود، کنترلکنندههای رویداد درون خطی باید برای استفاده از addEventListener
تبدیل شوند و eval()
غیرفعال است. Chrome Apps خطمشی سختگیرانهتری دارد و ما از ویژگیهای امنیتی این خطمشیها کاملاً راضی هستیم.
با این حال، میدانیم که کتابخانههای مختلفی از eval()
و ساختارهای شبیه eval
مانند new Function()
برای بهینهسازی عملکرد و سهولت بیان استفاده میکنند. کتابخانه های الگو به ویژه مستعد این سبک پیاده سازی هستند. در حالی که برخی (مانند Angular.js ) از CSP خارج از جعبه پشتیبانی میکنند، بسیاری از فریمورکهای محبوب هنوز به مکانیزمی که با دنیای eval
افزونهها سازگار باشد، بهروزرسانی نشدهاند. بنابراین حذف پشتیبانی از آن عملکرد برای توسعهدهندگان مشکلسازتر از حد انتظار بوده است.
این سند sandboxing را به عنوان مکانیزم ایمن برای گنجاندن این کتابخانه ها در پروژه های خود بدون به خطر انداختن امنیت معرفی می کند. برای اختصار، ما از اصطلاح پسوندها در سراسر استفاده خواهیم کرد، اما این مفهوم به همان اندازه برای برنامهها کاربرد دارد.
چرا سندباکس؟
eval
در داخل یک برنامه افزودنی خطرناک است زیرا کدی که اجرا می کند به همه چیز در محیط با مجوز بالا دسترسی دارد. تعداد زیادی chrome.*
استخراج ساده داده ها کمترین نگرانی ماست. راه حل ارائه شده یک جعبه شنی است که در آن eval
می تواند کد را بدون دسترسی به داده های برنامه افزودنی یا API های با ارزش بالای برنامه افزودنی اجرا کند. بدون داده، بدون API، بدون مشکل.
ما این کار را با فهرست کردن فایل های HTML خاص در داخل بسته برنامه افزودنی به عنوان جعبه شنی انجام می دهیم. هر زمان که یک صفحه sandbox بارگیری شود، به یک مبدا منحصر به فرد منتقل می شود و از دسترسی به chrome.*
API. اگر این صفحه سندباکس را از طریق iframe
در برنامه افزودنی خود بارگذاری کنیم، میتوانیم پیامهایی را به آن ارسال کنیم، اجازه دهیم به نحوی روی آن پیامها عمل کند و منتظر بمانیم تا نتیجه را به ما ارسال کند. این مکانیسم پیامرسانی ساده همه چیزهایی را که برای گنجاندن کدهای مبتنی بر eval
در گردش کار برنامه افزودنی نیاز داریم، به ما میدهد.
ایجاد و استفاده از جعبه شنی
اگر میخواهید مستقیماً وارد کد شوید، لطفاً پسوند نمونه sandboxing را بردارید و بلند شوید . این یک نمونه کاربردی از یک API پیام کوچک است که در بالای کتابخانه قالب Handlebars ساخته شده است، و باید همه چیزهایی را که برای شروع به کار نیاز دارید در اختیار شما قرار دهد. برای کسانی از شما که میخواهید کمی توضیح بیشتری بدهید، بیایید این نمونه را با هم در اینجا مرور کنیم.
فایلها را در مانیفست فهرست کنید
هر فایلی که باید در یک جعبه ایمنی اجرا شود باید با افزودن یک ویژگی sandbox
در مانیفست پسوند فهرست شود. این یک مرحله حیاتی است و فراموش کردن آن آسان است، بنابراین لطفاً دوباره بررسی کنید که فایل sandbox شما در مانیفست فهرست شده باشد. در این نمونه، فایلی را با نام هوشمندانه "sandbox.html" sandbox می کنیم. ورودی مانیفست به شکل زیر است:
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
فایل سندباکس را بارگیری کنید
برای انجام کاری جالب با فایل sandboxed، باید آن را در زمینه ای بارگذاری کنیم که بتوان با کد افزونه به آن پرداخت. در اینجا، sandbox.html از طریق iframe
در صفحه رویداد برنامه افزودنی ( eventpage.html ) بارگیری شده است. eventpage.js حاوی کدی است که هر زمان که روی عملکرد مرورگر کلیک شود، با یافتن iframe
در صفحه و اجرای متد postMessage
در contentWindow
آن، پیامی را به جعبه ایمنی ارسال میکند. پیام یک شی حاوی دو ویژگی است: context
و command
. ما در یک لحظه به هر دو می پردازیم.
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.getElementById('theFrame');
var message = {
command: 'render',
context: {thing: 'world'}
};
iframe.contentWindow.postMessage(message, '*');
});
postMessage
API، نگاهی به مستندات postMessage
در MDN بیندازید. کاملا کامله و ارزش خوندن داره به ویژه، توجه داشته باشید که داده ها تنها در صورتی می توانند به عقب و جلو منتقل شوند که قابل سریال سازی باشند. توابع، برای مثال، نیستند.یه کار خطرناک انجام بده
هنگامی که sandbox.html
بارگیری می شود، کتابخانه Handlebars را بارگیری می کند و یک الگوی درون خطی را به روشی که Handlebars پیشنهاد می کند ایجاد و کامپایل می کند:
<script src="handlebars-1.0.0.beta.6.js"></script>
<script id="hello-world-template" type="text/x-handlebars-template">
<div class="entry">
<h1>Hello, !</h1>
</div>
</script>
<script>
var templates = [];
var source = document.getElementById('hello-world-template').innerHTML;
templates['hello'] = Handlebars.compile(source);
</script>
این شکست نمی خورد! حتی اگر Handlebars.compile
از new Function
استفاده میکند، همه چیز دقیقاً همانطور که انتظار میرود کار میکند، و در نهایت با یک الگوی کامپایل شده در templates['hello']
مواجه میشویم.
نتیجه را به عقب برگردانید
ما این الگو را با راه اندازی یک شنونده پیام که دستورات صفحه رویداد را می پذیرد، برای استفاده در دسترس قرار می دهیم. ما از command
ارسال شده برای تعیین اینکه چه کاری باید انجام شود استفاده خواهیم کرد (شما می توانید تصور کنید که کاری بیش از رندر کردن ساده انجام دهید؛ شاید ایجاد الگوها؟ شاید آنها را به نحوی مدیریت کنید؟)، و context
مستقیماً برای رندر به قالب منتقل می شود. . HTML رندر شده به صفحه رویداد بازگردانده می شود تا برنامه افزودنی بتواند بعداً با آن کار مفیدی انجام دهد:
<script>
window.addEventListener('message', function(event) {
var command = event.data.command;
var name = event.data.name || 'hello';
switch(command) {
case 'render':
event.source.postMessage({
name: name,
html: templates[name](event.data.context)
}, event.origin);
break;
// case 'somethingElse':
// ...
}
});
</script>
به صفحه رویداد برمی گردیم، این پیام را دریافت می کنیم و با داده های html
که به ما ارسال شده است، کار جالبی انجام می دهیم. در این مورد، ما فقط آن را از طریق یک اعلان دسکتاپ بازتاب میدهیم، اما استفاده از این HTML بهعنوان بخشی از رابط کاربری افزونه کاملاً ممکن است. درج آن از طریق innerHTML
خطر امنیتی قابل توجهی ایجاد نمی کند، زیرا حتی در معرض خطر قرار گرفتن کامل کدهای sandbox شده از طریق برخی حملات هوشمندانه نمی تواند اسکریپت یا محتوای پلاگین خطرناک را در زمینه افزونه با مجوز بالا تزریق کند.
این مکانیسم قالب بندی را ساده می کند، اما البته به قالب بندی محدود نمی شود. هر کدی که تحت یک خطمشی امنیتی سختگیرانه محتوا کار نمیکند، میتواند در جعبه ایمنی قرار گیرد. در واقع، اغلب برای اجزای سندباکس افزونههای شما مفید است که به درستی اجرا میشوند تا هر بخش از برنامه شما را به کوچکترین مجموعهای از امتیازات لازم برای اجرای صحیح آن محدود کند. ارائه Writing Secure Web Apps and Chrome Extensions از Google I/O 2012 چند نمونه خوب از این تکنیک ها را در عمل ارائه می دهد و ارزش 56 دقیقه وقت شما را دارد.