innerHTMLによるXSSと防止方法
クロスサイトスクリプティングとinnerHTMLの安全な代替手段を理解します
「innerHTMLによるXSSと防止方法」はCoddyKit上の無料HTML Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはHTML Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 HTML Academyコースには全4レッスンが含まれています。
根本的な脆弱性
el.innerHTML = userInputは、文字列をHTMLとして解析します。userInputに<script>タグやイベントハンドラー属性(onclick、onerror)が含まれていると、ブラウザーはそれらを解釈し、攻撃者が制御するコードをページ上で実行します。
なぜよく起こるのか
HTMLにユーザーデータを埋め込むコード、つまりサーバーテンプレートやクライアントサイドレンダリングでは、データがエスケープされていないとXSSの危険があります。APIレスポンスからinnerHTMLを構築するシングルページアプリケーションは、レスポンスにユーザーコンテンツが含まれる場合、特に危険にさらされます。
具体例
ユーザー名"Bob<img src=x onerror=alert(1)>"をdiv.innerHTML = `Welcome, ${user}`で設定すると、imgの読み込みに失敗したときにalert(1)が実行されます。同じペイロードをtextContentでプレーンテキストとして設定すれば無害です。ブラウザーにはタグではなく文字だけが見えるためです。
// VULNERABLE
div.innerHTML = `Hi, ${user.name}`;
// SAFE
div.textContent = `Hi, ${user.name}`;プレーンテキストにはtextContentを使用する
textContentはテキストだけを設定するため、HTMLの特殊文字はタグではなくリテラル文字として表示されます。これはほとんどの場合に適した方法です。実際にマークアップを表示する必要がある場合にだけinnerHTMLへ切り替え、テキストの表示には使用しないでください。
構造にはDOMメソッドを使用する
ユーザーデータを含む要素を作成するには、createElementとtextContentを使って構築します:const li = document.createElement("li"); li.textContent = name; ul.appendChild(li);。結果の構造はinnerHTMLと同じですが、最初からXSSに安全です。
innerHTMLを使う必要がある場合
サーバーで生成された信頼できるHTML(独自のテンプレート出力や、信頼できるエディターでサニタイズされたリッチテキスト)であれば、innerHTMLを使用しても問題ありません。信頼できないソースのデータには、サニタイズせず直接適用しないでください。
DOMPurifyでリッチテキストをサニタイズする
ユーザーがリッチテキスト(コメントエディターの入力やMarkdownのレンダリング結果など)を送信する場合は、innerHTMLに設定する前にサニタイズします:el.innerHTML = DOMPurify.sanitize(richHtml)。DOMPurifyは危険なタグや属性を除去しつつ、<b>、<em>、<a>のような安全な書式は保持します。
insertAdjacentHTMLにも同じ危険がある
el.insertAdjacentHTML("beforeend", html)はHTML文字列を解析するため、innerHTMLと同じXSS攻撃面を持ちます。同じルールが適用されます。ユーザーデータを直接渡さず、サニタイズするかDOMメソッドを使用してください。document.writeも同様ですが、これはもう誰も使うべきではありません。
フレームワークのデフォルト動作
React、Vue、Svelte、Angularは、補間されたテキストをデフォルトでエスケープします。{name}は安全です。これらのフレームワークにはエスケープを回避する機能(ReactのdangerouslySetInnerHTMLやVueのv-html)がありますが、同じXSSの危険を伴います。サニタイズと併用し、慎重に使用してください。
属性への注入
属性値でさえ攻撃経路になることがあります。<a href={url}>で、url="javascript:alert(1)"の場合、クリック時に実行されます。ユーザー入力をhref、srcなどのURLを受け取る属性に設定する前に、URLのスキームを1つずつ検証し、http:、https:、mailto:、tel:だけを許可してください。
Trusted Typesポリシー
モダンブラウザーはTrusted Typesをサポートしています。CSPでrequire-trusted-types-for 'script'を設定すると、innerHTMLは生の文字列を拒否し、ポリシーでラップされた値だけを受け入れるようになります。これにより、開発者の注意力ではなくAPIによってXSSを防止できます。
多層防御
単一のレイヤーだけでは十分ではありません。サーバーでの入力検証、レンダリング時の出力エスケープ、注入されたスクリプトをブロックする CSP、生の文字列を拒否する Trusted Types、そして innerHTML の使用箇所に対するセキュリティレビューを組み合わせてください。多層防御により、いずれか 1 つのレイヤーにバグがあっても耐えられます。
理解度チェック
なぜ el.textContent = userInput は XSS に対して安全なのに、el.innerHTML = userInput は危険なのですか?
まとめ
ユーザー入力に対する innerHTML は、典型的な XSS の攻撃経路です。テキストには textContent を使い、構造の生成には createElement と textContent を使い、リッチ HTML が必要な場合は DOMPurify を使ってください。属性値の URL スキームを検証してください。CSP と Trusted Types を重ねて、コードレビューをすり抜けたバグを無力化してください。最新のフレームワークはデフォルトでエスケープしますが、安全でないエスケープハッチはできるだけ少なくし、レビューしてください。
AI チューターと学ぶ HTML — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 40
- レッスン
- 159
よくある質問
「innerHTMLによるXSSと防止方法」レッスンは無料ですか?
はい。「innerHTMLによるXSSと防止方法」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、HTML Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 HTML Academyコースには全4レッスンが含まれています。
「innerHTMLによるXSSと防止方法」で何を学びますか?
クロスサイトスクリプティングとinnerHTMLの安全な代替手段を理解します ブラウザで直接実行するハンズオンコードでHTML Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
HTML Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのHTML Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「innerHTMLによるXSSと防止方法」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このHTML Academyレッスンでコードを書いて実行できますか?
はい。すべてのHTML Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Content Security Policyのmeta http-equiv
- innerHTMLによるXSSと防止方法
- iframeのサンドボックスとPermissions Policy
- HTTPSとSubresource Integrity