開発者ツール · HTML エンティティ エスケーパー
innerHTML を使用しない HTML エンティティのデコード: ルックアップ テーブル デコーダの仕組み
· 仕組み
html セキュリティ エンコーディング
innerHTML に代入してエンティティをデコードする一般的な手法では、入力が HTML パーサーを介して実行されますが、これはまさに望ましくないことです。この投稿では、より安全なテーブルベースのアプローチと、それが名前付き、10 進数、および 16 進数の参照を処理する方法について説明します。
<img onerror> を実行したデコーダー — 「デコードするだけ」がスクリプト実行になった具体的なケース
一般的な 1 行の element.innerHTML = 入力は、& をデコードするだけではありません。入力に <img src=x onerror=...> も含まれている場合、ブラウザは画像要素とイベント ハンドラー属性を作成します。そのノードがどのようにアタッチされロードされるかによっては、書式設定のショートカットがスクリプトの実行に変わる可能性があります。唯一のジョブが文字参照を解決することである場合、貼り付けられた HTML のような文字列は、DOM ツリーに解析されるのではなく、データのままである必要があります。
innerHTML が文字列に対して実際に行うこと — エンティティの置換だけでなく、解析、要素の作成、イベント ハンドラー属性
innerHTML は HTML パーサーを呼び出します。タグはノードになり、属性はブラウザーの意味を取得し、その後の textContent の読み取りによって結果からマークアップが取り除かれます。リテラル入力として保持するつもりだった <strong> タグは、テキスト書式設定として消える可能性があります。分離された要素は一般的な安全性を保証するものではありません。コードは多くの場合、そのサブツリーを再挿入するか、結果の HTML を別の場所で使用します。信頼できない入力を表示する必要がある場合は、HTML のレンダリングを意図的に選択した場合にのみ、textContent を割り当ててサニタイズします。
ルックアップ テーブル アプローチ - &name;、&#NNN; の正規表現&#xHHH;、および名前からキャラクターへのマップ
ToolAcre のデコーダーは、有界正規表現を使用して、&name;、{、または { 形式の参照を検索します。名前付き参照は、amp、lt、gt、引用符、一般的なタイポグラフィなどを含む、実用的な明示的なテーブルで検索されます。未知の名前は、推測ではなく書かれたままになります。このアプローチでは要素は作成されず、HTML パーサーも呼び出されません。単に文字列内の認識された部分文字列を置き換えるだけです。このテーブルは意図的にサブセットであり、すべての HTML 名前付き文字参照ではありません。
数値参照の処理 - 10 進数および 16 進数のコード ポイントを解析し、アストラル文字を含む文字列に変換します。
数値参照の場合、&# の後の 10 進数または &#x の後の 16 進数を解析し、数値コード ポイントを String.fromCodePoint を持つ文字に変換します。 0x1F600 などのアストラル値は、2 つの独立した印刷可能な文字ではなく、絵文字を生成します。この実装では、ブラウザと同様に、過去の Windows-1252 制御範囲値もマッピングされます。ゼロ、サロゲート コード ポイント、および U+10FFFF を超える値は置換文字になります。この明示的なエラー処理により、無効な数値によるデコーダのクラッシュが防止されます。
実用的な例: &、©、および 😀 が混在する文字列をデコードします。それぞれの一致はテーブルまたは数値から解決されます。
リテラル入力 &、©、😀 をデコードします。最初の参照は名前付きテーブルを介して & にマップされ、10 進数の 169 は © になり、16 進数の 1F600 は 😀 になります。それらの横に生の <img onerror="alert(1)"> を含めます。デコーダは、タグのようなシーケンスを通常の文字列文字として返します。イメージの作成やイベントの実行は行いません。後で結果を実際のページに配置する場合は、デコードされた文字列を取得して innerHTML に割り当てるのではなく、安全なテキスト シンクを使用してください。
テーブルアプローチではできないこと — 意図的に実装しない限り、従来のセミコロンのない参照とパーサーのエラー回復の癖
ルックアップのアプローチでは、HTML パーサーの従来のセミコロンのない回復ルールは意図的に再現されません。セミコロンのない © はそのまま残される場合があります。修正された名前付きテーブルでは、2,000 を超える HTML5 名前付き参照の多くも省略されています。これらの制限は、予測可能な小さなデコーダにとっては正直なトレードオフです。明示的に終了した参照のみを受け入れることで、アンパサンドを含む任意の散文をマークアップとして扱うことを回避できます。ブラウザーの完全な互換性が不可欠な場合は、ツールの文書化されたサポート名を確認してください。
これでカバーされないこと — レンダリングする予定の HTML のサニタイズ、これは別の問題です
参照のデコードは、表示用の HTML をサニタイズするわけではありません。デコードされたテキストに <script> シーケンスが含まれている場合、後でアプリケーションの別の部分がそれをマークアップとして挿入した場合に危険が残ります。 HTML 属性、JavaScript 文字列、URL などのコンテキストには、それぞれ独自の出力エンコーディングとポリシーが必要です。 ToolAcre はテキストを返します。将来的に危険なシンクを安全にすることはできません。
要点: 入力をデータとして扱う - HTML エンティティ エスケープが HTML パーサーではなくルックアップ テーブルを使用してデコードし、入力がテキストのままになる方法
入力をデータとして扱います。 HTML エンティティ エスケープ機能は、innerHTML トリックではなく、テーブルとコードポイントの算術演算を使用してデコードするため、マークアップに見えるペイロードはツール内で不活性な文字のままになります。 3 つのリファレンスを試してから、デコードされたテキストと、それを次にどのように使用する予定かを調べてください。HTML として再解析すると、安全境界が失われます。