HTMLエンティティ エンコード / デコード

特殊文字をHTMLエンティティ(&、<、©)に変換、またはエンティティを読みやすいテキストに戻します — 双方向・リアルタイム。

971回閲覧

仕組み

HTMLは自身の構文のためにいくつかの文字を予約しています。<>はタグを示し、&はエンティティ参照の開始を示します。これらの文字がページに挿入されるコンテンツ——コメント、ユーザー名、画面にそのまま表示される検索クエリなど——の中にそのまま現れると、ブラウザはそれをテキストとして表示する代わりにマークアップとして解釈しようとします。エンコードはこれらの文字をエンティティ形式(&lt;&gt;&amp;)に変換し、解釈されるのではなく文字どおりに表示されるようにします。デコードはこの逆を行い、&amp;&#8217;のようなエンティティを、それが表す実際の文字に戻します。

これは見た目だけの些細な問題ではなく、セキュリティ上の対策です。コメント欄がユーザーの入力を受け取り、エンコードせずにそのままページのHTMLに挿入してしまうと、訪問者が<script>...</script>と入力するだけで、そのスクリプトが他のすべての訪問者のブラウザ上で実際に実行されてしまう可能性があります。この種の脆弱性はクロスサイトスクリプティング(XSS)と呼ばれ、信頼できない出力をHTMLに触れさせる前にエンコードすることが標準的な防御策です。たとえば5 < 10 & 10 > 5というテキストをエンコードすると5 &lt; 10 &amp; 10 &gt; 5となり、正しく表示されつつマークアップと誤認されることもありません。

知っておくべきこと

  • 名前付きエンティティと数値エンティティは同じ文字を異なる形で表します。 &apos;(名前付き)と&#39;(数値)はどちらも単一引用符を意味しますが、名前付きエンティティはパーサーがその特定の名前を認識できるかどうかに依存します。数値エンティティ(10進数、または&#xによる16進数)はどの環境でも普遍的にサポートされ、機械的に生成される出力にはより安全な選択です。
  • エンコードだけが唯一の防御ではありません。 エンコードが守るのはテキストコンテンツです。属性値、URL、インラインJavaScriptの文脈にはそれぞれ固有のエスケープ規則が必要です。href="javascript:..."の中の値や<script>ブロックの中身は、通常の本文テキストとは異なる規則で解析されるためです。
  • 変換はローカルで行われます。 このツールはブラウザ自身のDOMパーサーを使用しており、何もアップロードやログ記録はされません。
  • すべてのサーバーサイドのテンプレート言語が自動エスケープを行うわけではありません。 一部の言語(古いPHPの出力や生の文字列連結など)では、エスケープ関数を明示的に呼び出す必要があります。これを忘れることが、実際のXSSバグの最も一般的な原因のひとつです。
  • 一部のエンティティは見た目がほとんど区別できません。 直線の引用符(')とタイポグラフィ上の右シングルクォート(&#8217;)は画面上ではほぼ同じに見えますが、バイト列としては異なります。コードサンプルやURLではこの違いが重要になります。

具体的な例で見てみましょう。Nice post! 5 < 10, right?というコメント欄の内容は、プレーンテキストとして扱う分には特別な処理を必要としませんが、これがエスケープされないままHTMLテンプレートに挿入されると、悪意ある訪問者は代わりに<img src=x onerror=alert(1)>を送信できてしまいます——エンコードはこれを、実行される画像エラーハンドラーではなく、無害で目に見えるテキストに変えます。

よくある質問

テキストをHTMLに入れる前になぜエンコードする必要があるのですか?

HTMLコンテンツ内でエスケープされていない<や&はマークアップとして解釈され、ページのレイアウトを崩したり、さらに悪いことに、注入された<script>や<img onerror>タグが実際に実行されてしまう(クロスサイトスクリプティング)可能性があります。&lt;や&amp;にエンコードしておけば、ユーザーが何を入力したかにかかわらず、テキストは文字どおりのまま無害に保たれます。

名前付きエンティティと数値エンティティの両方に対応していますか?

はい——デコードは名前付きエンティティ(&amp;copy;)と数値エンティティの両方を理解します。数値エンティティは10進数(&amp;#169;)でも16進数(&amp;#x00A9;)でも構いません。この3つはすべて同じ©という文字を表しており、このツールはそのいずれからでも実際のグリフへと正規化します。

数値エンティティと名前付きエンティティ、どちらを使うべきですか?

名前付きエンティティ(&amp;apos;、&amp;hellip;)はソースコード上で読みやすい一方、パーサーがその正確な名前を認識できるかどうかに依存しており、あまり一般的でないものの中には古いツールでのサポートが一貫していないものもあります。数値エンティティ(&amp;#39;、&amp;#8230;)は、年代やベンダーを問わずすべてのHTMLパーサーで普遍的に理解されるため、自動化ツールやサニタイズ用のライブラリではしばしば数値エンティティが好まれます。

エンコードするだけでページはXSSから完全に安全になりますか?

エンコードが処理するのはテキストノードだけです。HTMLには他にも注入の文脈があります——属性値の中、URLの中、<script>や<style>ブロックの中——それぞれに固有のエスケープの考え方が必要です。ブラウザのパーサーは文書内のどこにいるかによって適用する規則を切り替えるためです。テキストコンテンツをエンティティでエンコードすることは重要な防御層の一つであり、防御のすべてではありません。タグ全体を取り除いたり書き換えたりする、より広範な「サニタイズ」処理は、限定的なHTMLを意図的に許可したい場合に使う、これとは別のより踏み込んだツールです。

入力したテキストはどこかに送信されますか?

いいえ——変換はDOM自身のパーサーを使ってブラウザ内で即座に行われます。何もアップロードされず、ログにも記録されず、保存もされません。そのため、インジェクションの試みが含まれているのではと疑われるものも含め、実際にユーザーが投稿したコンテンツをテストする際にも安全に使用できます。

コメント

まだコメントはありません — 最初のコメントを書いてみましょう!

関連ツール