限られた相手にのみWebサイトを公開するには、いくつかの認証方式があり、ユーザIDとパスワードによる認証がよく使われていますが、これらの認証方式にはいくつかの問題があり、安全とはいえません。

ユーザIDとパスワードによる認証方式の特徴

 ・ベーシック認証 (Basic Authentication)

 ユーザIDとパスワードは暗号化されず平文(ひらぶん)でネットワーク上を流れるため、通信経路上のパケットを悪意のある第三者が盗聴すれば、暗号化されていないユーザIDやパスワードを使い、ユーザになりすますことが簡単にできてしまいます。  

 ・ダイジェスト認証 (Digest Authentication)

 ユーザIDとパスワードおよびサーバが送った乱数を使った認証で、ハッシュ化したパスワードと乱数をさらにハッシュ化したメッセージダイジェストがネットワークを流れるため、パスワードが平文で流れるベーシック認証よりはましになりますが、認証後のデータのやりとりは暗号化されないため、安全性に欠けます。また、古いブラウザでは対応してない場合があります。

 ・フォーム認証 (Form Authentication)

 Webページのフォームに入力されたユーザIDとパスワードを、サーバに送る方式です。ユーザIDとパスワードは暗号化されていません。

 このように、Web上でユーザを認証するには、多くの問題があります。意図した相手と安全に通信する方式としては、SSL/TLSがあります。

SSL/TLSサーバ認証とクライアント認証

 ・SSL/TLSサーバ認証

 SSL/TLSサーバ認証は、ベリサインなどの認証局(CA:Certificate Authority)から発行された「サーバ証明書」をサーバ側で設定し、通信の暗号化とサーバの認証を行い、「盗聴」・「改竄」・「なりすまし」を防止することを目的に、ショッピングサイトなどで広く使われている方式です。

 具体的には、サーバで秘密鍵と公開鍵のキーペアを生成し、その公開鍵を自サイトの情報(ドメイン名等)をサブジェクトとした署名前証明書(CSR)とともに認証局に送ります。認証局は署名前証明書を審査し、OKならば、署名前証明書を認証局の秘密鍵で署名(暗号化)したデータを付加して、サーバ証明書を発行します。サーバ証明書の署名を復号できるのは、キーペアである認証局の公開鍵だけです。公開鍵は認証局の証明書に登録されています。

 「証明書でサーバを認証する」とは?

 たとえば、銀行で口座を開設する際には、本人確認のためにパスポートや運転免許証のような公的機関が発行する身分証明書の提示を求められます。公的機関が発行する証明書は「信頼できる」ので、銀行の担当者は写真を確認し、本人確認を行います。
 それと同じように、SSL/TLSサーバ認証は、そのサイトに接続した際にクライアントがサーバに対して証明書の提示を求めます。IEやFireFoxのようなブラウザには、あらかじめ著名な認証局のルート証明書が組み込まれています。これらの認証局は「信頼できる」と自分が認めているということになります。

 信頼する認証局に登録されたルート証明書は、サーバが提示した証明書の署名を検証し(認証局の公開鍵で復号する)、問題なければ通信を許可します。その後で、クライアントはお互いの暗号に使う共通鍵を、サーバの公開鍵で暗号化してサーバに送ります。サーバはサーバの秘密鍵で復号し、受け取った共通鍵でこれからやりとりするデータの暗号化を行います。また、途中でデータの改ざんがあったとしても、メッセージダイジェストにより検知することが可能です。

 ・SSL/TLSクライアント認証

 サーバ認証に加えて、サーバ側からもクライアントを認証する方法です。クライアント用に証明書を発行し、クライアントは自分のPCの証明書ストアに証明書を保存しておきます。接続の際に、お互いの証明書を交換し合い、自分の信頼する認証局が発行した証明書に問題がなければ接続が許可されます。この方式が最もセキュリティレベルが高い方式です。

クライアント認証を試してみる 

 最もセキュアな方式である「SSL/TLSクライアント認証」を試してみました。おおまかな手順は以下のとおりです。

 1.証明書の準備

