trust(html)
Description
HTML 또는 SVG 문자열을 이스케이프 처리 없이 HTML 또는 SVG로 변환합니다. 검증되지 않은 사용자 입력에 m.trust
를 사용하지 마십시오.
m.trust
를 사용하기 전에 항상 대체 방법을 먼저 고려하십시오.
Signature
vnode = m.trust(html)
인수 | 타입 | 필수 여부 | 설명 |
---|---|---|---|
html | String | 예 | HTML 또는 SVG 텍스트를 포함하는 문자열 |
반환 값 | Vnode | 입력 문자열을 나타내는 신뢰할 수 있는 HTML vnode |
How it works
기본적으로 Mithril.js는 XSS (Cross-site scripting) 공격과 같은 보안 문제를 방지하기 위해 모든 값을 이스케이프 처리합니다.
var userContent = "<script>alert('evil')</script>";
var view = m('div', userContent);
m.render(document.body, view);
// equivalent HTML
// <div><script>alert('evil')</script></div>
하지만 때로는 서식이 풍부한 텍스트나 마크업을 렌더링해야 할 필요가 있습니다. 이러한 요구 사항을 충족하기 위해 m.trust
는 HTML로 렌더링되는 신뢰할 수 있는 HTML vnode를 생성합니다.
var view = m('div', [m.trust("<h1>Here's some <em>HTML</em></h1>")]);
m.render(document.body, view);
// equivalent HTML
// <div><h1>Here's some <em>HTML</em></h1></div>
신뢰할 수 있는 HTML vnode는 문자열이 아닌 객체이므로 일반 문자열과 연결할 수 없습니다.
Security considerations
HTML 문자열에 사용자 생성 악성 코드가 없는지 확인하려면 m.trust
에 전달되는 입력을 반드시 검증해야 합니다. HTML 문자열을 검증하지 않고 신뢰할 수 있는 문자열로 표시하면 HTML 문자열 내의 모든 비동기 JavaScript 호출 지점이 트리거되어 페이지를 보는 사용자의 권한 수준으로 실행될 수 있습니다.
HTML 문자열에 실행 가능한 코드가 포함될 수 있는 방법은 여러 가지가 있습니다. 보안 공격을 주입하는 가장 일반적인 방법은 <img>
또는 <iframe>
태그에 onload
또는 onerror
속성을 추가하거나, 안전하지 않은 문자열 보간에서 실행 가능한 컨텍스트를 주입하기 위해 " onerror="alert(1)
과 같이 닫히지 않은 따옴표를 사용하는 것입니다.
var data = {};
// Sample vulnerable HTML string
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// An attack using JavaScript-related attributes
data.description = "<img onload='alert(1)'>";
// An attack using unbalanced tags
data.description = "</span><img onload='alert(1)'><span";
// An attack using unbalanced quotes
data.title = "' onerror='alert(1)";
// An attack using a different attribute
data.title = "' onmouseover='alert(1)";
// An attack that does not use JavaScript
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Click here to read more</a>";
악성 코드를 생성하는 방법은 매우 다양하므로 사용자 입력을 검증하기 위해 블랙리스트 대신 허용된 HTML 태그, 속성 및 속성 값의 화이트리스트를 사용하는 것이 좋습니다. 또한 정규 표현식은 모든 예외적인 경우를 테스트하기 어렵기 때문에 사용자 입력 검증 시 정규 표현식보다는 적절한 HTML 파서를 사용하는 것이 좋습니다.
Scripts that do not run
HTML 문자열이 JavaScript를 실행하도록 만드는 방법은 많지만, HTML 문자열에 나타날 때 실행되지 않는 것 중 하나는 <script>
태그입니다.
과거의 이유로 브라우저는 innerHTML
을 통해 DOM에 삽입된 <script>
태그를 무시합니다. 요소가 준비되면 (따라서 액세스 가능한 innerHTML
속성을 가짐) 스크립트가 document.write("</body>")
와 같은 것을 호출하는 경우 렌더링 엔진이 구문 분석 단계로 되돌아갈 수 없기 때문에 이러한 동작을 합니다.
이 브라우저 동작은 jQuery를 사용하던 개발자에게는 놀라운 일일 수 있습니다. jQuery는 스크립트 태그를 찾아 이 시나리오에서 실행하기 위해 특별히 코드를 구현하기 때문입니다. Mithril.js는 브라우저 동작을 따릅니다. jQuery 동작이 필요한 경우 HTML 문자열에서 코드를 이동하여 oncreate
라이프사이클 메서드로 이동하거나 jQuery를 사용 (또는 스크립트 구문 분석 코드를 다시 구현)하는 것을 고려해야 합니다.
Avoid trusting HTML
일반적으로 서식이 있는 텍스트를 렌더링해야 하고 다른 방법으로는 원하는 결과를 얻을 수 없는 경우에만 m.trust
를 사용하는 것을 고려해야 합니다.
// AVOID
m('div', m.trust('hello world'));
// PREFER
m('div', 'hello world');
Avoid blind copying and pasting
m.trust
를 잘못 사용하는 일반적인 방법 중 하나는 HTML 코드를 복사하여 붙여넣도록 안내하는 타사 서비스를 이용할 때 발생합니다. 대부분의 경우 HTML은 vnode를 사용하여 작성해야 합니다 (일반적으로 m()
유틸리티를 통해).
다음은 Facebook Like button에 대한 예제 스니펫입니다.
<!-- 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>
다음은 m.trust
를 피하는 방식으로 Mithril.js 컴포넌트로 리팩터링하는 방법입니다.
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]'
),
];
},
};
위의 Mithril.js 컴포넌트는 단순히 스크립트 태그의 코드를 oncreate
후크에 복사하고 Mithril.js의 m()
구문을 사용하여 나머지 HTML 태그를 선언합니다.
Avoid HTML entities
m.trust
를 잘못 사용하는 일반적인 방법은 HTML 엔티티에 사용하는 것입니다. 더 나은 방법은 해당 유니코드 문자를 사용하는 것입니다.
// AVOID
m('h1', 'Coca-Cola', m.trust('™'));
// PREFER
m('h1', 'Coca-Cola™');
특수 문자에 대한 유니코드 문자는 해당 언어의 키보드 레이아웃을 사용하여 입력할 수 있으며, 일반적으로 사용되는 기호를 생성하기 위해 키보드 단축키를 암기할 수도 있습니다 (예: Windows에서 Alt+0153
또는 Mac에서 ™ 기호의 경우 Option+2
). 이를 생성하는 또 다른 간단한 방법은 유니코드 문자 테이블에서 원하는 문자를 복사하여 붙여넣는 것입니다. 또 다른 방법은 이스케이프된 유니코드 코드 포인트(예: ™ 기호의 경우 "\u2122"
)를 사용하는 것입니다.
HTML 엔티티로 표현 가능한 모든 문자는
나 ­
와 같은 공백 문자나 하이픈을 포함하여 유니코드 문자로 대체할 수 있습니다.
인코딩 문제를 피하려면 JavaScript 파일에서 파일 인코딩을 UTF-8로 설정하고 호스트 HTML 파일에 <meta charset="utf-8">
메타 태그를 추가해야 합니다.