innerHTML, innerText 等の違い (HTML タグとして認識されるものとそうでないものの違い)
ふと innerHTML と innerText の違いについて, ブラウザでどのように解釈されるかなどをしっかりと理解していないような気がしたため調べたことの覚え書き.
基礎知識
HTML の要素? (厳密な表現かどうかは不明) には以下のようなプロパティが存在 (リンクは MDN Web Docs の該当ページ)
セキュリティの文脈では主に innerHTML とそれ以外で分けているイメージがあり, ユーザー入力が innerHTML に反映される場合はタグを注入することが可能になるため注意が必要となる.
以下のような場合において innerHTML では alert() 関数が起動する.
hoge.innerText = "<script>alert(1)</script>" # script tag is not enabled hoge.innerHTML = "<script>alert(1)</script>" # script tag is enable
innerText と textContent の違いについて
- innerText と textContent はざっくり ブラウザで表示される コンテンツか ブラウザで表示されないものも含めた すべてのコンテンツかの違いとなる
- innerText と比較して textContent では ブラウザで表示される文字 だけでなく, 表示設定などに使われる部分まで表示される
- 例として,
scriptタグの中身 (JavaScript のコード) やstyleタグの中身 (CSS のコード) は textContent では表示されるが, innerText では表示されない (MDN Web Docs で実験環境が用意されているためいろいろなタグで表示を確かめられる) - 逆に共通点として 中身が HTML として解釈されない ことが挙げられる
innerHTML とその他の取り扱いの違い
- innerHTML と innerText にはブラウザで HTML として解釈されるかどうかという違いがある
- innerText などではユーザー入力を HTML タグとして解釈しないため, "<" のような特殊文字を入力してもソースコード上はエスケープされたもの ("<" など) に変換される
innerHTML とセキュリティについて
- innerHTML は基本的にタグを認識してしまうため, 検証をしないと有害な JavaScript を埋め込まれ XSS 攻撃につながる恐れがある
- 一方で HTML5 の仕様 上
scriptタグは innerHTML に入力されても動作しない仕組みとなっているらしい
"Note: script elements inserted using innerHTML do not execute when they are inserted."
- しかし, PortSwigger の XSS のチートシート でも多く紹介されているようなスクリプトの実行手段は innerHTML に渡すとしっかり動作するため注意が必要