・サーバ証明書の署名前証明書を作成し、認証局に申請してサーバ証明書を発行してもらう

・プライベート認証局の構築とクライアント証明書の発行

 2.Webサーバの設定

・ApacheのインストールとSSL/TLSクライアント認証の設定

 3.クライアントPCの設定と接続確認

・証明書ストアにクライアント証明書をインストール

証明書の準備

  • サーバ証明書

テスト用に、ベリサインやコモドジャパンなどが発行する、試用版のサーバ証明書を利用する方法があります。署名前証明書(証明書要求:CSR)をOpenSSL等のコマンドで作成し、Web上で申請してサーバ証明書を発行してもらうことができます。

  • プライベート認証局の構築 

    OpenSSLをインストールすると、「CA.pl」というプライベート認証局を作成するスクリプトが利用できます。

# apt-get install openssl

 (注意1) DSA-1571-1セキュリティ勧告あり。 (バージョン0.9.8c-1以降) 0.9.8c-4etch3で修正済

# vi /etc/ssl/openssl.cnf を編集

(注意2) 自組織のポリシーにに合わせて、openssl.cnfを編集して下さい。

# cd /usr/lib/ssl/misc

プライベート認証局を構築します。

# ./CA.pl -newca

CA秘密鍵のパスフレーズやCA証明書の組織名などを入力すると、/usr/lib/ssl/misc/demoCAディレクトリと、以下のようなファイル・ディレクトリが構築されます。

/usr/lib/ssl/misc/demoCA/careq.pem <- CA証明書要求

/usr/lib/ssl/misc/demoCA/cacert.pem <- CA証明書

/usr/lib/ssl/misc/demoCA/private/cakey.pem <- CA秘密鍵

/usr/lib/ssl/misc/demoCA/newcerts/シリアル番号.pem <- CA証明書と同じもの

他にも、証明書の発行や失効を管理する一覧ファイル 「index.txt」や、証明書失効用のディレクトリ等が作成されます。

認証局がら発行されたサーバ証明書、サーバ秘密鍵と、先ほど作成したクライアント認証用のCA証明書は、Apacheの設定ファイルに記述した場所にコピーしておきます。

# cp サーバ証明書 /etc/apache2/server.crt

# cp サーバ秘密鍵 /etc/apache2/server.key

# cp /usr/lib/ssl/misc/demoCA/cacert.pem  /etc/apache2/ssl.crt/ca-bundle.crt

  • クライアント証明書を発行する
クライアント証明書のRSAキーペアと証明書要求を作成します。

# ./CA.pl -newreq

/usr/lib/ssl/misc/newkey.pem <- クライアント秘密鍵

/usr/lib/ssl/misc/newreq.pem <- クライアント証明書要求(公開鍵を含む)

が作成されました。

プライベート認証局の秘密鍵で署名し、クライアント証明書を発行します。

# ./CA.pl -sign

/usr/lib/ssl/misc/newcert.pem と/usr/lib/ssl/misc/demoCA/newcerts/シリアル番号.pem

が作成されました。

クライアントに配布するため、PKCS#12形式ファイルを作成します。

# openssl pkcs12 -export -in newcert.pem -inkey newkey.pem -out newcert.p12

Enter pass phrase for newkey.pem:
Enter Export Password:
Verifying - Enter Export Password:

秘密鍵のパスフレーズとエクスポート用のパスワードを入力します。クライアントにインポートする際は、ここで指定したエクスポート用パスワードを入力します。

以上でクライアント証明書の発行処理は終わりです。次に、「./CA.pl -newreq」 「./CA.pl -sign」を実行すると、newkey.pem、newreq.pem、newcert.pemは上書きされてしまうので、必要であれば他のディレクトリに退避させて下さい。

Webサーバの設定

Apacheのインストール

# apt-get install apache2

http://localhost にアクセスし 「It Works!」が表示されればデフォルト起動OKです。

default設定ファイルを編集します。

# vi /etc/apache2/sites-available/defaut

