みどりのさるのエンジニア

WebセキュリティのためのHTTPレスポンスヘッダー

2020年04月08日

フロントエンド実装においてセキュリティを考慮する際に意識した方が良いHTTPレスポンスヘッダーについてまとめています。

X-Powered-By

ヘッダーの説明

サーバー側で利用しているフレームワークやバージョン情報を含むHTTPヘッダー

例: 
X-Powered-By: Next.js

脆弱性

サーバー側で利用されているフレームワークやバージョンが含まれているため、他に脆弱性が存在した場合に攻撃者に攻撃を助ける情報を与える可能性がある。

対策方法

サーバー側で X-Powered-By ヘッダーを出力しないように設定する。

X-Runtime

ヘッダーの説明

サーバーの応答時間を含むHTTPヘッダー

例: 
X-Runtime: 0.094235

脆弱性

タイミング攻撃(Timing Atacking)に利用される可能性がある。

タイミング攻撃

サーバーの応答時間の違いを利用する事でサービスを分析する攻撃手法です。
例えば、次のようにログイン処理が実装されていたとします。

const login = (user_name, password) => {
    const user = User.get(user_name);
    if (user == null) return res.send(400);

    // 登録済みのユーザー名の場合はパスワードチェク処理が実行される分だけ応答時間が長くなる
    const mached = user.matchPassword(password);
    if (matched) res.send(200);
    else res.send(400);
}

この時、ユーザー名がサービスに登録済みの場合はパスワードチェック処理が追加で実行される影響で応答時間が少し長くなるため、攻撃者はランダムなユーザー名でリクエストを送信して X-Runtime の応答時間の違いを比較することで、サービスに登録済みのユーザー名を特定する事ができます。

# 未登録のユーザー名の場合
X-Runtime: 0.3949

# 登録済みのユーザー名の場合
X-Runtime: 0.6421

参考: X-Runtime Header Timing Attacks - Virtue Security

対策方法

X-Runtime ヘッダーを出力しないように設定する。

Cache-Control

ヘッダーの説明

キャッシュの生存期間や保存可否などを制御するHTTPヘッダー
HTTPレスポンスヘッダーとして指定された場合は、サーバーからのレスポンスを Cache-Control の指定に基づいて制御する。

例 画像などを1日キャッシュする
Chach-Control: max-age=86400

脆弱性

ブラウザは何の指定も無い場合はデフォルトでサーバーレスポンスを可能な場合にキャッシュします。
この時サーバーレスポンスにユーザーのパスワード情報などが含まれていた場合に、何らの方法で攻撃者がユーザーの物理マシンにアクセス可能な状態であれば、マシンに保存されているブラウザキャッシュなどからパスワード情報を盗み出される可能性がある。

対策方法

Cache-Control を指定して、扱う情報に応じた適切なキャッシュ制御を行う。
例えば、ユーザーの端末に保存するべきでない情報を含む場合は nostore を指定してキャッシュを保存しないようにする。

Cache-Control: nostore

X-Frame-Options

ヘッダーの説明

X-Frame-Options - HTTP | MDN

ブラウザが自分のWebページを <iframe> や <object> の中へ表示することを禁止することで、Webページが他のサイトに埋め込まれないことを保証することができます。

脆弱性の説明

適切に設定していない場合にクリックジャッキング攻撃に利用される可能性がある。

クリックジャッキング攻撃

外部ページを埋め込んだiframeを透明化して通常のWebページの上に被せることで、攻撃者がユーザーに意図しない操作をさせる攻撃手法です。

例えば、次の要件を満たすようなサービスをユーザーが利用しているとします。

1. ログイン情報をCookieで管理している
2. same-site属性はnone
3. アカウント画面の削除ボタンを押すだけで確認なしでアカウントが削除できる

このとき対象サービスのアカウントページをiframeに埋め込み透明化した状態でWebページの上に重ねた場合、ユーザーがログイン済みであればユーザーのアカウントページが透明な状態で上に重なって表示されます。
対象サービスの削除ボタンに重なる位置にクリックしたくなるようなリンクを配置することで、ユーザーに削除ボタンをクリックさせて、アカウントを削除するように誘導する事ができます。

対策方法

X-Frame-Options: Deny を指定する事で iframe 等へのページの埋め込みを禁止する。

Content-Security-Policy(CSP)

ヘッダーの説明

コンテンツセキュリティポリシー (CSP) - HTTP | MDN

インラインスクリプトの実行を禁止してXSSなどの攻撃を軽減する事ができます。

例えば、次のようにHTTPレスポンスヘッダーに含める事で、掲示板のサービスなどでサニタイズ処理をせず任意の文字列をサービスに埋め込める脆弱性があった場合でも、インラインスクリプトの実行ができないためXSS攻撃を軽減する事ができます。

# 外部ドメインのファイル読み込みやインラインスクリプトの実行を禁止する
Content-Security-Policy: default-src 'self'

IEは CSPの sandbox ディレクティブのみが利用可能になっており、IE9以下は CSP 未対応なので、次に紹介する X-XSS-Protection を利用する必要があります。

詳しい設定は上記のMDNのリンクを参照してください。

脆弱性の説明

掲示板などでユーザーが入力した値をサニタイズせずに画面上に表示していた場合にXSS攻撃を仕込まれる可能性がある。

注意点

外部ドメインからのスクリプト読み込みを禁止した場合に、CDN経由でのライブラリ読み込みなどが出来なくなってしまいます。
そのため、自身のサービスの特性に合わせて適切に設定する必要があります。

例えば、次の設定をする事で自身のドメインと特定ドメインの CDN からのみスクリプト読み込みを許可する事ができます。

Content-Security-Policy: default-src 'self' cdnjs.cloudflare.com

対策方法

Content-Security-Policyを適切に設定する。

※ CSPの設定とは別でユーザーが入力した値を表示する箇所で適切にサニタイズ処理はするべきです。

X-XSS-Protection

ヘッダーの説明

ブラウザがXSS攻撃を検出した時にページの読み込みを自動で停止します。

CSPが厳しく設定済みであれば、このヘッダーは本来不要です。
しかし、ユーザーがCSPに未対応の古いブラウザ(IE9以下)を利用している場合に有効な対策になります。

Strict-Transport-Security

ヘッダーの説明

Strict-Transport-Security - HTTP | MDN

HTTPS でページにアクセスした時にHTTPレスポンスヘッダーに含めることで、次回以降はブラウザーに HTTP の代わりに HTTPS を用いて通信を行うよう指示する事ができます。

初めてのユーザーが HTTP でページにアクセスした場合は Strict-Transport-Security 無視されるため、ユーザーが HTTPS アクセスを一度もしていない場合には有効でない事に注意してください。
HTTPS アクセスをしてSSL証明書が確認されたタイミングで設定が有効になります。

# HTTPSアクセスの設定を1年間有効にする(有効期限はアクセスの度に更新される)
Strict-Transport-Security: max-age=31536000;

脆弱性の説明

HTTPアクセスが許可されている銀行サイトを普段から利用していたとします。
カフェで無料のWifiに接続した状態で、その銀行サイトをHTTP経由で利用をしてしまった場合に、攻撃者にHTTPリクエストの内容を傍受され銀行口座やログイン情報などが盗まれる可能性があります。

対策方法

Strict-Transport-Security ヘッダーを指定する。

上の例では、もし銀行サイトが Security-Transport-Security を設定しており、一度でも HTTPS で銀行サイトにアクセスしていた場合には、誤ってHTTPアクスした場合でも HTTPS 経由で自動で接続されるため被害を防ぐことができます。