オレオレ証明書を使いたがる人を例を用いて説得する

[TIS Engineer Advent Calendar 2015](http://qiita.com/advent-calendar/2015/tis) 4日目はExcelから予定を変更して証明書のお話です。

はじめに
--------------------
SSLサーバ証明書を用いたHTTPS通信は一般的になってきましたが、社員向けWebサービスなどにおいては自己署名証明書（通称：オレオレ証明書）が使われている例も少ないながら見受けられます。
これらのサーバの中には「暗号化できているから良いじゃないか」と、有料のSSL証明書を買ってもらえない例もあるかもしれません。
この記事ではこういった場合の説得に使える「オレオレ証明書は何故まずいのか」について、まずい例と許容できる例を取り上げつつ説明していきたいと思います。


SSLサーバ証明書の役割について
--------------------
SSLサーバ証明書には3つの役割があります。

1. 暗号化。サーバ側とクライアント側で暗号化／復号化を行うことにより、通信経路上での盗聴・改竄を防ぎます。
2. 通信相手が正しいことの保障。DNS cache poisoningや、MITM(Man in the middle)によるSSL終端など、攻撃者によって通信相手が変更された場合に警告を表示することで、攻撃者による盗聴・改竄を防ぎます。
3. 改竄の検出。サーバ側で証明書を使って署名することで、通信経路上で改竄された場合にもクライアント側で受信した際に改竄を検出することができます。

1番に関してはオレオレ証明書でも可能ですが、問題になるのは2番、3番です。
3番（改竄の検出）が行えないのは、2番（通信相手が正しいことの保障）が出来ないためなので、肝は2番になります。

さて、買ってもらえない理由として言われることのある「暗号化は出来ているから問題ないよ」について、本当に問題ないのか、例を交えて見ていきたいと思います。

オレオレ証明書の問題点
--------------------
オレオレ証明書を用いたサイトに接続するとブラウザで証明書の警告が表示されます。
Firefoxを使っている場合、このような警告ページが表示され、証明書に問題があることが示されますが、例外として証明書を受け入れることでページが表示されます。

![Firefox.png](https://qiita-image-store.s3.amazonaws.com/0/27861/84047e59-5aed-962e-5846-5cff30418f67.png)

この画面は証明書の期限切れ、証明書の更新、使用ブラウザの変更、PCの変更などの理由により、同一人物であっても何度も目にすることがあり、繰り返される警告画面に慣れてしまった人の中には、証明書の中身を見ずに接続している人も多いかと思います。

さて、いつものようにサーバに接続した際、良く見かける警告画面が表示され、安全のために証明書を確認した際に以下の画面のいずれかが表示されたとします。この画面を見てOKを押さないでいられる人が何人いるでしょうか。

![画像1.png](https://qiita-image-store.s3.amazonaws.com/0/27861/234d39cb-c752-bfc0-5943-e2042df35ab0.png)

![画像2.png](https://qiita-image-store.s3.amazonaws.com/0/27861/b78a4eab-c50c-5100-a6d5-03628d9f0682.png)



1枚目の画像は正規の証明書ですが、2枚目の画像は攻撃者が作成した証明書です。（今回はテスト用に証明書を作成）
つまり正解は1枚目が表示された場合は受け入れても良く、2枚目が表示された場合は拒否する必要があるわけですが、発行対象、発行者、シリアル番号、有効期限のどれを見ても同一になっており、これを判断できる人は、ほぼいないと思います。

攻撃者の証明書が表示されたときに受け入れてしまった場合、外見上は何も問題はありません。
サイトはいつも通りに表示されますし、ログインも可能。サイト上の動作も全く問題なく表示・更新することができます。
しかし、裏ではすべての通信が**「暗号化されない状態で」**通信経路上の攻撃者に見えており、ユーザ名、パスワード、ユーザが書き込んだ内容など、全ての通信内容を傍受したり、通信内容を改竄したりすることができます。

また、毎回証明書の確認を求められるのは面倒なため、受け入れた証明書はFirefoxやOSの証明書ストアに追加してしまう人が多数かと思います。
こういった状況下においては、この攻撃は一度成功してしまえば次からはユーザの確認や入力も不要となり、ユーザに気づかれることなく盗聴・改竄を続けることができます。

このように、オレオレ証明書を使った通信は暗号化が行えていたとしても、攻撃者の発行した証明書を受け入れてしまった時点で**暗号化すらも意味がなくなり**、通信経路上での盗聴・改竄が起こるようになります。また、何よりも問題なのは人間の目ではそれを判断することがまず不可能ということです。

**オレオレ証明書を使用しても問題ないのは通信経路上の機器がすべて管理下にあるイントラネットのみで運用されるサーバに限られており、インターネット経由で外部から接続されるサーバに使用してはいけません。**


通信相手が正しいことの保障
--------------------
これらの問題は本来SSLでサポートされているはずの2番（通信相手が正しいことの保障）が無いことに起因しています。

さて、それでは通信相手が正しいことの保障はどうやって行えば良いのでしょうか。
HTTPS通信の場合、サーバ側の証明書が送られてくるため、クライアント側に正しいサーバ証明書が保存されていれば、双方を比較することで正しい相手かどうかを判定することができます。

証明書の画像で示したように、攻撃者は人間が判別しやすい組織名や有効期限は容易に真似ることができますが、サーバの秘密鍵を知らない以上、サーバ証明書に内蔵された公開鍵(Subject's public key)は真似るわけにいきません。
（正確には真似ること自体は可能だが、秘密鍵を知らないため、攻撃者による暗号の解読が不可能になるので意味が無い）

そのため攻撃者は自分の生成した秘密鍵で署名したサーバ証明書を使うわけですが、秘密鍵が異なる以上公開鍵も異なる値となります。実際、二つの証明書を比較すると「証明書のフィンガープリント」が異なる値になっています。
フィンガープリントは公開鍵から求められるため、このような違いが発生し、前述したとおりこれを真似ることはできません。

クライアント側に保存された証明書の公開鍵と、サーバ側から送られた証明書の公開鍵、これが一致すれば正しい相手と通信していることが保障できるわけです。

しかし、この場合サーバ証明書をどのようにして受け渡すかが問題になります。
例えばメールやHTTPのサイトで配布する方法がありますが、これはインストールする証明書自体を安全ではない経路で送信していることになります。前項で示したように、この方法では攻撃者の発行した証明書をインストールしてしまうことがあり、安全ではありません。

比較的安全なやり方の例としては、フロッピー・USBメディアなどの物理媒体を用いて別経路で送付する方法があります。これであれば途中ですり替えられる可能性は低いため、正しいサーバ証明書をクライアントに届けることができます。

しかし、これは手間・費用共にコストがかさみますし、サーバ側で証明書を更新した際にメディアが届くまでの間通信できないなどの問題もあります。


ルート証明書と証明書のチェーン
--------------------
そこで現在一般的に用いられているのがルート証明書を用いた上位局による認証です。

WindowsやMacといったOSには出荷時点で「厳格に審査された信用できる認証局」を記したルート証明書が内蔵されています。これらのルート証明書はHDDやSSD、またはDVDなどのインストールメディアといった物理媒体に書き込まれて配送されるため、フロッピーやUSBメディアなどを使用した受け渡しと同様、安全（とみなせる）経路で配信されており、信用して良い認証局とみなすことができます。

これらの信用できる認証局は下位にあたる中間認証局（中間CA）に対し、署名付きの証明書を発行します。
そしてその中間認証局はまたその下の中間認証局に対し署名付きの証明書を発行し……と、数段（実際には1～2段）を経て、最終的なサーバ証明書を発行します。

例としてGoogleの証明書を見てみると「証明書の階層」としてこの認証の連鎖が表示されています。
![階層.png](https://qiita-image-store.s3.amazonaws.com/0/27861/03f153ce-55f0-73db-488b-ccc2f2661f90.png)

サーバ証明書を検証する際は逆に下から順に辿っていきます。まず、サーバが返したサーバ証明書には発行元の中間CAによる署名が記載されているため、発行元の中間CAを知ることができます。
中間CAの証明書には同様に一つ上位の認証局が記載されており、これを順に上位にたどることによってルート証明書にたどり着くことができます。

ドメイン認証SSL(DV SSL)の場合、サーバ証明書の発行時点でサーバのドメインを保持していることを中間認証局が確認した上で証明書を発行します。（ドメイン名のついたメールアドレスへの到達確認など）
そのため攻撃者が偽って発行することはできず、また、別ドメイン用のサーバ証明書を発行してもらったとしても、ドメイン名（CNフィールド）は証明書の一部のため、書き換えると異なるハッシュとなり、上位局による署名が無効になります。

結果として、正常な証明書を受信した（＝ルート証明局まで辿れた）場合は警告画面も出ずにそのまま繋がりますし、攻撃を受けている（＝攻撃者によって偽装された証明書）なら警告画面が出るのでネットワーク管理者に問い合わせる、というシンプルな対応が可能になります。

これがルート証明局から辿れる中間認証局の効果であり、これがあることによってオレオレ証明書にはできない2番（通信相手が正しいことの保障）と3番（改竄の検出）が出来るようになっています。

オレオレ証明書で攻撃は防げない
--------------------
Botnetの作成などに使用できるShellshockなどの脆弱性と違い、情報の盗聴・改ざん攻撃を受ける可能性は通信路を流れる情報の価値次第となります。社員など限られたユーザ向けのサービスである以上、攻撃を受ける可能性も高くは無いでしょう。

しかし、HTTPではなく（オレオレ証明書を使った）HTTPSで通信をしているのは何故でしょうか？それは可能性が低いとはいえ、経路上での盗聴や改竄といった攻撃が想定され、その際の甚大な被害を防止するためかと思います。

それであれば、オレオレ証明書を使ったHTTPS通信では意味がありません。
攻撃対象になっていないのであれば平文のHTTPでも問題なく、逆に攻撃対象になっているのであればMITM攻撃は当然想定されるものです。

**そしてサイトを使用する全ユーザが正規の証明書と攻撃者の証明書を見分けられるわけでは無い以上、オレオレ証明書では（暗号化していたとしても）MITM攻撃による盗聴・改竄は防げません。**

オレオレ証明書の裏にある問題点
------------------
また、この問題にはサーバの脆弱性に加えて教育面でも問題があります。

イントラネット以外でのオレオレ証明書がまずいと知っている人は良いですが、ネットワーク技術に明るいわけではない新人や、専門分野の違う人の中には知らない人もいるかと思います。そういった人がこういったシステムを使い続ければ、これが普通だと思い、警告画面に慣れるに従って警戒心も持たないまま証明書を受け入れるようになっていくでしょう。いえ、既になっている人もいると思います。

この場合、2つの問題があります。

1つは本人が被害にあう危険性です。
ChromeやFirefoxの警告画面がバージョンアップに従ってどぎつくなっていったことからもわかるように、本来インターネット上でこの警告画面が出た際は十分な警戒心を持ってあたるべきものです。
しかし、警告画面に慣れた人の中にはいつも通りに証明書を受け入れてしまう人が出てくるでしょう。

もう1つはお客様に提案する際の問題です。
IT技術に詳しくないお客様などが年間費用を嫌ってオレオレ証明書を希望するというのは、ありうる話ですし、気持ちとしてはわかります。

その際に、ここに書いたような知識を（説明する必要は無いですが）背景として、「それは安全ではないのでダメなんです」と伝えるためには、オレオレ証明書の受け入れに慣れてしまうのは悪影響と思います。

さて、明日は同じ証明書でもクライアント証明書のお話。@seiketkm@githubさんです。