自己署名した電子証明書とは

通常の電子証明書には、それを発行した認証機関(Certificate Authority)
の証明書に含まれる公開鍵によって電子的に署名が付与されています。
自己署名した電子証明書とは、証明書の発行元と発行先が同一であり、
発行しようとしている証明書の公開鍵をつかって電子署名を付与しているものです。

通常、ルート認証機関が自身の証明書(CA証明書)として発行したものが
自己署名証明書です。自己署名したサーバ証明書やクライアント証明書も
作成可能ですが、多くのPKIアプリケーションではそのような証明書を
受け付けない場合も多いのでここでは扱いません。


ここでは、「自己署名した証明書を使う」のではなく「独自に作成したCAによって
署名されたサーバ証明書を使う」ための説明をします。

なお、簡単に自己発行のサーバ証明書を作るツールがあります。

a) Kousec Server Software Manager - Basic Edition

ウェブ: http://www.kousec.com/prod_cm_ja.html
サーバー証明書の自己発行だけではなく商用CAの証明書の管理・監視なども
できるものです。こちらは日本語化もされています。


b) gencert.exe ユーティリティ

コマンドラインプログラムです。(Orenosp Secure Reverse Proxyにも
付属しています)

ウェブ: http://www.orenosv.com/gencert/gencert_en.html


本文書で使う用語
プライベートCA:独自に作成したRoot CA
自己発行証明書:プライベートCAによって発行されたサーバ証明書


手順としては以下のようになります。

自らroot CAを立ち上げる。
  -> root CAの秘密鍵とroot CAの証明書を作る。この証明書が
     root CAの秘密鍵で署名(自己署名)されている。
そのroot CAがSSLサーバ用の証明書を生成する。
  -> サーバの秘密鍵とroot CAよって署名されたサーバ証明書を作る。

つまり2つの証明書が生成されます。ひとつはCAの証明書、
もうひとつがサーバ証明書です。
Webブラウザがサーバ証明書をチェックする際、そのサーバ証明書を
発行しているCAを認識できない場合「信頼されていないCAから発行
されている証明書」と扱われブラウザーが警告を発します。



自己発行した電子証明書を使う場合の脆弱性と対処方法

自己発行した、すなわち信頼されていないroot CAによって署名された
電子証明書を使うとman-in-the-middle(MITM)アタックに対し脆弱になります。
具体的な説明は以降のセクションにあります。

これがどのくらいのセキュリティレベルかを簡単に説明するならば、
現在Unix/Linuxで広く運用されているSSH(Secure Shell)とほぼ同じといえます。


対処方としては独自root CAの証明書、もしくはサーバ証明書自体を
ユーザのブラウザに安全な経路で提供し、ブラウザに証明書を
信頼できるものとしてインストールしてもらいます。
これを行うことにより「信頼されていないroot CAが発行した証明書」という
警告をブラウザが出さないようになります。それでも警告が発せられたら
本当にman-in-the-middleアタックが行われていると認識できます。

2つの方法があります。

- 独自root CAの証明書 をインストール
  IE、Netscape、Operaなどほとんどすべてのブラウザで使える方法です。
  ただしCA証明書の転送およびインストールに結構手間がかかります。
  何らかの方法でCA証明書をユーザのブラウザまで届けインストールします。

  CA証明書の転送は、もっとも安全なものとして以下が考えられます
  o フロッピーによる手渡し
  o 信頼されたCAからの証明書を使った別のSSLサーバからのダウンロード

  一回きりのリスクを伴う方法として以下が考えれます
  o 暗号化していないemailで送る(改竄、MITMのリスクあり)
  o 自サーバへのSSL初回アクセス時に、「信頼していないCAに署名されたサーバ
    証明書」という警告を無視して、root CA証明書をダウンロードしてもらう
    (MITMのリスクあり)
  o 自サーバへの初回アクセス時に、まず非SSLでアクセスしてもらいそこから
    root CA証明書をダウンロードしてもらう(改竄、MITMのリスクあり)

  SSL通信ではサーバの証明書はクライアントに送られますが、
  そのCAの証明書自体は送られませんのでこのような手順が必要になります。

- サーバ証明書をインストール
  Netscape、Mozilla系でのみ使える方法です。Sun Java Pluginでも使用できます。

  SSL通信ではサーバの証明書がクライアントに送られるので
  初めてブラウザがそのサーバにアクセスした際に、その証明書を
  信頼できるサーバ証明書としてインストールしてもらいます。

  証明書のインストールはブラウザによるサーバアクセスの延長で
  行われますのであまり手間がかかりません。
  サーバの証明書は安全ではない経路で送られますのでそこでman-in-the-
  middle攻撃や改竄される可能性もありますが、最初の一回だけそのリスクを
  負うことになります。

  SSH(Secure Shell)と同様の手順であり、手間とリスクのバランスを考えると
  とても便利な方法だと思います。IEで使えないのが残念です。

信頼されていないサーバ証明書を使った場合のman-in-the-middle攻撃

上記対処法を取らずにSSLサーバにコネクトするたびに信頼されていない
証明書を受け入れるようにすると、man-in-the-middle攻撃される可能性が
高まります。例を上げて説明します。

サーバ : 自己発行証明書をつかったHTTP/SSLサーバ。さらにコンテンツには
         HTTPベーシック認証でパスワードをかけている。
クライアント : サーバ/CAの証明書をインストールせず毎回アクセス時に
               信頼できない証明書を受け付けている。
プロキシー : 悪意を持ったプロキシー管理者(攻撃者)がいるとする。
             クライアントからサーバへの経路上にある。


- プロキシー管理者がクライアントからサーバへアクセスをモニターし
  サーバーのIPアドレスを取得する。(SSLなのでIPアドレスしか取得できない)。

- プロキシー管理者がそのIPアドレスを用いてサーバにアクセスを試みる。
  SSLはつながるがHTTPの認証で拒否される。

-  プロキシー管理者が自身のサーバ証明書を作成する。その証明書の
  人間が読む情報には接続先のサーバの証明書と同じものを記述する。
  証明書を偽造できたわけではなく似たような証明書を作ったということ。

- man-in-the-middle攻撃のマウント:
  次にクライアントがサーバにアクセスする時に、プロキシーが自身の
  サーバ証明書をクライアントに送るように設定する。クライアントユーザが
  サーバへのアクセスを開始すると、ブラウザはいつもどおり
  「信頼されていないroot CAが発行した証明書」という警告を出す。
  ブラウザが表示する情報もいつものサーバのものと同じである。
  したがって、ユーザはその証明書を受け付ける。

- SSLのレベルでの接続完了後、サーバを装ったプロキシーはHTTPの認証要求を
  クライアントに送る。ユーザはユーザ名とパスワードを入力し、プロキシー
  管理者はめでたく接続先サーバで使えるユーザ名パスワードを入手する。


上記対処方でブラウザにroot CA証明書もしくはサーバ証明書を
インストールしておくと、ブラウザはもともとの証明書とプロキシー管理者が作成した
証明書を区別できるので、正常時は出していなかった警告を出すようになります。

この説明では想像しやすくするためプロキシーを攻撃者としましたが
実際にはサーバ・クライアント間のパケットを運ぶいかなるネットワーク
デバイスでも同様です。