XSSの脅威

サイトカスタマイズをしていたところ、セキュリティの壁に当たったので記録しておく。

チェックボックスを表示

自己紹介ページに「最近のタスク」を示すチェックボックスを作ろうとした時のことだ。Markdown記法でチェックボックスを作成するとビュレットが表示されてしまい、デザインに欠ける。

  • 十分な睡眠と適切な飲酒
  • 読書

そこで、HTMLを直接埋め込むことで改善を試みた。

Markdown で HTML を作動させる

HugoのMarkdownレンダラーである「Goldmark」の安全装置が働いていて、直接HTMLを書き込んでも反映されない。HTMLの使用を許可するには、hugo.toml に以下の設定を追記する。

[markup.goldmark.renderer]
    unsafe = true

なぜ Hugo は HTML を無視するのか?

Hugoはパーサーとして「Goldmark」を採用している。「Goldmark」はMarkdownレンダラーの一種で、標準設定でMarkdown内のHTMLは安全ではないとして除去されるようになっている。これにはXSSという非常に重要な脆弱性を防ぐ意図がある。

XSS(クロスサイトスクリプティング)とは何か

XSSとは、サイトの脆弱性を突いて攻撃者が埋め込んだ悪意あるスクリプトを、閲覧者のブラウザ上で実行させるサイバー攻撃のことだ。もし、不特定多数が記事を投稿できるサイトで HTMLを無効化(サニタイズ) していなかったらどうなるか?悪意のある者が、以下のようなコードを紛れ込ませるかもしれない。

<img src="invalid" onerror="alert(`セッション情報を盗みました: ` + document.cookie);">

このスクリプトは、、、

  1. src="invalid"(存在しない画像パス)を指定することで、わざと読み込みエラーを発生させる。
  2. エラーが起きる、onerror 属性に書かれたJavaScriptが作動する。
  3. この例では alert が出るだけだか、実際は document.cookie(セッション情報など)を攻撃者のサーバーへ送信させるようなコードが書かれることが多い。

総括

今回のケースでは 「自分で自分のサイトにHTMLを書く」 ためリスクはほぼない。これはMarkdown内に直接以下のような外部JSを書いた場合に、その提供元がハッキングされると結果的に悪意のあるコードが実行されてしまうということであり、実質的なリスクはほぼないという意味である。

<script src="https://example.com/widget.js"></script>

不特定多数がコメントを残せるようなサイトであれば、この 「HTMLの無効化」 は絶対に欠かせない防衛ラインとなる。利便性と安全性のトレードオフをどう管理するか、難しい課題だと感じた。