日本語

開発者ツール · HTML エンティティ エスケーパー

innerHTML を使用しない HTML エンティティのデコード: ルックアップ テーブル デコーダの仕組み

· 仕組み

html セキュリティ エンコーディング

DOM ノードを作成せずに、エンコードされた HTML 参照を無害なテキストにマッピング
オリジナル ToolAcre ベクトル イラスト

innerHTML に代入してエンティティをデコードする一般的な手法では、入力が HTML パーサーを介して実行されますが、これはまさに望ましくないことです。この投稿では、より安全なテーブルベースのアプローチと、それが名前付き、10 進数、および 16 進数の参照を処理する方法について説明します。

<img onerror> を実行したデコーダー — 「デコードするだけ」がスクリプト実行になった具体的なケース

一般的な 1 行の element.innerHTML = 入力は、&amp; をデコードするだけではありません。入力に ​​<img src=x onerror=...> も含まれている場合、ブラウザは画像要素とイベント ハンドラー属性を作成します。そのノードがどのようにアタッチされロードされるかによっては、書式設定のショートカットがスクリプトの実行に変わる可能性があります。唯一のジョブが文字参照を解決することである場合、貼り付けられた HTML のような文字列は、DOM ツリーに解析されるのではなく、データのままである必要があります。

innerHTML が文字列に対して実際に行うこと — エンティティの置換だけでなく、解析、要素の作成、イベント ハンドラー属性

innerHTML は HTML パーサーを呼び出します。タグはノードになり、属性はブラウザーの意味を取得し、その後の textContent の読み取りによって結果からマークアップが取り除かれます。リテラル入力として保持するつもりだった <strong> タグは、テキスト書式設定として消える可能性があります。分離された要素は一般的な安全性を保証するものではありません。コードは多くの場合、そのサブツリーを再挿入するか、結果の HTML を別の場所で使用します。信頼できない入力を表示する必要がある場合は、HTML のレンダリングを意図的に選択した場合にのみ、textContent を割り当ててサニタイズします。

ルックアップ テーブル アプローチ - &name;、&#NNN; の正規表現&#xHHH;、および名前からキャラクターへのマップ

ToolAcre のデコーダーは、有界正規表現を使用して、&name;、&#123;、または &#x7B; 形式の参照を検索します。名前付き参照は、amp、lt、gt、引用符、一般的なタイポグラフィなどを含む、実用的な明示的なテーブルで検索されます。未知の名前は、推測ではなく書かれたままになります。このアプローチでは要素は作成されず、HTML パーサーも呼び出されません。単に文字列内の認識された部分文字列を置き換えるだけです。このテーブルは意図的にサブセットであり、すべての HTML 名前付き文字参照ではありません。

数値参照の処理 - 10 進数および 16 進数のコード ポイントを解析し、アストラル文字を含む文字列に変換します。

数値参照の場合、&# の後の 10 進数または &#x の後の 16 進数を解析し、数値コード ポイントを String.fromCodePoint を持つ文字に変換します。 0x1F600 などのアストラル値は、2 つの独立した印刷可能な文字ではなく、絵文字を生成します。この実装では、ブラウザと同様に、過去の Windows-1252 制御範囲値もマッピングされます。ゼロ、サロゲート コード ポイント、および U+10FFFF を超える値は置換文字になります。この明示的なエラー処理により、無効な数値によるデコーダのクラッシュが防止されます。

実用的な例: &amp;、&#169;、および &#x1F600; が混在する文字列をデコードします。それぞれの一致はテーブルまたは数値から解決されます。

リテラル入力 &amp;、&#169;、&#x1F600; をデコードします。最初の参照は名前付きテーブルを介して & にマップされ、10 進数の 169 は © になり、16 進数の 1F600 は 😀 になります。それらの横に生の <img onerror="alert(1)"> を含めます。デコーダは、タグのようなシーケンスを通常の文字列文字として返します。イメージの作成やイベントの実行は行いません。後で結果を実際のページに配置する場合は、デコードされた文字列を取得して innerHTML に割り当てるのではなく、安全なテキスト シンクを使用してください。

テーブルアプローチではできないこと — 意図的に実装しない限り、従来のセミコロンのない参照とパーサーのエラー回復の癖

ルックアップのアプローチでは、HTML パーサーの従来のセミコロンのない回復ルールは意図的に再現されません。セミコロンのない &copy はそのまま残される場合があります。修正された名前付きテーブルでは、2,000 を超える HTML5 名前付き参照の多くも省略されています。これらの制限は、予測可能な小さなデコーダにとっては正直なトレードオフです。明示的に終了した参照のみを受け入れることで、アンパサンドを含む任意の散文をマークアップとして扱うことを回避できます。ブラウザーの完全な互換性が不可欠な場合は、ツールの文書化されたサポート名を確認してください。

これでカバーされないこと — レンダリングする予定の HTML のサニタイズ、これは別の問題です

参照のデコードは、表示用の HTML をサニタイズするわけではありません。デコードされたテキストに <script> シーケンスが含まれている場合、後でアプリケーションの別の部分がそれをマークアップとして挿入した場合に危険が残ります。 HTML 属性、JavaScript 文字列、URL などのコンテキストには、それぞれ独自の出力エンコーディングとポリシーが必要です。 ToolAcre はテキストを返します。将来的に危険なシンクを安全にすることはできません。

要点: 入力をデータとして扱う - HTML エンティティ エスケープが HTML パーサーではなくルックアップ テーブルを使用してデコードし、入力がテキストのままになる方法

入力をデータとして扱います。 HTML エンティティ エスケープ機能は、innerHTML トリックではなく、テーブルとコードポイントの算術演算を使用してデコードするため、マークアップに見えるペイロードはツール内で不活性な文字のままになります。 3 つのリファレンスを試してから、デコードされたテキストと、それを次にどのように使用する予定かを調べてください。HTML として再解析すると、安全境界が失われます。