クロスサイトスクリプティング (XSS) 対策
html/templateにおけるXSS
HttpOnly属性:HTML出力時の適切なエスケープ処理とサニタイズ(エスケープ)文字コードの指定必要性。
1.XSSとは?(超シンプルな概念)
ユーザーが悪意のあるJavaScriptコードをHTMLページに挿入しようとすると、ブラウザがそれをページの正規のコンテンツと誤認して実行してしまうのがXSS攻撃です。
-
ユーザー(攻撃者)が悪意のあるコードを入力
悪意のあるユーザーが、ウェブサイトの入力フォームなどに、JavaScriptコードを含むテキストを送信します。 -
ウェブサーバーが適切に処理せずHTMLに埋め込み
脆弱性のあるウェブサーバーは、この悪意のある入力をエスケープ(無害化)せずに、そのままHTMLコンテンツとして出力してしまいます。
XSSの主要な種類
| 種類 | 発生源 | 対策の責任 |
|---|---|---|
| リフレクトXSS | URLパラメータやフォーム入力など、外部からの入力をすぐさまページに表示するとき | サーバーサイド(Go)での適切なエスケープ処理 |
| ストアドXSS | データベースなどに保存された悪意あるスクリプトを後で表示するとき | サーバーサイド(Go)での適切なエスケープ処理 |
| DOM-based XSS | クライアントサイドのJavaScript内で、安全でないAPI(例: innerHTML)を使ってDOMを操作するとき | フロントエンド(JavaScript)でのサニタイズ処理 |
2. Goでの対策:html/templateの自動エスケープ
Go言語におけるXSS対策の核は、標準ライブラリの html/template パッケージを正しく使用することです。
このパッケージは、データが挿入されるHTMLのコンテキスト(場所)を判断し、自動で適切なエスケープ処理を施します。
適切に使えば、リフレクトXSSとストアドXSSは自動で防御可能です。
覚えるべきルール(3つ)
- HTMLは必ず html/template で出力
- JSの中やHTML属性の中は専用関数を使う
- ユーザーが入力したものは絶対に template.HTML 型にキャストするな
テンプレートコード例と専用パイプライン
html/templateでは、通常のHTML要素の中({{.Comment}})は自動でエスケープされますが、JavaScriptやURLの中は特殊な処理が必要です。
// テンプレート(これが最重要!)
const tmplStr = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>安全なページ</title>
</head>
<body>
<h1>こんにちは {{.Name}} さん!</h1>
<p>コメント:{{.Comment}}</p>
<script>
var user = {{.UserJSON | js}}; // JSの中は必ず | js <script>タグ内でJavaScriptの変数として出力
location = "{{.NextURL | url}}"; // URLは必ず | url URL全体やクエリパラメータとして出力
</script>
</body>
</html>
🍪 3. HttpOnly属性による多層防御
XSS攻撃の多くは、ユーザーのセッションクッキーを盗み出し、セッションハイジャックを行うことを目的としています。HttpOnly 属性は、このクッキー窃盗を防ぐための重要な対策。
クッキー設定例は、別記事にて解説します。
XSS対策のチェックリスト
| 対策の種類 | 項目 | Goコードでの対応 |
|---|---|---|
| 自動エスケープ | HTMLの出力はすべてhtml/template経由か? | template.ParseFiles / template.Execute の使用。 |
| コンテキスト対策 | JSやURLなど特殊な場所は専用パイプラインを使用しているか? | ` |
| サニタイズ | ユーザー入力値に対して絶対に template.HTML 型のキャストをしていないか? | キャスト禁止、Go側で手動でエスケープしない |
| セッション制御 | セッションクッキーにHttpOnly: trueを設定しているか? | http.SetCookie で設定 |
