Chrome'un uzantı sistemi, oldukça katı bir varsayılan İçerik Güvenliği Politikası (İGP) uygular.
Politika kısıtlamaları basittir: Komut dosyası satır dışına, ayrı JavaScript dosyalarına taşınmalı, satır içi etkinlik işleyiciler addEventListener
kullanacak şekilde dönüştürülmelidir ve eval()
devre dışı bırakılmalıdır. Chrome Uygulamalarının daha da katı bir politikası vardır ve bu politikaların sağladığı güvenlik özelliklerinden çok memnunuz.
Bununla birlikte, çeşitli kitaplıkların performans optimizasyonu ve ifade kolaylığı için new Function()
gibi eval()
ve eval
benzeri yapılar kullandığını biliyoruz. Şablon oluşturma kitaplıkları özellikle
bu uygulama tarzına eğilimlidir. Bazıları (Angular.js gibi) CSP'yi kullanıma hazır olarak desteklese de birçok popüler çerçeve, uzantıların eval
içermeyen dünyasıyla uyumlu bir mekanizmaya henüz güncellenmemiştir. Bu nedenle, bu işleve yönelik desteğin kaldırılmasının geliştiriciler için beklenenden daha sorun olduğu kanıtlandı.
Bu belgede, güvenlikten ödün vermeden bu kitaplıkları projelerinize dahil etmek için güvenli bir mekanizma olarak korumalı alan tanıtılmaktadır. Kısaca uzantılar terimini belge boyunca kullanacağız ancak bu kavram, uygulamalar için de aynı şekilde geçerlidir.
Neden korumalı alan?
eval
, çalıştırdığı kod, uzantının yüksek izinli ortamındaki her şeye erişimi olduğundan uzantının içinde tehlikelidir. Kullanıcıların güvenliğini ve gizliliğini önemli ölçüde etkileyebilecek çok sayıda güçlü chrome.*
API kullanıma sunulmuştur. Basit veri hırsızlığı, en az endişelendiğimizdir.
Sunulan çözüm, eval
ürününün, uzantı verilerine veya uzantının yüksek değerli API'lerine erişmeden kod çalıştırabileceği bir korumalı alan olmasıdır. Ne veri, ne API, ne de sorun.
Bunu, belirli HTML dosyalarını uzantı paketi içinde korumalı alan olarak listeleyerek yaparız.
Korumalı alana alınmış bir sayfa her yüklendiğinde benzersiz bir kaynağa taşınır ve chrome.*
API'lerine erişimi reddedilir. Korumalı alana alınmış bu sayfayı bir iframe
aracılığıyla uzantımıza yüklersek söz konusu sayfayı mesaj iletebilir, bu mesajlar üzerinde bir şekilde hareket etmesine izin verebilir ve bize bir sonucu geri vermesini bekleyebiliriz. Bu basit mesajlaşma mekanizması, eval
yönlendirmeli kodu uzantımızın iş akışına güvenli bir şekilde eklemek için ihtiyacımız olan her şeyi sağlıyor.
Korumalı alan oluşturma ve kullanma.
Doğrudan koda geçmek isterseniz lütfen korumalı alan örnek uzantısını alın ve kaldırın. Bu, Handlebars şablon kitaplığının üzerine inşa edilmiş küçük bir mesajlaşma API'sının çalışan bir örneğidir ve size başlamak için ihtiyacınız olan her şeyi sağlayacaktır. Biraz daha açıklama isteyenler için buradaki örneği birlikte inceleyelim.
Manifest'teki dosyaları listeleyin
Korumalı alan içinde çalıştırılması gereken her dosya, bir sandbox
özelliği eklenerek uzantı manifest'inde listelenmelidir. Bu önemli bir adımdır ve kolayca unutulabilir. Bu nedenle, korumalı alana alınan dosyanızın manifest'te listelendiğini lütfen tekrar kontrol edin. Bu örnekte, akıllı bir şekilde "sandbox.html" adını
oluşturan dosyayı korumalı alana alıyoruz. Manifest girişi şöyle görünür:
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
Korumalı alana alınmış dosyayı yükle
Korumalı alana alınan dosyayla ilginç bir şey yapmak için dosyayı uzantı kodunun ele alınabileceği bir bağlamda yüklememiz gerekir. Burada sandbox.html, bir iframe
aracılığıyla uzantının Etkinlik Sayfası'na (eventpage.html) yüklenmiştir. eventpage.js, tarayıcı işlemi her tıklandığında sayfada iframe
öğesini bulup contentWindow
üzerinde postMessage
yöntemini çalıştırarak korumalı alana mesaj gönderen bir kod içerir. Mesaj iki özellik içeren bir nesnedir: context
ve command
. Birazdan her ikisini de ele alacağız.
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.getElementById('theFrame');
var message = {
command: 'render',
context: {thing: 'world'}
};
iframe.contentWindow.postMessage(message, '*');
});
postMessage
API hakkında genel bilgiler için MDN ile ilgili postMessage
dokümanlarına göz atın. Oldukça eksiksiz ve okumaya değer. Özellikle, verilerin yalnızca seri hale getirilebilir olması durumunda karşılıklı olarak aktarılabileceğini unutmayın. Örneğin işlevler buna dahil değildir.Tehlikeli bir şey yap
sandbox.html
yüklendiğinde, Gidon kitaplığını yükler ve Gidbar'ın önerdiği şekilde bir satır içi şablon oluşturup derler:
<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>
Hata yok. Handlebars.compile
, new Function
kodunu kullansa bile işler tam olarak beklendiği gibi çalışır ve templates['hello']
içinde derlenmiş bir şablon elde ederiz.
Sonucu geri verme
Etkinlik Sayfası'ndan gelen komutları kabul eden bir mesaj işleyici oluşturarak bu şablonu kullanılabilir hale getireceğiz. Ne yapılması gerektiğini belirlemek için iletilen command
bilgisini kullanacağız (yalnızca oluşturma işleminden daha fazlasını yapmayı, belki de şablon oluşturmayı düşünebilirsiniz. Belki bunları bir şekilde yönetir misiniz?) ve context
, oluşturma için doğrudan şablona iletilir. Oluşturulan HTML, Etkinlik Sayfası'na geri gönderilir ve böylece uzantı daha sonra bununla ilgili faydalı bir şey yapabilir:
<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>
Etkinlik Sayfası'na döndüğünüzde, bu mesajı alıp ilettiğimiz html
verileriyle ilginç bir şey yapacağız. Bu örnekte, bunu bir Masaüstü Bildirimi ile vurgulayacağız, ancak bu HTML'yi, uzantının kullanıcı arayüzünün bir parçası olarak güvenli bir şekilde kullanmak tamamen mümkündür. Korumalı alana alınmış kodun zekice bir saldırıyla ele alınması dahi yüksek izinli uzantı bağlamına tehlikeli komut dosyası veya eklenti içeriği ekleyemeyeceğinden, innerHTML
aracılığıyla eklenmesi önemli bir güvenlik riski oluşturmaz.
Bu mekanizma, şablon oluşturmayı basitleştirir ancak elbette şablon oluşturmakla sınırlı değildir. Katı İçerik Güvenliği Politikası kapsamında çalışmayan tüm kodlar korumalı alana alınabilir. Aslında, programınızın her bir parçasını doğru yürütülmesi için gereken en küçük ayrıcalık grubuyla kısıtlamak üzere, doğru şekilde çalışacak uzantılarınızın korumalı alana alınması genellikle yararlıdır. Google I/O 2012'deki Write Secure Web Apps and Chrome Extensions (Güvenli Web Uygulamaları ve Chrome Uzantıları Yazma) sunumunda, bu tekniği uygulamalı olarak ne kadar başarılı örneklerle görebilirsiniz? Bu sunum için 56 dakikanızı ayırmanız yeterli.