今日のWebシステムには、不正アクセス、情報の盗み見、サービス妨害などに対するセキュリティ対策は必須なものになっています。システムとしてのセキュリティ対策は、種々の対策を組み合わせることによって行い、対策の種類も多岐に渡っていますが、ここでは、基本的な(これをやることが常識になっている)Webシステムでのセキュリティ対策を3つ紹介します。

9.1 通信の暗号化(SSLによる暗号化とHTTPS)

SSL/TLS

 インターネット上での通信を暗号化する仕組みで、一般的に使われているのはSSL (Secure Sockets Layer)というものを基にしたものです。現在主流なのはTLS(Transport Layer Security)という元のSSLから進化したものであり、「SSL/TLS」と表記されることがもあります。これらは、公開鍵暗号と共通鍵暗号という暗号化技術の組み合わせで、暗号化された安全な通信を確保するものものです。

SSLの暗号通信の仕組みは以下の通りで、サーバー側に公開鍵を含む「認証局」から発行された「サーバー証明書」が必要になります。

SSLの仕組み

HTTPS

HTTPSは、HTTPプロトコルにSSLを組み込んだものです。。SSL/TLSはセッション層で暗号化をする仕組みであり、HTTPSはこれを使ってアプリケーション層の通信を行います。SSL/TLSが組み込まれたアプリケーション層の通信を行うものは他にも色々あり、SSH、SCPなどがあります。

Webシステムが盗聴されることなく、ユーザーと安全にデータをやり取りするためにHTTPSはスタンダードになっており、必須なものです。WebサーバでHTTPSを扱うためには、「認証局」から「サーバー証明書」を取得し、これをWebサーバーソフトにインストールしてやる必要があります。

9.2. ログインとセッション(認証と認可)

 不特定の人に対してWebサービスを提供する場合は、HTTPSを導入するだけでも良いのですが、メンバーのみとか特定のユーザーのみに対してサービスを提供する場合、これだけでは不足です。ログインしたユーザーのみが特定のサービスを利用できたり、ユーザーごとに異なるデータが使えたりするような仕組みが必要になります。

ログイン

ログインとはアプリケーションなどが、ユーザーから送信された値とデータベースなどに保存された情報を照合して本人確認を行う仕組みです。本人確認を行うことを「認証(Authentication)」と呼びます。ログインするときの方法には、以下のようなものがあります。

  • 一番基本的な「ID/パスワード」で認証する方法
  • これに加え、ワンタイムパスワードや認証アプリのコードなどを要求する他要素認証
  • Google、Facebook、Appleなどのアカウントを使ってログインするOAuth認証

また、ログインしたユーザー(認証済み)に対し、ファイルやページへのアクセス、特定の操作(閲覧・編集・削除など)を行う権限を与えることを「認可(Authorization)」と言います。

セッション

 ログインしたユーザーのみが特定のサービスを利用できたり、ユーザーごとに異なるデータが使えたりするような仕組みとしてよく使われているのが「セッション」です。セッションは「通信の開始から終了までの一連の処理」 をひとまとめにしたもので、例えば、下記のような処理を一つの「セッション」として扱います。

  • Webアプリにおけるログインからログアウトまでの処理
  • ECサイトにおけるカートに商品を入れてから購入するまでの処理

HTTPプロトコルは元々、一回ごとのやり取りが独立した「ステートレス」なプロトコルなので、このままでは一連の処理をまとめて扱うことができません。そこで、セッションIDと呼ばれるサーバーで生成される一意の識別子をHTTPヘッダーのクッキーの中に入れてやり取りする方法でセッションを実現します。

セッションの仕組み

(1)ブラウザからの要求でログイン認証が行われる。

  • 認証に成功するとセッションIDが「一時的に」生成される
  • セッションIDに対応する「セッションファイル」が作成される。
  • セッションファイルにはログインユーザの情報など(例えばユーザー名など)が保存される

(2)サーバーはセッションIDをHTTPヘッダーのクッキーに格納し、ログイン成功の通知をブラウザに返す

(3)ブラウザは受け取ったセッションIDを含むクッキーの内容を保存。

(4)ユーザーが次に同じサイトにアクセスすると、ブラウザは自動的にセッションIDを含むクッキーをサーバーに送信する

(5)サーバーは受け取ったセッションIDを手がかりに、対応するユーザーデータをセッションファイルから取得し、適切なレスポンスを返します。

 例えば、以下のようなことを行います。

  • 受け取ったセッションIDに対応するセッションファイルがあれば、URLの内容を返す、なければ、「アクセス失敗」を返す
  • セッションファイルに情報を書き込む
  • セッションファイルから情報を読み出し、その内容を返す

(6)ログアウト要求を受けたり、あるいは一定時間アクセスがなかった場合にサーバーは記憶していたセッションIDとセッションファイルを削除します。

9.3 CSRF攻撃とその対策

CSRF攻撃とは

 CSRF(クロスサイトリクエストフォージェリ)は、Webサイトにログイン中のユーザーを騙し、意図しない操作(パスワード変更、送金、投稿など)を別のWebサイト上で強制的に実行させる攻撃です。以下のような仕組みで攻撃を行います。


1. ユーザーが銀行サイト等にログイン(セッションが有効な状態)。
  2. セッションが保持された状態で、ユーザーが攻撃者が用意した罠(メールやリンク)にアクセスする。
  3. ユーザーのブラウザから、ログインしているサイトへ不正なリクエストが送られる。
  4. サイトのサーバーはログイン中のユーザーからの正しい操作だと誤認し、要求された処理を実行してしまう。

ブラウザは保存していたcookieの内容を自動的に自分が出すリクエストに付与します。攻撃者が用意した不正なリクエストにもcookieのセッションIDが付与されるため、サーバー側はログイン中のユーザーからのリクエストだとみなしてしまい、処理を実行してしまうのです。

CSRF攻撃への対策

 CSRFは古典的な攻撃手法ですので、大抵のWebフレームワークはこれについての対策機能を備えています。

CSRFの対策ので最もポピュラーなのは、「CSRFトークン」を使う方法です。CSRFトークンはサーバー側で生成された秘密情報で、サーバーはリクエストにこの秘密情報が含まれ、これが自分が生成したものであることを確認することで、リクエストの実行を許可して良いかを判断します。

以下は、DjangoフレームワークにおけるCSRF対策の動作です。

  1. ユーザーがサイトにログインすると、CSRFトークンを自分が持っている秘密キーを基に生成
  2. サーバーはCSRFトークンをcookieのcsrftokenと、X-CSRFTokenというカスタムヘッダーに格納してレスポンスを返す
  3. ユーザー側(ユーザー側のプログラム)は、次にサーバーに処理を要求する際に、カスタムヘッダーX-CSRFTokenにトークンを格納して送信する
  4. サーバーは、cookieに含まれているcsrftokenとヘッダーに含まれているトークンが同一であるかをチェック。さらにトークンが自分で生成したものであるかどうかを秘密キーを使ってチェック。
  5. 両方のチェックが通れば要求内容を実行

攻撃者は、CSRFトークンの値を知ることができないので、不正リクエストのヘッダーにCSRFトークンをセットすることはできません。仮にあてずっぽうな値をセットしても、サーバー側のチェックで失敗します。