コンテンツにスキップ
GLANZ. CREATIVE WORKS / GLOBE TAILS
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

セキュリティ

HTTPS とセキュリティヘッダー、CSP、公開ディレクトリに置かないファイル、XSS を防ぐ DOM 操作、フォームの入力検証とスパム対策

Web サイトの制作で必要になる、基本的なセキュリティ対策をまとめています。 外部ライブラリの選び方と CDN から読み込むときの SRI はライブラリの利用、機密情報の管理は GitHub 権限・セキュリティを参照してください。

HTTPS

すべてのページを HTTPS で配信し、HTTP へのアクセスは HTTPS へ 301 リダイレクトします。 ページ内で読み込む画像・スクリプト・フォームの送信先も、すべて https:// にします。HTTPS のページから HTTP のリソースを読み込むと、ブラウザがブロックするか警告を表示します(混在コンテンツ)。

セキュリティヘッダー

サーバーやホスティングサービスの設定で、次のレスポンスヘッダーを付けます。

ヘッダー 値の例 防ぐもの
Strict-Transport-Security max-age=31536000 HTTP での接続。一度アクセスしたブラウザは、以後 HTTPS でしか接続しない
X-Content-Type-Options nosniff ブラウザがファイルの種類を推測し、画像などをスクリプトとして実行すること
Content-Security-Policy frame-ancestors 'self' 他のサイトの iframe にページを埋め込み、ボタンを押させる攻撃(クリックジャッキング)
Referrer-Policy strict-origin-when-cross-origin 外部サイトへの遷移時に、ページの URL(パスやクエリ)が送られること
Permissions-Policy camera=(), microphone=(), geolocation=() サイトで使わないブラウザの機能を、埋め込んだ外部スクリプトが使うこと

設定例

Cloudflare Pages では、ビルド成果物に _headers ファイルを置きます。

/*
  Strict-Transport-Security: max-age=31536000
  X-Content-Type-Options: nosniff
  Content-Security-Policy: frame-ancestors 'self'
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()

Apache のレンタルサーバーでは、.htaccess に記述します。

<IfModule mod_headers.c>
  Header always set Strict-Transport-Security "max-age=31536000"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Content-Security-Policy "frame-ancestors 'self'"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>

CSP(Content Security Policy)

CSP は、ページが読み込めるスクリプトや画像の読み込み元を制限し、XSS の被害を抑える仕組みです。 ただし、計測タグや埋め込みなど外部のスクリプトを多く使うサイトでは、許可する読み込み元の管理が難しくなります。案件の状況に応じて、次の段階で導入してください。

  1. 最低限: 上記の frame-ancestors 'self' に加え、object-src 'none' と base-uri 'self' を指定する。サイトの動作にほぼ影響しない
  2. 読み込み元の制限: script-src などで読み込み元を列挙する。まず Content-Security-Policy-Report-Only ヘッダーで違反をブラウザの Console に出すだけにして、必要な読み込み元を洗い出してから Content-Security-Policy に切り替える
Content-Security-Policy: frame-ancestors 'self'; object-src 'none'; base-uri 'self'

公開ディレクトリに置かないファイル

次のファイルは、サーバーの公開ディレクトリにアップロードしないでください。URL を推測されると、誰でもダウンロードできます。

  • .env などの環境変数ファイル
  • .git ディレクトリ
  • データベースのバックアップ(.sql など)
  • ビルド前のソースファイルや、作業用のファイル(.psd、.fig の書き出し元など)

デプロイをビルド成果物だけに限定すると、これらのファイルが混ざるのを防げます。

また、Vite では VITE_ で始まる環境変数がビルド後の JavaScript に埋め込まれ、誰でも読める状態になります。API キーなどの秘密の値には VITE_ を付けないでください。

DOM 操作での XSS 対策

ユーザーの入力や URL のパラメータ、外部の API から受け取った文字列を、HTML として解釈させないでください。

// ❌ 文字列に含まれるタグやスクリプトが実行される
message.innerHTML = params.get("name");

// ✅ 文字列をそのままテキストとして表示する
message.textContent = params.get("name");

innerHTML・outerHTML・insertAdjacentHTML() に渡してよいのは、コードに直接書いた固定の文字列だけです。 外部から受け取った URL を href や src に設定する場合は、javascript: などのスキームが使われていないことを確認してください。

const url = new URL(input, location.href);
if (url.protocol === "https:" || url.protocol === "http:") {
  link.href = url.href;
}

フォーム

  • 入力検証はサーバー側で行う: HTML の required や JavaScript での検証は、入力を助けるためのものです。ブラウザを通さずに送信することもできるため、サーバー側でも必ず検証してください。
  • スパム対策をする: Cloudflare Turnstile や reCAPTCHA などのボット対策を入れます。
  • CSRF 対策をする: CMS やフレームワークが用意しているトークンの仕組み(WordPress の nonce など)を使います。
  • メール送信は実績のある仕組みを使う: 自作の mail() 関数の呼び出しは、ヘッダーインジェクションなどの脆弱性を作りやすいため避け、CMS のフォームプラグインやフォーム送信サービスを使います。
  • 個人情報を扱うフォーム: プライバシーポリシーへのリンクを送信ボタンの近くに置きます。

参考リソース

このページは役に立ちましたか?