クロスサイトスクリプティング(XSS)は、悪意のある攻撃者がクライアントサイドのJavaScriptをウェブサイトに注入し、ユーザーのブラウザの信頼できる環境で実行させる攻撃の一種です。
XSS攻撃を防ぐ最も確実な方法は、注入時点で信頼できないデータをエスケープすることです。つまり、HTMLに実際に注入される時点でエスケープすることです。
データをHTMLエンコードするには<%= %>
を使用します
<h3 is="welcome-msg">Hello <%= me.username %>!</h3>
<h4><%= owner.username %>'s projects:</h4>
<ul><% _.each(projects, function (project) { %>
<li>
<a href="/<%= owner.username %>/<%= project.slug %>"><%= project.friendlyName %></a>
</li>
<% }); %></ul>
ビューローカル変数の全部または一部をクライアントサイドのJavaScriptに安全に公開するには、exposeLocalsToBrowser
パーシャルを使用します
<%- exposeLocalsToBrowser(); %>
<script>
console.log(window.SAILS_LOCALS);
// {
// me: {
// username: 'eleven',
// memberSince: '1982-08-01T05:00:00.000Z'
// },
// owner: {
// username: 'joyce',
// memberSince: '1987-11-03T05:00:00.000Z'
// },
// projects: [
// {
// slug: 'my-neat-stuff-n-things',
// friendlyName: 'My neat stuff & things',
// description: 'Yet another project.'
// },
// {
// slug: 'kind-of-neat-stuff-but-not-that-great',
// friendlyName: 'Kind of neat stuff, but not that great...',
// description: 'I am so sick and tired of these project. <script>alert(\'attack\');</script>'
// }
// ],
// _csrf: 'oon95Uac-wKfWQKC5pHx1rP3HsiN9tjqGMyE'
// }
</script>
この戦略を使用する場合、ビューローカル変数の文字列は、クライアントサイドのJavaScriptに公開された後、HTMLエスケープされなくなります。これは、DOMに文字列を挿入する際に再度エスケープする必要があるためです。注入時点ですべてのエスケープを行うと、これらの管理がはるかに容易になります。このようにすれば、クライアントサイドのJavaScriptからDOMに挿入する任意の文字列を安全にエスケープできることがわかります。(詳細は下記参照)
XSS防止の多くは、クライアントサイドコードで行う操作に関係します。いくつかの例を以下に示します。
データをHTMLエンコードするには<%- %>
を使用します
<div data-template-id="welcome-box">
<h3 is="welcome-msg">Hello <%- me.username %>!</h3>
</div>
$(...).text()
などを使用してデータをHTMLエンコードします
var $welcomeMsg = $('#signup').find('[is="welcome-msg"]');
welcomeMsg.text('Hello, '+window.SAILS_LOCALS.me.username+'!');
// Avoid using `$(...).html()` to inject untrusted data.
// Even if you know an XSS is not possible under particular circumstances,
// accidental escaping issues can cause really, really annoying client-side bugs.
上記例ではjQueryを使用していることを前提としていますが、使用するフロントエンドライブラリに関係なく、同じ概念が適用されます。
- 上記の例では、デフォルトのビューエンジン(EJS)と、デフォルトのアセットパイプラインからのクライアントサイドJST/Lodashテンプレートを使用していることを前提としています。