استفاده از eval در افزونه های کروم، استفاده از eval در افزونه های کروم

سیستم برنامه افزودنی 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 دقیقه وقت شما را دارد.