1. HTML タグの構造 #html-tag
HTML は要素(element)の入れ子で構成されます。各要素は通常、開きタグ・内容・閉じタグの形を取ります。
<p>これは段落です</p> <h1>見出し</h1> <a href="...">リンク</a>
一部の要素(<img>、<br> 等)は閉じタグを持たない「空要素」です。
2. 属性とは #html-attribute
要素には属性を付けて、追加情報を与えられます。属性は 名前="値" の形式で、開きタグ内に書きます。
<a href="https://example.com" target="_blank">クリック</a> <img src="photo.jpg" alt="写真"> <input type="text" name="email" value="user@example.com">
属性値は通常ダブルクォート(または シングルクォート)で囲みます。値の中に同じクォートを含めたい場合はエスケープが必要。
3. DOM(Document Object Model) #dom
ブラウザは HTML を読むと、それをメモリ上で木構造として保持します。これが DOM。JavaScript はこの木構造に対して、要素の追加・削除・属性の変更などができます。
document (ルート)
└── html
├── head
│ └── title
└── body
├── h1
├── p
└── div
JavaScript からは document.getElementById('foo')、document.querySelector('.bar') 等で要素にアクセスできます。
4. script タグと JavaScript の実行 #script-tag
<script> を見つけたら、その中身を「コード」として実行する。
HTML の中に <script>...</script> があると、ブラウザはその中身を JavaScript コードとして実行します。
<script>
alert('こんにちは');
</script>
外部ファイルから読み込むこともできます:
<script src="app.js"></script>
もし攻撃者が「ページの HTML に <script> タグを差し込む」ことができれば、その中身がブラウザで実行されてしまいます。XSS の最も基本的なベクトルは、HTML 出力の中に <script> タグを注入することです。
5. イベントハンドラ属性 #event-handler
<script> 以外でも JavaScript は実行できる。
HTML の要素には onclick、onerror、onmouseover 等のイベントハンドラ属性があり、属性値として書かれた JavaScript が、特定のイベントが発生したときに実行されます。
<button onclick="alert('クリックされました')">押してね</button>
<img src="存在しない.jpg" onerror="alert('読み込み失敗')">
特に <img onerror=...> は重要。意図的に存在しない画像を指定すれば onerror が必ず発火するので、攻撃者は <script> がフィルタされている場面で <img src=x onerror="..."> を使います。
<img src=x onerror="alert(1)"> はブラウザに「x という画像を読みに行け、失敗したら onerror を実行せよ」と指示。x は存在しないので必ず失敗 → 必ず onerror が実行されます。
6. innerHTML — DOM への HTML 挿入 #innerhtml
JavaScript には、文字列を HTML として要素の中に挿入する API があります。代表的なのが innerHTML。
document.getElementById('greeting').innerHTML = '<b>こんにちは</b>';
'<b>こんにちは</b>' という文字列が HTML としてパースされ、太字のテキストになります。
innerHTML にユーザ入力を直接渡すと、その入力が HTML として解釈されます。これは Reflected XSS や DOM-based XSS の典型的な原因です。
// 危険 element.innerHTML = userInput; // 安全(テキストとして扱う) element.textContent = userInput;