trust(html)
Açıklama
Bir HTML veya SVG dizesini, karakterlerden kaçış yapılmamış (unescaped) HTML veya SVG'ye dönüştürür. Temizlenmemiş kullanıcı girdileri için m.trust
kullanmayın.
m.trust
kullanmayı düşünmeden önce, öncelikle alternatif bir yöntem kullanmayı deneyin.
İmza
vnode = m.trust(html)
Argüman | Tür | Gerekli | Açıklama: |
---|---|---|---|
html | String | Evet | HTML veya SVG metni içeren bir dize. |
dönüş | Vnode | Giriş dizesini temsil eden güvenilir bir HTML vnode'u. |
Nasıl Çalışır
Mithril.js, varsayılan olarak, XSS enjeksiyonları olarak adlandırılan bir güvenlik açığı sınıfını önlemek amacıyla tüm değerleri otomatik olarak kodlar (escape eder).
var userContent = "<script>alert('evil')</script>";
var view = m('div', userContent);
m.render(document.body, view);
// eşdeğer HTML
// <div><script>alert('evil')</script></div>
Ancak, bazen zengin metin ve biçimlendirme işaretlemesi oluşturmak istenebilir. Bu ihtiyacı karşılamak için m.trust
, HTML olarak yorumlanan güvenilir HTML vnode'ları oluşturur.
var view = m('div', [m.trust("<h1>Here's some <em>HTML</em></h1>")]);
m.render(document.body, view);
// eşdeğer HTML
// <div><h1>Here's some <em>HTML</em></h1></div>
Güvenilir HTML vnode'ları dize değil nesne olduklarından, normal dizelerle doğrudan birleştirilemezler.
Güvenlik Hususları
HTML dizesinde kötü amaçlı kod bulunmadığından emin olmak için m.trust
'ın girdisini temizlemeniz (sanitize etmeniz) gerekir. Bir HTML dizesini temizlemez ve güvenilir olarak işaretlemezseniz, bu HTML dizesindeki eşzamansız JavaScript çağrıları tetiklenebilir ve bu sayfayı görüntüleyen kullanıcının yetkileriyle çalıştırılabilir.
Bir HTML dizesinin yürütülebilir kod içerebileceği birçok yol vardır. Güvenlik saldırıları enjekte etmenin en yaygın yolları, <img>
veya <iframe>
etiketlerine onload
veya onerror
öznitelikleri eklemek ve temizlenmemiş dize interpolasyonlarında yürütülebilir bağlamlar enjekte etmek için " onerror="alert(1)
gibi eşleşmeyen tırnak işaretleri kullanmaktır.
var data = {};
// Örnek savunmasız HTML dizesi
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// JavaScript ile ilgili öznitelikleri kullanan bir saldırı
data.description = "<img onload='alert(1)'>";
// Dengesiz etiketler kullanan bir saldırı
data.description = "</span><img onload='alert(1)'><span";
// Dengesiz tırnak işaretleri ile yapılan bir saldırı
data.title = "' onerror='alert(1)";
// Farklı bir öznitelik kullanan bir saldırı
data.title = "' onmouseover='alert(1)";
// JavaScript kullanmayan bir saldırı
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Daha fazla bilgi için buraya tıklayın</a>";
Kötü amaçlı kod oluşturmanın birçok gizli yolu olduğundan, kullanıcı girdilerini temizlerken bir kara liste kullanmak yerine, izin verilen HTML etiketleri, nitelikleri ve nitelik değerlerinden oluşan bir beyaz liste kullanmanız kesinlikle önerilir. Ayrıca, tüm olası durumlar için düzenli ifadeleri test etmek çok zor olduğundan, temizleme işlemi için düzenli ifadeler yerine uygun bir HTML ayrıştırıcısı (parser) kullanmanız şiddetle tavsiye edilir.
Çalışmayan Betikler
Bir HTML dizesinin JavaScript çalıştırmasını sağlamanın birçok karmaşık yolu olmasına rağmen, bir HTML dizesinde göründüğünde çalışmayan bir şey <script>
etiketleridir.
Tarihsel nedenlerden dolayı, tarayıcılar innerHTML
aracılığıyla DOM'a eklenen <script>
etiketlerini yok sayar. Bunu yaparlar çünkü öğe hazır olduğunda (ve dolayısıyla erişilebilir bir innerHTML
özelliği olduğunda), betik document.write("</body>")
gibi bir şey çağırırsa, işleme motorları ayrıştırma aşamasına geri dönemez.
Bu tarayıcı davranışı, jQuery kullanmaya alışkın bir geliştirici için şaşırtıcı olabilir, çünkü jQuery, bu senaryoda özellikle script etiketlerini bulup çalıştırmak için özel kodlar kullanır. Mithril.js, tarayıcı davranışını izler. jQuery davranışı isteniyorsa, kodu HTML dizesinden çıkarıp bir oncreate
yaşam döngüsü yöntemine taşımayı veya jQuery'yi kullanmayı (veya betik ayrıştırma kodunu yeniden uygulamayı) düşünebilirsiniz.
HTML'ye Güvenmekten Kaçının
Genel bir prensip olarak, zengin metinler oluşturmadığınız ve istediğiniz sonuçlara ulaşmanın başka bir yolu kalmadığı durumlarda m.trust
kullanmaktan kaçınmalısınız.
// KAÇININ
m('div', m.trust('hello world'));
// TERCİH EDİN
m('div', 'hello world');
Düşünmeden Kopyalama ve Yapıştırmadan Kaçının
m.trust
'ı yanlış kullanmanın yaygın bir yolu, eğitimlerinde kopyalanıp yapıştırılan HTML kodları bulunan üçüncü taraf servislerle çalışırken ortaya çıkar. Çoğu durumda, HTML, vnode'lar kullanılarak yazılmalıdır (tipik olarak m()
yardımcı programı aracılığıyla).
Facebook Beğen düğmesi için örnek snippet:
<!-- JavaScript için Facebook SDK'sını yükleyin -->
<div id="fb-root"></div>
<script>
(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = '//connect.facebook.net/en_US/sdk.js#xfbml=1';
fjs.parentNode.insertBefore(js, fjs);
})(document, 'script', 'facebook-jssdk');
</script>
<!-- Beğen düğmesi kodunuz -->
<div
class="fb-like"
data-href="https://www.your-domain.com/your-page.html"
data-layout="standard"
data-action="like"
data-show-faces="true"
></div>
Ve işte m.trust
'tan kaçınan bir şekilde bir Mithril.js bileşenine nasıl yeniden düzenleneceği:
var FacebookLikeButton = {
oncreate: function () {
(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = '//connect.facebook.net/en_US/sdk.js#xfbml=1';
fjs.parentNode.insertBefore(js, fjs);
})(document, 'script', 'facebook-jssdk');
},
view: function () {
return [
m('#fb-root'),
m(
'.fb-like[data-href=https://www.your-domain.com/your-page.html][data-layout=standard][data-action=like][data-show-faces=true]'
),
];
},
};
Yukarıdaki Mithril.js bileşeni, betik etiketinin kodunu oncreate
kancasına kopyalar ve kalan HTML etiketlerini Mithril.js'nin m()
sözdizimini kullanarak bildirir.
HTML Karakter Referanslarından Kaçının
m.trust
'ı kötüye kullanmanın yaygın bir yolu, onu HTML karakter referansları (entities) için kullanmaktır. Daha iyi bir yaklaşım, karşılık gelen unicode karakterlerini kullanmaktır:
// KAÇININ
m('h1', 'Coca-Cola', m.trust('™'));
// TERCİH EDİN
m('h1', 'Coca-Cola™');
Özel karakterler için Unicode karakterleri, ilgili dilin klavye düzeni kullanılarak yazılabilir. Ayrıca, sık kullanılan sembolleri oluşturmak için klavye kısayollarını ezberlemeyi de tercih edebilirsiniz (örneğin, Windows'ta Alt+0153
veya Mac'te ™ sembolü için Option+2
). Bunları üretmenin bir başka basit yöntemi, istenen karakteri bir unicode karakter tablosundan kopyalayıp yapıştırmaktır. Bir başka ilgili yöntem ise, kaçış dizili bir unicode kod noktasını yazmaktır (örneğin, ™ sembolü için "\u2122"
).
HTML karakter referansları olarak temsil edilebilen tüm karakterlerin,
ve ­
gibi görünmeyen karakterler de dahil olmak üzere unicode karşılıkları vardır.
Kodlama sorunlarını önlemek için, JavaScript dosyasının kodlamasını UTF-8 olarak ayarlamanın yanı sıra, ana HTML dosyanıza <meta charset="utf-8">
meta etiketini eklemelisiniz.