NameVirtualHost *  ---> NameVirtualHost *:80 に変更

<VirtualHost *> ---> <VirtualHost *:80> に変更

SSL/TLS用の設定ファイルのサンプルをコピー

# cd /etc/apache2/sites-available

# cp /usr/share/doc/apache2.2-common/examples/apache2/extra/httpd-ssl.conf.gz

# gunzip httpd-ssl.conf.gz

# mv httpd-ssl.conf ssl

SSL/TLSl用設定ファイルを編集します。

# vi /etc/apache2/sites-available/ssl

#ServerName www.example.com:443
ServerName localhost:443

SSLCertificateFile /etc/apache2/server.crt <--- サーバ証明書

SSLCertificateKeyFile /etc/apache2/server.key <--- サーバ秘密鍵

SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt <--- クライアント認証用のCA証明書
SSLVerifyClient require <--- クライアント認証を有効にする
SSLVerifyDepth 1 <--- 最上位CAまでの数
SSL/TLSクライアント認証を有効にしてApacheを再起動

# a2enmod ssl

# a2ensite ssl
# /etc/init.d/apache2 restart

クライアントPCの設定と接続確認

クライアントのPCに、CAから発行されPKCS#12形式ファイルをインポートします。Windowsの場合は、ダブルクリックすると証明書のインポートウィザードが起動するので、画面の指示に従い、証明書ストアに登録します。

Netscape Navigatorの場合は、「編集」から「設定」を開き、「プライバシーとセキュリティ」の「証明書」を選択し、証明書マネージャで登録します。

Firefoxの場合は、「ツール」 → 「オプション」 → 「詳細」 → 「暗号化」 → 「証明書を表示」の証明書マネージャで登録します。

クライアントから「https://~」でサーバに接続すると、クライアント証明書を選択する画面が表示されるので、接続する証明書を選択して「OK」を押下します。

SSL/TLSクライアント認証で接続成功!アドレスバーの右にある鍵のマークはデータの暗号化を示しています。ダブルクリックすると、サーバ証明書が表示されます。

クライアント証明書をインストールしていない場合や、サーバの指定した証明書を持っていない場合は何も表示されません。

「OK」を押下しますが、サーバに接続することはできません。

証明書が失効している場合も接続することはできません。

まとめ

ユーザIDとパスワードによる認証は、様々な脅威が存在します。

 ・暗号化されていないパスワードの盗聴

 ・よく使われるパスワードを集めた辞書を使った攻撃 (辞書攻撃 dictionary attack)

 ・パスワードとして考えられるすべての可能性を試す攻撃 (総当り攻撃 brute force attack)

 ・キーボードからの入力値を記録するソフトをインストールされる (キーロガー key logger)

 ・パスワードの入力をのぞき見される (ショルダーハッキング shoulder hacking)

このような攻撃をしかけて、悪意のある第三者がパスワードを入手した場合、簡単に身元を偽るこができてしまいます。パスワードを守るためには、他人に容易に推測できないように、パスワードの長さ、文字種類に気を使い、定期的に変更することが求められます。

複雑なパスワードは覚えづらく、管理の煩わしさから、同じパスワードをいろいろなサイトに設定したり、ひとつのパスワードを何人かで共有して使うなど、よくあることだと思います。これではセキュリティを下げてしまい、内部統制もできません。

しかし、SSL/TLSクライアント認証は、クライアントPCに証明書を設定するだけで、クライアントとサーバでお互いの正当性を確認しあい、なりすまし、盗聴、改ざんといった脅威から重要な通信データを守ることができます。

クライアントは、秘密鍵を暗号化し、本人以外がPCにアクセスできないようにすることに注意すればよいのです。

さらに、セキュリティを高める方法として、インターネットバンキングなどで使用されている「ハードウェアトークン」を使用する方法があります。PC上で秘密鍵を管理するソフトウェア・トークン(証明書ストアや証明書マネージャ)と違い、秘密鍵をもっと厳重に管理することができます。次回、ハードウェア・トークンを使用したレポートをまとめてみたいと思います。