trust(html)
Opis
Konwertuje ciąg HTML lub SVG na nieeskejpowany HTML lub SVG. Nie używaj m.trust
na danych pochodzących od użytkownika, które nie zostały uprzednio zweryfikowane i oczyszczone.
Zawsze rozważ alternatywne metody zanim użyjesz m.trust
.
Sygnatura
vnode = m.trust(html)
Argument | Typ | Wymagany | Opis |
---|---|---|---|
html | String | Tak | Ciąg znaków zawierający kod HTML lub SVG |
zwraca | Vnode | Zaufany vnode HTML, reprezentujący ciąg wejściowy |
Jak to działa
Domyślnie Mithril.js poddaje eskejpingu wszystkie wartości, aby zapobiec problemom związanym z bezpieczeństwem, znanym jako ataki XSS.
var userContent = "<script>alert('evil')</script>";
var view = m('div', userContent);
m.render(document.body, view);
// odpowiednik HTML
// <div><script>alert('evil')</script></div>
Jednak czasami konieczne jest renderowanie sformatowanego tekstu i znaczników formatowania. W takich przypadkach m.trust
tworzy zaufany vnode HTML, który jest renderowany jako HTML.
var view = m('div', [m.trust("<h1>Here's some <em>HTML</em></h1>")]);
m.render(document.body, view);
// odpowiednik HTML
// <div><h1>Here's some <em>HTML</em></h1></div>
Zaufane vnode HTML są obiektami, a nie ciągami znaków; dlatego nie można ich łączyć bezpośrednio ze zwykłymi ciągami znaków.
Kwestie bezpieczeństwa
Konieczne jest zabezpieczenie danych wejściowych przekazywanych do m.trust
, aby upewnić się, że ciąg HTML nie zawiera złośliwego kodu wprowadzonego przez użytkownika. Jeśli nie zabezpieczysz ciągu HTML przed oznaczeniem go jako zaufanego, wszelkie asynchroniczne wywołania JavaScript zawarte w ciągu HTML zostaną uruchomione i wykonane z uprawnieniami użytkownika przeglądającego stronę.
Istnieje wiele sposobów, w jakie ciąg HTML może zawierać kod wykonywalny. Najczęstsze metody wstrzykiwania ataków bezpieczeństwa to dodawanie atrybutów onload
lub onerror
w tagach <img>
lub <iframe>
oraz używanie niezbalansowanych cudzysłowów, takich jak " onerror="alert(1)
, aby wstrzyknąć konteksty wykonywalne w niezabezpieczonych interpolacjach ciągów znaków.
var data = {};
// Przykładowy ciąg HTML podatny na ataki
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// Atak wykorzystujący atrybuty związane z JavaScript
data.description = "<img onload='alert(1)'>";
// Atak wykorzystujący niezbalansowane tagi
data.description = "</span><img onload='alert(1)'><span";
// Atak wykorzystujący niezbalansowane cudzysłowy
data.title = "' onerror='alert(1)";
// Atak wykorzystujący inny atrybut
data.title = "' onmouseover='alert(1)";
// Atak, który nie wykorzystuje JavaScript
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Kliknij tutaj, aby przeczytać więcej</a>";
Istnieje wiele subtelnych sposobów na wprowadzenie złośliwego kodu, dlatego wysoce zalecane jest użycie białej listy dozwolonych tagów HTML, atrybutów i wartości atrybutów, zamiast czarnej listy, do oczyszczania danych wejściowych użytkownika. Zaleca się również użycie odpowiedniego parsera HTML zamiast wyrażeń regularnych do oczyszczania, ponieważ wyrażenia regularne są niezwykle trudne do przetestowania pod kątem wszystkich przypadków brzegowych.
Skrypty, które się nie uruchamiają
Pomimo wielu nieoczywistych sposobów na uruchomienie JavaScript w ciągu HTML, tagi <script>
nie są wykonywane, gdy pojawiają się w ciągu HTML.
Z przyczyn historycznych przeglądarki ignorują tagi <script>
, które są wstawiane do DOM za pomocą innerHTML
. Dzieje się tak, ponieważ gdy element jest gotowy (a zatem ma dostępną właściwość innerHTML
), silniki renderujące nie mogą cofnąć się do etapu parsowania, jeśli skrypt wywołuje coś takiego jak document.write("</body>")
.
To zachowanie przeglądarki może być zaskakujące dla programistów migrujących z jQuery, ponieważ jQuery implementuje kod specjalnie do znajdowania tagów skryptów i uruchamiania ich w tym scenariuszu. Mithril.js zachowuje się zgodnie z przeglądarką. Jeśli pożądane jest zachowanie jQuery, należy rozważyć przeniesienie kodu z ciągu HTML do metody cyklu życia oncreate
lub użycie jQuery (lub ponowne zaimplementowanie jego kodu parsowania skryptów).
Unikaj zaufania HTML
Ogólną zasadą jest unikanie używania m.trust
, chyba że renderujesz sformatowany tekst i nie ma innego sposobu na uzyskanie pożądanych rezultatów.
// UNIKAJ
m('div', m.trust('hello world'));
// PREFERUJ
m('div', 'hello world');
Unikaj ślepego kopiowania i wklejania
Częstym błędem jest używanie m.trust
podczas pracy z usługami stron trzecich. Ich samouczki często zawierają kod HTML do skopiowania i wklejenia. W większości przypadków kod HTML powinien być napisany przy użyciu vnode (zazwyczaj za pomocą funkcji m()
).
Oto przykładowy fragment kodu dla przycisku Lubię to Facebooka:
<!-- Load Facebook SDK for JavaScript -->
<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>
<!-- Your like button code -->
<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>
A oto jak refaktoryzować go do komponentu Mithril.js w sposób, który unika m.trust
:
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]'
),
];
},
};
Powyższy komponent Mithril.js po prostu przenosi kod tagu skryptu do metody oncreate
i deklaruje pozostałe tagi HTML za pomocą składni m()
Mithril.js.
Unikaj encji HTML
Częstym przypadkiem niewłaściwego użycia m.trust
jest używanie go dla encji HTML. Lepszym podejściem jest użycie odpowiednich znaków Unicode:
// UNIKAJ
m('h1', 'Coca-Cola', m.trust('™'));
// PREFERUJ
m('h1', 'Coca-Cola™');
Znaki Unicode dla znaków akcentowanych można wpisywać za pomocą układu klawiatury dla odpowiedniego języka. Można również zapamiętać skróty klawiaturowe do tworzenia powszechnie używanych symboli (np. Alt+0153
w systemie Windows lub Option+2
na komputerze Mac dla symbolu ™). Inną metodą jest wpisanie zakodowanego punktu kodowego Unicode (np. "\u2122"
dla symbolu ™).
Wszystkie znaki, które można przedstawić jako encje HTML, mają odpowiedniki Unicode, w tym znaki niewidoczne, takie jak
i ­
.
Aby uniknąć problemów z kodowaniem, należy ustawić kodowanie pliku na UTF-8 w pliku JavaScript. Należy również dodać tag meta <meta charset="utf-8">
w pliku HTML hosta.