自堕落な技術者の日記

基本は喰ってるか飲んでるかですが、よく趣味でカラオケ・PKI・署名・認証・プログラミング・情報セキュリティをやっています。旅好き。テレビ好きで芸能通

(小ネタ) Chrome 60で証明書を表示させるフラグ設定

Chrome 56からGoogleの「素人はすっこんでろ」UI/UXポリシーによりHTTPSで接続した際に使用しているSSLサーバー証明書の表示が鍵アイコンから簡単にできなくなってしまいました。証明書大好きっ子にはなんとも辛い仕打ちでした。開発ツールからは証明書が表示できるので、メニューを辿って操作するか、ショートカットキーを素振り100回していた方も多いのではと思います。

Windows: Ctrl + Shift + I or F12
Mac: ⌘ + Opt + I

今日は、やっとChrome 60からフラグ設定で証明書が簡単に表示できるようになったので、今日はその設定について紹介します。

何も設定していないと、HTTPSサイトを見ている際の、鍵アイコンをクリックして見られるメニューはこんな感じ。
before
そこで、アドレスバーで以下のように入力します。

chrome://flags/#show-cert-link
すると、このようなフラグ設定が表示されます。
flag
「有効にする」をクリックし、指示に従ってブラウザを再起動します。すると、HTTPSサイトを表示した場合このように
after
「証明書、有効」というリンクが表示されるようになり、クリックすると証明書が表示されるようになります。いや〜〜、よかった、よかった。
52

GmailアカウントでS/MIME 署名/暗号メールを使う(その1 iOS標準メーラー編)

とある匿名の紳士がご厚意で、JCANのS/MIME証明書をわたしのGmailのアドレスに発行してくださり、iOSの標準メーラーのGmailアカウントからS/MIME署名/暗号メールが送れるようになりました。 docomoアカウントのメールはS/MIME使えないので渡りに船でした。(匿名の淑女からいただいていたS/MIME証明書はとっくに期限切れになり困っていました。)

「ブログに書いて下さいよ〜〜〜」とその紳士に言われていたので、ちょっと書いてみたいと思います。

ここに書いてあるのは、JCAN証明書に限った話ではないので、iOS標準メーラーの任意のアカウント向けの証明書で使える話です。現時点で最新のiOS 10.3.2で試しました。

,泙困麓分のS/MIME証明書のインストール

発行された証明書と秘密鍵のファイルである「*.p12」や「*.pfx」を添付ファイルにしてiOS標準メーラーのアカウントに送り、添付ファイルを開きます。
IMG_2600m
表示されている「インストール」のリンクをクリックし、iOSのロック解除パスコードを入力し、続いて *.p12 または *.pfx ファイルのパスワードを入力すれば証明書がインストールされます。
IMG_2601m

⊆,GmailアカウントへのS/MIME証明書の設定

次に、iOSの標準メーラーからGmailのアカウントでS/MIME署名メールを送れるように、証明書(と鍵)の設定をします。「設定>メール>アカウント>Gmail>アカウント>詳細」の一番下の方にS/MIMEの設定があります。S/MIMEをオンにして「署名」を開き、
IMG_2602m
「署名」をオンにして証明書を選択します。JCANからの証明書は「BN-英語氏名」となっていると思います。
IMG_2603m
この時点では「デフォルトで暗号化」は「いいえ」のままがいいです。

iOS標準メーラーからS/MIME署名メールを送ってみる

iOS標準メーラーからGmailアカウントを選んで新規メールを送ってみましょう。
IMG_2604m
宛先が空欄の時には、錠前アイコンは「グレーで開いた」状態です。錠前が開いている状態は「相手に対して暗号化しませんよ」という意味です。また、グレーの錠前がある状態は「S/MIMEが利用可能」な状態にあるということです。次に、S/MIME署名メールを送りたい相手を選んでみましょう。
IMG_2606m
青い錠前が開いている状態は「メールの送信が可能で、相手にはS/MIME暗号化をしない」ということを意味しています。初期状態では相手の証明書をもらっていないので、暗号化できないのは当然です。ここで、無理やり「開いた青い錠前」をクリックしてみましょう。
IMG_2607m
相手の証明書を持っていないので、宛先が赤くなり「赤い錠前」のアイコンになり「暗号化できません」と表示されます。もう一度クリックして青に戻し、送信してみてください。

ちられてきた署名メールを受けてみる

iOSのメーラーから送られてきたメールをS/MIME対応のメーラー、例えばOutlookで見てみましょう。
zzz01m

ゥ僖愁灰鵐罅璽兇S/MIME署名メールから証明書を登録する

iPhoneから暗号メールまたは、署名暗号メールを送る場合には、iOSの標準メーラーのS/MIME関係の利用方法はいろいろイマイチな面が多いですが、署名メールに単純に返信する形では送れず、iPhoneでの相手証明書の事前登録が必要です。ここでは、その「相手の証明書」の登録方法を紹介します。

まず、送られてきた署名メールを開きます。
IMG_2606m
青い錠前をクリックしても、証明書が無いので赤くなるだけなので、もう一度タッチして青になるように戻します。
IMG_2607m
ちなみに、送られてきたメールが署名暗号メールだと、以下のようにバッジ(署名)と錠前(暗号化)の2つのアイコンつきます。
IMG_2609m
ちなみに、このメールをiPhoneの標準メーラーではなく、Gmailのウェブアプリで見てみると以下のようになっています。smime.p7mというファイルが添付されているだけで、暗号化されており、バイナリファイルを見ても内容はわからないでしょう。(そのうち、この中身のバイナリファイルの形式について述べることもあるかもしれません。) Googleにもメールの内容を知られることなく、安心ですね。
スクリーンショット 2017-06-09 22m
そこで、相手のアドレスをタッチすると、相手の連絡先が表示され、証明書に関する記述も書かれています。
IMG_2597m
「証明書を表示」のリンクをタッチすると、相手の証明書が表示されますので、「詳細」を表示などして、内容をざっと確認して「インストール」をタッチするとインストールされます。
IMG_2598m
IMG_2610m
以上で送信先の証明書を登録することができました。

iPhoneからS/MIME署名暗号メールを送る

先ほど証明書を登録した人に新規にメールを送ってみます。宛先にメールアドレスを入力すると、最初は青い錠前は開いている状態です。
IMG_2613m
青い錠前をクリックすると、無事「暗号化済み」と表示されています。あとは送信ボタンを押すだけです。
IMG_2614m
パソコンのOutlookで受け取ってみると無事、署名暗号化メールを見ることができます。
zzz07m

おわりに

以上、JCANのS/MIME証明書をいただいたので、iPhone標準メーラーのGmailアカウントに設定し、 署名暗号メールを送受信してみました。 すこし、登録などまどろっこしい所もあるんですが、AndroidではまともなS/MIMEメーラーは無いので、 iPhoneの標準メーラーはS/MIMEを「ちゃんと」使えて大したもんだなぁ、、、と思います。 今回の証明書はJCANさんのでしたが、英語の申請が気にならなければCOMODOからも 無料のS/MIME証明書を発行してもらえます。よかったらトライしてみてください。

これで、Googleはユーザーのメールの内容を監視していたりするんでしょうが、安心してムフフなメールのやり取りを他の人には決してみられることなく送れるわけです。いや〜〜、素晴らしいですね。

Gmailアカウント用のS/MIME証明書を欲しかったのは、実は GoogleのG-Suite Enterpriseではサーバーに秘密鍵と証明書を設定して クラウド型でS/MIMEの署名暗号メールが使えるそうで、それを使ってみたかったというのが あります。最近、インシデント対応に追われてなかなか時間が取れないんですが、 なんとか時間作って試したいなぁと思っています。 ではでは。

関連記事

Amazon AWSの認証局が少し怪しい件

Amazon AWSのELBとCloudFrontで使えるらしい、無料の証明書発行サービスで、AWS Certificate Manager(ACM)というのがあるそうです。([参考1])。ちょっと気になったきっかけはJavaからHTTPSで繋ぐと検証失敗するケースがあった


というので、ちょっと見始めたらドツボにはまったので、少しメモを書き残しておこうかとおもいます。

ACMの証明書を使ったサイトにブラウザで繋いでみると、、、

Javaで繋がらないとなると、ルート証明書や中間CA証明書が入ってないんだろうと疑ってみるとおもいます。 とりあえず、ブラウザで繋いだりしてみました。Windows 7のChromeやIEだとこんなパス。
view-ch-ie
Mac OS X(や多分iOSも)だとSafariでもChromeだとこんなパス。
safari-view
FirefoxだとOSによらず、WindowsでもMac OS Xでもこんなパス。
view-ff-chain
クライアント毎に使われている信頼するルート証明書が違うようです。 Starfieldルートになっているケースもありますね。 調べてみると、AmazonはGoDaddyからStarfieldルート認証局を一つ買ったのだそうです。

ACMの証明書を使ったサイトにブラウザで繋いでみると、、、

Amazonの証明書発行サービスはAmazon Trust Servicesというのだそうで、 証明書ポリシ、認証実施規程などの文書、ルート証明書、中間CA証明書などが置いてある リポジトリはこちらにあるようです。

リポジトリをよく見てみると、クロス証明書(片方向相互認証証明書、中間CA証明書)の リストがあるんですが、ハッシュと証明書のリンクが張ってあるだけで、大した説明もなく えらく不親切なページですよね。 認証局の構成がよくわからなかったので、これを元に図にしたのがコレです。(かなりの力作だとおもいます。)
ca-structure

なんかCAの鍵使いまわしてないですか?

このクロス証明書のリストで気になったのが、各Amazon Root 1〜4に対して、origとそうじゃないやつ、Starfieldに関してはv2とそうじゃないやつがある所です。 例えば、Amazon Root 1のorigとそうじゃないやつを比較してみると 以下の3点が違うだけで、

  • シリアル番号が違う
  • notBeforeが違う(origが2015年10月で、orig無しが2015年5月)
  • authorityInfoAccess拡張のcaIssuerのURLが少し違う。 http://{crl,crt}.rootg2.amazontrust.com/rootg2.cer となっている。origがcrlで、origなしがcrt。
とほとんど同じで、caIssuerを直したいだけのつまらない理由のために、中間CA証明書を再発行したようです。 これって中間CAの鍵を使いまわしてますよね。マズくないんですかね? さらに問題なのは、
  • どちらが正しい証明書なのかわからない。
  • ファイル名からはorigが古いように見えるが、 notBefore的には逆にorigが新しいようにも見える。
  • どちらか一方を失効しているわけでもなく、どちらも有効。
  • パス検証としてはどちらを使っても検証成功となるが、そんな事でいいのか?
  • 将来、{crl,crt}.rootg2.amazontrust.comのいずれかを無くす計画があると思うが、 それが明らかになっていない。
といった所です。 ちなみに、caIssuerに記載されたURLは、今の所はどちらもアクセス可能なようです。 両方にアクセスできるなら、なおさら中間CA証明書再発行の必要があったんですかねぇ? 単に、DNSの別名、CNAMEレコードの設定だけの問題なんじゃないですかねぇ。 また、本当はどちらに寄せたいと思っているのかも明らかにされてませんよねぇ。

同様に、Starfield Class 2 CAからStarfield Services Root CA G2に発行している 中間CA証明書も怪しくて、シリアル番号とnetBeforeだけが違う証明書があります。 どちらも失効していません。 こんなことして大丈夫なんですかねぇ? 最近、Certificate Transparency(CT)でSSLサーバー証明書全ての発行履歴残されており、 (私は最初はCTは嫌いだったのですが、) 認証局が問題あると、 (シマンテックのように、、、、) いろんな人が指摘してくれます。 中間CA証明書の発行についても、CTログに残しておかないと、 ヤバイ運用があるんじゃないかなぁ、、、、と思います。

Amazonの認証局はWebTrust認定もしており、Ernst Youngが監査しているそうですが、 こんなんで本当に大丈夫なんですかね?

Java 8?のcacertsのaliasについて

Amazon AWSやACMとは全く無関係ですが、最近自分は、Javaはめっきり触らなくなってしまい、今回の件でかなり苦労しました。Javaの信頼する認証局のためのキーストアファイルであるjre/lib/security/cacertsファイルなんですが、中のファイルを取り出そうとすると、そんなファイルは無いと怒られてしまいました。 よく見ると使ってみた新しい8u121では、aliasはこのようになっており、

% keytool -list -keystore jre/lib/security/cacerts   :中略 globalsigneccrootcar5 [jdk],2016/08/26, trustedCertEntry, 証明書のフィンガプリント(SHA1): 1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46: 3A:1B:69:AA starfieldservicesrootg2ca [jdk],2016/08/26, trustedCertEntry, 証明書のフィンガプリント(SHA1): 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63: E8:25:6F:3F ttelesecglobalrootclass2ca [jdk],2016/08/26, trustedCertEntry, 証明書のフィンガプリント(SHA1): 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF: 17:D8:94:E9 addtrustqualifiedca [jdk],2016/08/26, trustedCertEntry, 証明書のフィンガプリント(SHA1): 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E: C5:4D:8B:CF   :後略
例えば「starfieldservicesg2ca」だけではだめで、表示されている通り「starfieldservicesg2ca [JDK]」のようにちゃんと[JDK]までつけないといけなくなったのだそうです。知らなかったし、ハマりました。

GWなもんで、今日はこんなとこで。

参考リンク

A look at AWS Certificate Manager
ACMを使い始めるときに参考になる。ACMを使ったサイト。
Free SSL With Amazon’s AWS Certificate Manager (ACM)
ACMを使い始めるときに参考になる。(その2)
ACM FAQ
公式サイトのFAQ

追悼 Adobe CDS

PDF署名の利用拡大につながると、密かに期待していた、とても先進的な サービスだったAdobe CDSが、いよいよサービスを終了し、AATL (Adobe Approved Trust List)に移行すると知りました。まぁ、移行とは言えず、いろいろなものを捨て去っているわけですが、、、かつて自分も人柱としてAdobe CDS対応の証明書とトークンを購入し、使ってみたりもし、幾つかブログで書かせてもらい、良いサービスだったのですがとても残念です。悲しすぎるので追悼記事のようなもの書いてみたいと思います。
cdstoken

Adobe CDSとは何か

Adobe Acrobat には誰が署名をしたか、それが改ざんされていないかを示すためのPDF署名機能があり、Adobe Acrobat ReaderにはPDF署名の検証機能がついています。PDF署名の運用を厳格化し、Adobe Acrobat Readerのデフォルトであっても、ちゃんと本人確認をした証明書とハードウェアデバイスをつかって署名したPDF署名が検証できるようにするサービスがAdobe CDSでした。Adobe CDSには

  • HSMを使った組織によるサーバー向けPDF署名
  • USBトークンを使った個人によるPDF署名
の2種類に対応していました。ただのPDF署名とはどう違うのか、比較表にまとめてみました。
一般的なPDF署名Adobe CDS PDF署名
証明書発行の際、本人確認をしようがしまいが構わない 証明書発行の本人確認はかなり厳格。例えば、パスポートのコピー、メールアドレスの送付と電話による(英語での)本人の意思確認など
秘密鍵の管理はなんでもよい 秘密鍵は必ずサーバー型ならHSM、個人型ならUSBトークンに格納され、エクスポート不可。(スマートカード対応の認証ベンダーはなかったはず。)
証明書はデジタル署名が可能ならなんでも良い。例えば、SSLサーバー証明書と秘密鍵でもよい Adobe CDS署名専用の証明書であり、拡張領域に専用の拡張がある。証明書ポリシもCDS対応のものでないとAdobe CDSに登録できるCAとはならない。
PAdESタイムスタンプつきPDF署名である必要はなく、普通のPDF署名でもよい 署名するとPAdES署名タイムスタンプ付きのPDF署名となる
タイムスタンプをつけようとする場合、日本では一般に別途、タイムスタンプ事業者との利用契約が必要 Adobe CDS対応の認証局では、証明書を購入すればタイムスタンプサービスが合わせて提供される。Adobe CDSでは、認証サービスごとに、どのタイムスタンプサービスを使用するかが、証明書拡張に記載されており、固定である。認証サービス自体がタイムスタンプサービスを提供しているケースが多い。
信頼するルート証明書のリストはAdobe独自のものだった。この度これが、Adobe Approved Trust List(AATL)というルート証明書プログラムとして定義され、現時点で58のルート証明書が登録されている。WindowsやMac OS Xなどのルート証明書の数は400程度とこれよりかなり多いが、OSの持つルート証明書はAcrobat Readerのデフォルトでは信頼しておらず、これを信頼するようにするには設定変更の必要がある。 Adobe CDSのルート認証局はAdobeのルート一つであり、中間認証局としてAdobe CDS対応の認証ベンダー6つ程度があり、そこからユーザ用の証明書が発行される。Adobe CDS用の専用の運用ポリシ(CP/CPS)で運用されている。どのようなOSのAcrobat ReaderでもOSのトラストリストに関係なく同じ検証結果となる
Adobe CDSサービスのポイントは以下のようになると思います。
  • 確かに本人が署名したと見なせる印鑑で言えば実印レベルのPDF署名ができる
  • (最近いろんな認証局が問題起こしていますが)運用のしっかりしていない認証局が紛れ込む可能性が比較的低い(けど、この中にも問題起こしたところありましたよね)
  • Adobe CDS専用の証明書で署名する
  • 電子署名では、証明書が有効だった時刻に署名されたことを示すために、タイムスタンプが必須とされるが、Adobe CDSではデフォルトで署名タイムスタンプつきPDF署名となる
  • USBトークンなどのハードウェアデバイスを持っているはずの本人署名できず、他人がなりすまして署名をされる可能性は極めて低い

Adobe CDSのナイスなところ

タイムスタンプ付きPDF署名をしようとした場合に、日本では一般に署名用のクライアント証明書と、タイムスタンプサービスの利用がそれぞれ必要になります。これって、それぞれお金がかかるし、煩わしいですよね。日本でタイムスタンプ付き署名が流行らない理由の一つなのではとも思ってたりもします。海外の署名用証明書発行サービスでは、タイムスタンプサービスとセットで提供するものが多いですし、Adobe CDSもセット提供で、とても使いやすいです。

コード署名用証明書なんかも、RFC 3161タイムスタンプとは違いますが、似たようなカウンタ署名によるタイムスタンプの仕組みがセットで提供されるので、デフォルトでコード署名にはタイムスタンプがつきます。

Adobe CDSの何がいけなかったのか

Adobe CDSを使っているかどうかで、PDF署名に対する信頼の度合いは全く異なると思うのですが、Acrobat Readerでは、普通のPDF署名とAdobe CDS PDF署名との違いはありません。違いもないのなら、高いお金を払ってまでAdobe CDSを使うメリットも薄いですよね。

また、認証局にとっても、独立した中間CAを運用しなければならない。特別な証明書プロファイルも必要で、認証局にとってもとても負担となるプログラムだったと思います。相当利用が伸びないとサービスを維持するのは難しいと思います。

Adobe CDSのようにUSBトークンを使ったり、マイナンバーカードのようにスマートカードを使ったり、ハードウェアデバイスを使用して、厳格な本人確認のもと発行された証明書に関しては、共通の専用の証明書拡張を持たせるようにし、普通の署名とは区別し、EV証明書の緑のアドレスバーのような表示上の区別をしないと、ハードウェアデバイスを使った署名がなかなか普及しないのかなとも思います。

最近では、クラウド上で秘密鍵の管理をし、リモートで署名を行うような運用形態も増えており、ハードデバイスを本人が管理して署名するというのは、だんだん時代にも合わなくなってきたのかもしれません。

おわりに

Adobe CDSは、維持費用も結構かかるので、結局持ち続けることはできませんでしたが、「実印レベルのちゃんとした」PDF署名であるAdobe CDSは、なくなって欲しくはなかったです。ホントさびしい。バイバイ Adobe CDS。

関連記事

HPKP(HTTP Public Key Pinning)公開鍵ピニングについて考える

もくじ
1. はじめに
2. HPKPが生まれた背景
3. HPKPの仕組み
4. ピンの設定の考察
 4.1. ピンの値の取得方法
 4.2. 証明書チェーンに一致するピンの選択
 4.3. 証明書更新とHPKPヘッダの設定変更の運用方法
 4.4. バックアップピンという名前のイケてなさ
 4.5. CA鍵のバックアップピンのオススメの値
 4.6. 証明書チェーン中で複数ピンをつけても意味はない
 4.7. 同じCA証明書にPinし続ける場合の課題
 4.8. 2つのCA証明書にPinする場合の課題
 4.9. max-ageのオススメ値を考える
5. HPKPはどの程度使われているのか
6. 今のHPKPの何がいけなかったのか
7. おわりに
8. (参考) HPKP関連の勉強になるリンク
9. 追記
 9.1. 追記(2017.02.26) HPKPのブラウザサポート状況
 9.2. 追記(2017.02.26) smashingmagazine.comで発生したHPKP障害

1. はじめに

HPKPとはHTTP Public Key Pinningの略で、RFC 7469 Public Key Pinning Extension for HTTPで規定されており、 ウェブサイトのオーナーが、ニセのサイトで意図しない証明書チェーンが使われないように保護するための仕組みです。

日本語解説は少ないですが、敬愛する jovi0608さんの記事Jxckさんの記事などでも解説されています。

私も3年ちょい前、IPAのガイドを書いていた前あたりから、HPKPの運用上の課題について、何かブログ等で書きたいと思っていたのですが、なんか日頃のヘンなことに忙殺されて、これまでまとめて書くことができませんでした。(なんか書こうと思ってたらjoviさんのが出ちゃって、まぁいいかと思っちゃったっていうのもありますw) IPAのガイドの時も書かせてもらおうとしたんですが、なんだか大人の事情で追加させてもらうことができませんでした。とほほ。

今回は、HPKPとは何かといった基本的なことは、他の方のブログに譲るとして、HPKPの現状やHPKPの運用上の課題についてフォーカスして書きたいと思っています。長くなりそうですが、ごめんなさいね。

結論から言えば、本番サイトで安易にHPKPを使うのはやめた方がいいと考えています。それは、HPKPの仕様自体が運用をしっかり考えて設計されておらず、一般的なサイトでは大したセキュリティ上の効果が無い割に、長期の運用でサービスを提供できなくなる期間が発生するリスクが高すぎるし、証明書のコストも余計にかかるからです。

おそらく、HPKPの運用について深く突っ込んでかいた、世界では初めての解説資料かなと思います。ご笑納くださいw

2. HPKPが生まれた背景

2011年頃から、認証局を対象にしたサイバー攻撃や、認証局の運用上の不備などで、攻撃に利用しやすいGoogleやFacebookといった有名サイト向けのワイルドカード証明書(*.google.com等)を取得されてしまうという事件が増えてきました。Googleを怒らせちゃったのは2011年のオランダの認証局DigiNotarが不正侵入を受け、*.google.comのワイルドカード証明書を発行され、イランのプロバイダの盗聴や攻撃に使われたという事件がありました。
hpkp-digi
このような事件を防ぐためには、ウェブサイトに対して、サイトオーナーの意図しない証明書が使われた場合に、警告を発する仕組みが必要です。そこで開発されたのが、HPKPです。HPKPでは、証明書チェーンの証明書公開鍵のハッシュの一致を確認することにより、ウェブサイトオーナーの意図した証明書かどうか検証することができます。
hpkp-hpkp1
joviさんのブログの1章で背景と仕組みをわかりやすく解説されているので、そちらもご覧頂ければと思います。

3. HPKPの仕組み

HPKPの実装方法には2つの方法があります。

  • 1) Google、Facebook、Twitterなどの有名サイト向けの、ChromeFirefoxなどブラウザに組み込まれたピンのリスト(Preloaded Known Pinned Host List)と照合する方法
  • 2) HTTPSで通信する際に、サーバーからピン情報のHTTPヘッダを取得し、それをブラウザに保管しておき、以降の通信で照合に使う方法
1) の方法は、ブラウザを最新になっているならば何も設定しなくても、有名なサイトについてはHPKPを使って安全に接続することができます。今回の記事で議論したいのは2)のサイトオーナーが設定する場合についてなので、2)の仕組みについて説明します。
hpkp-sethead
ウェブサーバーに不正な証明書チェーンに接続させないためのHPKP HTTPヘッダを設定するのですが、これはウェブサーバーのHTTPS設定で使用するルート証明書からSSLサーバー証明書までの証明書チェーンを元に設定します。HTTPヘッダとその値の書式は以下のようになっています。
Public-Key-Pins: \   pin-sha256="チェーン中の公開鍵のどれかのSHA256ハッシュ値のBase64"; \   pin-sha256="チェーン中の公開鍵のどれにも一致しないSHA256ハッシュ値のBase64"; \   [pin-sha256="その他ハッシュ値1"; ...; ] \   max-age=ブラウザにこのHPKPヘッダが保管される秒数; \   [includeSubDomain;] \    サブドメイン(example.comならsub.example.com)もHPKPの対象にするか   [report-uri="JSON形式のエラーレポートがPOSTされるURL"; ] [...]はオプション
  • pin-sha256は証明書チェーンを元に設定しますが、その設定方法や考察については後で述べます。
  • max-ageの保存期間はRFCの4.1節で考察しており60日(=5184000秒)が良いのでは?としていますが、その考察も後で述べさせて下さい。
  • includeSubDmainは、サブドメインまで含めるか、例えば example.com にHPKPを設定したら、sub1.example.comも、www1.sub2.example.comもHPKPの対象にするというフラグです。現時点で持っていないなら安易に設定しない方が良いように思います。
  • HPKPは、CSPなどと同様ににブラウザ側で検証するので、サーバー側にはエラー原因が把握できず困ることがあります。report-uriを使えば、ブラウザでHPKPのエラーが発生した際に、指定したURLのウェブサーバーにJSON形式のエラーレポートをPOSTすることで送信しますので、設定上の問題を知るのに役立つかもしれません。Jxckさんのブログで設定を試してみたという詳しい報告がされているのでご覧になると良いでしょう。ブログでも書かれていますが、レポートが出力される条件がよくわからず、ブラウザやバージョンにも依存するようで、私もレポート生成がうまくできていません。
また、HTTPヘッダについて "Public-Key-Pins" ではなく、"Public-Key-Pins-Report-Only" と設定すれば、ブラウザではエラーを発生させることなく、エラーレポートの収集はできますので、テストの際にこれを使うと良いでしょう。

4. ピンの設定の考察

pin-sha256属性を使ってピンを設定することにより、サーバーオーナーが意図しない証明書が使われることを防ぐことができます。 ピンの値は、証明書チェーンの証明書の何れかの証明書に一致するものを最低一つ、 どれにも一致しないものを最低一つの計2つ以上により構成されます。
hpkp-intersect

4.1. ピンの値の取得方法

さて、一番簡単なハッシュ値の取得方法ですが、すでにウェブサーバーのHTTPS設定が完了しているならば、Scott Helme氏のHPKPハッシュの所得ページを利用するのが良いです。自分のでも他人のでもHTTPSサイトのURLを入力すれば、証明書チェーンの各証明書のピンのハッシュ値を計算してくれます。
index
SSLサーバー証明書から順にルート証明書まで、ピンのハッシュ値が

pin-sha256="hUIG87ch71EZQYhZBEkq2VKBLjhussUw7nR8wyuY7rY="
のように表示されますので、どのピンを使うのかを決めてHTTPヘッダに設定するだけです。

一つのピンのハッシュ値の計算ですが、証明書からでも、証明書発行要求(CSR/PKCS#10)でも、 秘密鍵と鍵アルゴリズムによっては鍵パラメーターから抽出されたPKCS#8公開鍵からでもハッシュ値を計算することができます。 ただ、いろんな人のブログでは、わざわざCSRを作ってからハッシュ値を計算しているようですが、特に証明書のまだ無いバックアップピンの場合には、 そんなことをしなくとも、公開鍵からハッシュ計算するのが良いように思います。 先ほどと同様に、Scott Helme氏のツールでPEM形式のPKCS#8公開鍵、CSR、X.509証明書を入力すれば、ピンのハッシュ値を計算してくれるページがあるので、これを使うのが簡単です。

手作業でピンを取得する場合には、以下を実施すれば公開鍵のSHA256ハッシュであるピンの値が取得できます。他の解説記事では、base64コマンドを使ったり、CSRをいちいち生成するのを強制させたりしているようですが、ここで紹介する方法はOpenSSLコマンドしか使わず、いろいろなケースに対応して、ピンの取得ができるように、例を示しておきました。

X.509証明書からsubjectPublicKeyInfoフィールドにあるPKCS#8公開鍵のピンの入手 % openssl x509 -in PEM証明書 -pubkey -noout | openssl rsa -pubin -outform DER | \ openssl dgst -sha256 -binary | openssl enc -base64 te4kc4F/5BhtIosKLOS9sy049x7a/LQHNRRG1WHfvyU= CSRからsubjectPKInfoフィールドにあるPKCS#8公開鍵のピンの入手 % openssl req -in PEMCSRファイル -pubkey -noout | openssl rsa -pubin -outform DER | \ openssl dgst -sha256 -binary | openssl enc -base64 te4kc4F/5BhtIosKLOS9sy049x7a/LQHNRRG1WHfvyU= PKCS#8秘密鍵からピンの入手 % openssl rsa -in PKCS#8秘密鍵 -pubout -outform DER | \ openssl dgst -sha256 -binary | openssl enc -base64 te4kc4F/5BhtIosKLOS9sy049x7a/LQHNRRG1WHfvyU= PKCS#8公開鍵からピンの入手 % openssl rsa -pubin -in PKCS#8公開鍵 -pubout -outform DER | \ openssl dgst -sha256 -binary | openssl enc -base64 te4kc4F/5BhtIosKLOS9sy049x7a/LQHNRRG1WHfvyU= 得られた値を pin-sha256="te4kc4F/5BhtIosKLOS9sy049x7a/LQHNRRG1WHfvyU=" のようにヘッダに設定する。
値を取得したら、ウェブサーバーのHTTPヘッダに設定します。例えば、Apache HTTP Serverの場合には、以下のように設定します。
<VirtualHost _default_:443> ... Header set Public-Key-Pins \ "pin-sha256=\"MRnxhYBVCMAxZHwalTJ7ZVl6P2005lll4ttWr+RN1Ro=\"; \ pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; \ max-age=2592000; \ report-uri=\"https://report.example.com\"" ... 読みやすさのためにバックスラッシュと改行を入れています。2592000秒は30日です。

4.2. 証明書チェーンに一致するピンの選択

HPKPでは、証明書チェーンに一致するピンを1つ以上設定する必要があります。本節では、次の2つに分けて考察してみたいと思います。

  • 1) 証明書チェーン中のどれか一つのみを選択する場合の比較検討
  • 2) 証明書チェーン中の2つ以上、または全部を選択する場合の考察

4.2. 証明書チェーンに一致するピンの選択

証明書チェーンで、SSLサーバー証明書、中間CA証明書、ルート証明書のような3段の証明書になっている場合、 不正な意図しない証明書チェーンになっていないかどうか検証するために、 どれか一つのピンを選ぶとすれば、どれを選べば良いでしょうか。 これら3つのケースで、それぞれ長所、短所があるので、考察してみたいと思います。 SSLサーバー証明書については、数年後証明書更新の際に使用する鍵ペアがあらかじめ決まっている場合(=鍵事前生成)、決まっていない場合(=鍵事前生成なし)のケースに分けて考察します。

証明書長所短所安全性運用負担
.襦璽CA証明書
  • 有効期間が長いためピン変更の頻度が少なくて済む。おそらく10年程度は変更不要
  • ブラウザ組み込みのプリロードピンではルート証明書を使用
  • 鍵更新後の公開鍵は事前にはわからずバックアップピンは使えない
  • 新しいSSLサーバー証明書を購入した場合に、同じルート認証局とは限らず、その際はピンの移行が必要
  • ルート証明書配下の証明書の数は非常に多く、その認証局が不正な証明書を発行された場合に、攻撃を防げないリスクは高い。例えば、シマンテック社がGoogleに許可なくGoogleの証明書を発行する事件があった。
  • 証明書更新でルートCAが変更になる可能性は低いが、変更になった場合には、max-ageに配慮した面倒な移行が必要で運用負荷が高い
中間CA証明書
  • 有効期間がやや長いためピン変更の頻度が若干少なくて済む。おそらく5年程度は変更不要
  • 安全性と運用負担の面でバランスが取れているか?
  • ピンする中間CAの公開鍵に変更がなかった場合のSSLサーバー証明書の更新は比較的楽
  • ピンしている中間CAの公開鍵が、次回のSSLサーバー証明書更新時に同じであるという保証はない。
  • SSLサーバー証明書の更新時に、中間CA証明書が変更になるリスクがあるが、それが事前 周知されないために、SSL接続不具合によるサービス停止リスクが高い
  • 中間CA証明書が変更になった場合の移行に係る運用負担は、回数も、作業負荷も 非常に高い
  • 同じ中間CAから、不正に同じドメインに対する証明書が発行された場合にも検証有効となってしまうリスクがある。,茲蠅魯螢好は低いが、い茲蠅蝋發
  • 証明書更新で中間CAが変更になる可能性はある程度あり、,茲蠅漏領┐高い。変更になった場合には、max-ageに配慮した面倒な移行が必要で運用負荷が高い
SSLサーバー証明書(鍵事前生成)
  • SSLサーバー証明書の更新時に、ピンした公開鍵のマッチング設定に失敗する可能性が低く、HPKP設定不備によるサービス停止のリスクは最も低い
  • HPKPのRFCでは、(さらっと簡単にできると取れるような記述がされており)推奨されているように取れる方法
  • 不正証明書チェーンが使われるリスクは、(秘密鍵漏洩のリスクを除けば)い汎営度に、´△茲蟾發
  • 証明書更新の前後で、変更されるピンがあらかじめわかっているので、(max-age内に再度証明書更新をすることをしなければ)max-ageをあまり気にせずに証明書の更新ができる
  • SSLサーバー証明書の更新時に、鍵ペアの事前生成が可能なのは、OpenSSL等により手作業で鍵ペア生成した場合のみであり、証明書の発行時に、CSRを自前で生成する必要がなく、ブラウザのコンポーネントで自動的に鍵ペア生成するような証明書発行サービスの場合には、本方式は使えない
  • Let's Encryptは使えず、SSLサーバー証明書自動更新に係る運用負担の軽減は見込めない
  • 鍵ペアは一般に、証明書の更新時に行われるものだが、それを2年程度前に実施することになる。事前生成しておくと、その分、SSLサーバー証明書の秘密鍵が漏洩するリスクは高く、機密保管の運用負担は大きい
  • 証明書の更新時には、それなりに設定変更に気を使う必要がある。また、その回数も2年弱程度おきであり、運用負担は比較的高い
SSLサーバー証明書(鍵事前生成なし)
  • 全てを自己制御でき、設定不備によるサービス停止リスクはと同程度に高い
  • に比べてSSLサーバー証明書の秘密鍵が漏洩するリスクも低い
  • 不正証明書チェーンが使われるリスクは、(秘密鍵漏洩のリスクを除けば)い汎営度に、´△茲蟾發
  • SSLサーバー証明書を使える期間が、必ず (max-age + α)×2 分だけ減る。2年物証明書の場合、max-ageを2ヶ月とした場合、テストや余裕も含め4〜5ヶ月程度は短くなることになり、証明書の費用負担が増える
  • 証明書更新の前後で証明書の有効期間をmax-age+αでオーバーラップさせれば、必ずmax-ageに配慮しながらピンの変更を行うことになる。運用の負担はあるが、ピンが変更になるか認証局次第でどうなるかわからない´△鉾罎戮董必ずmax-ageに配慮した、証明書更新、HPKP設定変更のスケジュールが組めるので、定型運用にできるため運用の心理的負担は´△茲蠅麓禊馨ない
  • では、 銑い任蓮何を選択するかですが、ブラウザ組み込みのピンが使えない一般サイトの場合は、 ◆銑のいずれかが妥当だと思いますが、どれも運用の負担や、サービス提供不能になるリスクがあり、 個人がテスト目的で設定する場合は何でも良いとして、 自分が商用サイトの運用を任されているならば、もっとも懸念すべきは 長期間サービス提供不能になりクレームが起きることなので、 HPKPは使わないという判断をすると思います。

    4.3. 証明書更新とHPKPヘッダの設定変更の運用方法

    4.2節では、証明書チェーンのどこにピンを設定するかで、 どのような違いがあるのかについて考察しました。

    本節では、4.2節の考察を受けて、設定不具合によるサービス利用不能を 防ぎながら、HPKPを使ったサイトの証明書更新、HPKPヘッダの変更を、どのように運用すればよいのかについて 考察します。

    HPKPを使った場合の証明書更新の運用の仕方は4つのケースにわけることができます。

    • a)証明書更新のmax-ageより前に確認し、ピンを行っている鍵に変更がない場合
    • b)証明書更新のmax-ageより前に証明書更新の前後でピンを行う公開鍵が何に変更されるかわかっている場合
    • c)証明書更新のmax-ageより前に証明書更新の前後でピンを行う公開鍵が何に変更されるかわからない、もしくは変更が明らかだが、更新の前後の証明書の有効期間をmax-age + αオーバーラップできる場合
    • d)証明書更新のmax-ageより前に証明書更新の前後でピンを行う公開鍵が何に変更されるかわからない、もしくは変更が明らかだが、更新の前後の証明書の有効期間をmax-age + αオーバーラップできない場合
    このような説明では、具体的なイメージがわかないと思いますので、証明書チェーン中の証明書に分けて具体例を示してみましょう。
    • a-1) ルート証明書や中間CA証明書にピンを設定しており、顧客サポートに問合せたら、次回、max-age後の証明書更新では、使用するルート証明書、中間CA証明書には変更がないことがわかった場合。(顧客サポートに嘘をつかれたら、一部ユーザに2ヶ月(=max-age)サービス障害になるリスクあり。)
      hpkp-move1
    • b-1) ルート証明書や中間CA証明書にピンを設定しており、顧客サポートに問合せたら、次回、max-age後の証明書更新では、使用するルート証明書、中間CA証明書がどれに変更されるか教えてもらえた場合。もしくはサポートページなどで告知されている場合。証明書発行サービスの変更、EVへの変更なども同様。
      hpkp-move-b1
    • b-2) SSLサーバー証明書にピンを設定しており、OpenSSL等で次回の証明書更新で使用する鍵ペアがすでに事前生成され、保管されている場合
      hpkp-move-b2
    • c-1) ルート証明書や中間CA証明書にピンを設定しているが、次回証明書更新後のルート証明書、中間CA証明書の変更について、顧客サポートからの回答が得られず、変更されるかどうか判断がつかないため、仕方なく、証明書更新をmax-age + α前に実施して有効期間を重ねるよう事前証明書発行したら、やはりルート証明書、中間CA証明書は変更になっていた場合(変更がなければa-1のケースとなる。)
      hpkp-move-c1
    • c-2) SSLサーバー証明書にピンを設定しているが、OpenSSLを使わず、ブラウザの機能で鍵ペア生成するタイプの認証局であるため、事前に更新後の公開鍵はわからず、証明書更新をmax-age + α前に実施して有効期間を重ねるよう事前証明書発行できる場合
      hpkp-move-c2
    • c-3) SSLサーバー証明書にピンを設定しているが、HSM機能を使うSSLアクセラレーターを使っており、事前に更新後の公開鍵はわからず、証明書更新をmax-age + α前に実施して有効期間を重ねるよう事前証明書発行できる場合。移行の図はc-2と同じになります
    • d-1) SSLサーバー証明書にピンを設定しているが、Let's Encryptや一部の認証局のように、証明書更新後、前の証明書は即時に失効処理がされ、max-age + αの期間の有効期間のオーバーラップができない場合
      hpkp-move-d1
    自分の運用がどのケースにあてはまるか、上記の説明でわかったでしょうか。さて、a〜dのケースで、どのように対応するかを以下に示します。
    • aの対応) 証明書更新に際し、ウェブサーバーのHPKPヘッダの設定は変更しなくてよい
    • bの対応) max-ageをはあまり気にせず、証明書更新後の、ウェブサーバーの証明書設定、HPKPヘッダを設定変更してよい
    • cの対応) もっとも神経を遣う、max-ageに配慮した、証明書更新、HPKPヘッダ設定が必要。証明書の更新の前後で、有効期間のオーバーラップが必要
    • dの対応) このケースではHPKPは使えない。他の証明書、証明書発行サービスへのピン設定の変更を検討する必要がある。使っても、一部ユーザにサービス接続不能障害がmax-age程度発生する。
    どんな証明書更新、HPKPヘッダ設定の移行を行うにしても、証明書の有効期限、max-age、秘密鍵の保管など、様々なことに気を遣いながら、移行計画を立て、移行しないとならず、きちんと考えないと長期のサービス障害発生するという運用上の負担やリスクは大きいと思います。

    4.4. バックアップピンという命名のいけてなさ

    先に述べたように、何か一つ、証明書チェーンとはマッチしないピンを必ず含めなければいけません。SSLサーバー証明書にピンをする場合は、現在使っているSSLサーバー証明書の秘密鍵に対して、将来、証明書更新で使う予定の秘密鍵も事前に生成しておけるなら、その公開鍵をバックアップピンとして設定しておけば、まさしくバックアップとして使用でき、(後述の問題ありありですが)スムースな証明書とピンの移行が可能です。

    しかしながら、秘密鍵を移行先のバックアップとして事前生成しておき、これが利用できるというケースはレアケースです。例えば以下の一般に起こりうるケースでは、証明書更新の際に、その事前生成した秘密鍵を使用することはできません。

    CA証明書のバックアップPin
    認証局が行う証明書更新もしくは鍵更新において、事前に移行先の秘密鍵が存在するということもありませんし、移行先の公開鍵のPinをユーザに公開してくれる認証局もありません。
    HSMを使っている場合のバックアップ
    認証局やSSLアクセラレーターを使っているケースでは、秘密鍵を取り出し不可能なハードウェアセキュリティモジュール(HSM)で管理するのが一般的です。HSMを使用した鍵更新、証明書更新では、事前に秘密鍵を幾つか生成しておき、更新時にそれを指定して更新に使用するということができません。更新時には、新たに鍵ペアを生成して、これを使用します。このために、認証局ではバックアップPinを公開することができないのです。
    ウェブ画面で鍵ペア生成してSSLサーバー証明書発行する認証局の場合
    認証局によっては、ウェブブラウザの機能を使用して、ボタンを押せば自動で鍵ペア生成を行い、これを用いて証明書を発行し、新しい証明書を格納するものがあります。そのような認証局では、事前に生成しておいた鍵を発行時に使用するということができません。
    Let's Encryptを使う場合
    無料で世界一の発行数を誇る証明書発行サービスであるLet's Encryptでは、証明書の発行プロセスがスクリプトにより自動化されていますが、これも証明書の更新時には自動で鍵ペア生成されるので、事前に生成していた鍵ペアを使用することができません。
    本当の意味での「バックアップPin」が使えるのは、以下の場合にのみ可能であるということです。
    • SSLサーバー証明書に対してPinをする場合で、かつ、
    • OpenSSLなどのコマンドで鍵ペア生成し、マニュアルで証明書発行要求を生成して、証明書発行してもらえる認証局を使用する場合
    従って、証明書チェーンにマッチしないものを、「バックアップPin」と呼ぶのは、上述のほとんどのケースで適切でないので、名称には問題があると考えています。

    4.5. CA鍵のバックアップピンのオススメの値

    ルート証明書や中間CA証明書にピンを設定する場合、 一致しないピンは、将来の更新先がわからない場合には何でもよく、 さらには、本物の公開鍵のハッシュである必要もありません。 SHA256なので、単に32バイトの値であれば何でも良いわけです。

    ただ、HPKPヘッダで一見して一致しないピンだとわかったほうが、 誤って削除するなどの運用ミスを防ぐ意味でも良いと考えており、 そこで、オススメしたいのが、以下の値です。

    pin-sha256="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; これは、16進数で 0000000000000000000000000000000000000000000000000000000000000000 (32バイト)
    となります。流行るといいなと思っていますw

    4.6. 証明書チェーン中で複数ピンをつけても意味はない

    これまで、証明書チェーンと一致するピンの数は1つを前提に議論してきましたが、 これを複数、例えば、ルート証明書と、中間CA証明書と、SSLサーバー証明書のピンを一致させた場合には、 どうなるのかを考察したいと思います。

    まず、SSLサーバー証明書にピンを打って、次に中間CA証明書、次にルート証明書のピンを追加していく ことを考えてましょう。 同じ鍵ペアを複数の認証局からのサーバー証明書発行で使用しないという、当たり前の事を前提とします。 SSLサーバー証明書にピンを打つ事が最も、範囲が限定的でニセHTTPSに対する 最も強い対策であると、4.2節で述べました。

    そこに中間CA証明書の一致するピンを足してみたらどうでしょうか。ピンで特定する証明書の範囲は全く変わりませので、中間CA証明書のピンを足すことで、ニセHTTPSサイト作りが難しくなったりはせず、セキュリティの強度も上がりません。また、運用面では、ピンの一致の配慮がピン一つと比べて難しく、また、ウェブサイトオーナーだけで管理できない範囲となるので証明書やピンヘッダ変更の運用は格段に複雑で面倒になります。これに対し、ルート証明書のピンを加えた場合でも全く同じことです。セキュリティ強度は上がらず、移行の運用は複雑になるのです。
    hpkp-multipin

    従って、証明書チェーン中で複数のピンをつけても意味がなく、かえって運用が複雑になるだけなので、止めたほうがよいということが言えます。

    4.7. 同じCA証明書にPinし続ける場合の課題

    今後当面は、同じルート認証局、中間認証局から発行してもらう場合に、その認証局の証明書の公開鍵にPinすることができます。その場合には、バックアップPinは、認証局から移行先のPinを教えてもらえるわけではないので、なんでも適当な値で良いことになります。公開鍵のハッシュである必要もなく、32バイトの値のBase64表現であれば(衝突しなければ)何でも良いことになります。

    ただし、「当面は」と書きましたが、SSLサーバー証明書を発行する使用していた中間認証局が、次の証明書発行時にも同じ中間認証局、同じ公開鍵であるという保証がありません。以下の理由により、同じ中間CA証明書が使われない可能性があります。

    • 中間CA証明書の有効期限は、5年から10年程度です。その有効期限の半分程度から、最長でも2、3年を残して、その中間認証局からは証明書が発行されなくなり、利用者は別のCAから証明書を発行してもらうようになります。
    • 証明書の発行数枚数が多くなると、それだけ、証明書失効リスト(CRL)のサイズも大きくなりますので、一つの中間CAから発行枚数を制限して、以降の証明書発行は、新しい中間CAから発行させるケースがあります。
    • 近年、認証局の運用上の不備、サイバー攻撃などから証明書発行サービス全体や、特定の中間CAが運用停止、サービス終了になることがあります。
    このような場合には、同じ中間CAのPinを使うことができません。

    有効なPinを設定した同じルートCAもしくは中間CAから、新しい証明書が発行してもらえないとわかった際に、別の証明書の移行は、すぐにはできず、max-ageで指定した期間、一般には1ヶ月から1年程度は、証明書の入れ替えができません。最悪の場合、その期間、有効なHTTPS通信ができないという事もありえます。

    このような影響を、軽減する方法が無いわけではありません。証明書を更新すると判断し、同じ中間CAから証明書が発行できないとわかった時点Aで、そこからmax-age経過した時点Bを記録しておき、新しい証明書を取得します。(が使いません。)。バックアップPinとして、その新しい証明書の別の中間CA証明書の公開鍵のPinをウェブサーバーのヘッダに設定します。時点Bになって、初めて新しい証明書への入れ替えを実施します。この事から、max-ageを1年等、長くとれば偽サイトの防止には役立ちますが、今述べたような証明書更新のリスクもあり、半月から1ヶ月程度に設定するのが妥当なように思います。

    4.8. 2つのCA証明書にPinする場合の課題

    SSLサーバー証明書の更新の際に、2つの証明書発行サービス、例えばSymantecとGlobalSignを交互に乗り換えるとして、これら2つの中間CA証明書のPinをヘッダに設定し、使用してないない方をバックアップPinとするのは、なかなか賢い方法だと思います。
    hpkp-two

    しかしながら、前述の理由により、Symantecの次に発行してもらおうと予定していたGlobalSignの中間CA証明書のPinが使えないケースがあります。

    以上のように、CA証明書にPinを打つケースでは、証明書発行サービスの気まぐれにビクビクしながら、ウェブサーバーのHPKPを運用するのはとても面倒だと思いませんか? それなら、まだ、自分でコントロールできるSSLサーバー証明書にPinを打つ方が、面倒でも良いような気もしてきます。

    4.9. max-ageのオススメ値を考える

    RFC 7469 4.1節の セキュリティ考察において、max-ageの最大値について以下のように記載されており、 「60日がバランスの取れた値かもね」と言っています。

    RFC 7469 4.1. Maximum max-age より
    However, a value on the order of 60 days (5,184,000 seconds) may be considered a balance between the two competing security concerns.
    ただ、5章のScott Helme氏のHPKP対応ドメインリストに基づいた私の調査では、 まともな運用をしている設定の中では、 30日が26%、次いで60日が19%と多いです。

    max-ageの値が長すぎると、

    • 設定ミスによる障害発生時に長期間接続できないユーザが出てしまう
    • 有効期間のオーバーラップが必要な場合、実質的な証明書有効期間が目減りして運用コストに影響する
    というリスクについて、4.2節で説明させて頂きましたが、 逆に、max-ageが短すぎるとどうなるのでしょうか?

    簡単には、ニセのHTTPSサイトに乗っ取られる可能性が高くなるという事かと思います。 本物サイトのmax-ageが短くて、有効期限が切れたタイミングで、ドメイン乗取り等の被害にあって 偽サイトが作られ、そこで1年等長いmax-ageのHPKPヘッダ対応のニセサイトが作られたとすると、 一度そのようになれば、当面1年間は、ニセサイトにしか繋げないようなユーザが発生することがあります。
    hpkp-maxage
    max-ageが短いと、それだけ攻撃のチャンスは増えるため、max-ageはある程度長くしておく必要があります。

    様々な情報ソースから、 ニセサイトを作られていたと気づくまでに、それほど時間はかからないと思います。 数日から1週間もあれば問題に気づくと思います。 半月や1ヶ月も気づかないままいる事はないでしょう。 「ニセHTTPSサイト問題に気づくまでに遅くともどれくらいかかるか」によって max-ageの最小値を決めるのがよいと思います。

    従って、攻撃と可用性のリスクのトレードオフで、私はmax-ageを15日か30日程度に 設定するのが良いように思っています。

    5. HPKPはどの程度使われているのか

    2016年3月のNetcraft社のSSL利用調査によれば、世界でわずか0.09%の4100サイト以下ぐらいしか、HPKPを設定しておらず、設定の誤りも多いそうで、正しく設定できているのは、そのうち3000サイト程度なのだそうです。

    また、CSP(Content Security Policy)やHPKPに詳しく、HPKPの検証やレポート先サイトを運営しているScott Helme氏のブログによれば、Alexa上位100万のサイトのうちHPKPを設定しているのは、わずか375サイトであったという報告もあります。

    Scott Helme氏は、調査の際のデータも公開しており、2016年8月時点でのHPKP対応サイトのドメイン名リスト448件があったので、それをベースに2017年2月現在でもHPKPヘッダを返すサイト283件に対して少し調査してみました。

    hpkp-graph1
    まず、HPKPヘッダとして正しいフォーマットになっているか、また、仕様上PINのハッシュ値は2つ以上必要ですが、2つ以上あるかという観点で、ヘッダがどの程度正しいかを調べました。16%は設定が正しくないことがわかりました。間違っているものの中には、pin-sha256属性が無い、pin-sha256の値が不適切、pin-sha256属性が一つしかない、など様々です。例えばこんなものがありました。
    • ...
    • pin-sha256="base64+info1="; max-age=3
    hpkp-graph2
    次に、HPKPヘッダのPINのハッシュ値の個数です。一般にはPINのハッシュ値は2つで十分で、2つとなっているサイトが多く占めますが、1個しかない誤ったサイトや、3つ以上を設定しているサイトも相当数あります。15個設定しているという猛者もありました。
    hpkp-graph3
    HPKPで有効な公開鍵ハッシュの保存期間を定めているのが、max-ageの値です。RFCでは、60日を推奨しているようですが、実際には30日を設定するサイトが多いとわかります。また、テスト中なのか1日以下にしているサイトも相当数あります。短いとサイトを乗っ取られる可能性が高まりますし、長すぎると設定に失敗した場合その期間接続不能になってしまいます。1年などと設定すると、設定失敗していたら1年間接続できないユーザーが出てクレーム確実なのに恐ろしいですね。
    hpkp-graph4
    report-uriを設定すると、対応ブラウザならば、HPKPのエラーの際に指定したURLにレポートを送ることができます。Jxckさんのサイトでは設定されているそうですが、まだまだ設定しているサイトは少なそうです。
    hpkp-graph5
    HPKPヘッダの値には、includeSubDomainというプロパティをつけることができます。これをつけるとexample.comにHPKPを設定しておけば、sub1.example.comドメインに対しても適用されるようになります。
    hpkp-graph6
    HPKPヘッダとして、通常は"Public-Key-Pins"を使いますが、"Public-Key-Pins-Report-Only"を使えば、ブラウザはHPKPを検証せずに、エラーとなってもHTTPS接続は続けられるテスト用の機能があります。約10%のサイトがこのテスト用の設定を使っているとわかります。
    hpkp-graph7
    Scott Helme氏の2017年時点で接続可能なHPKP対応サイト283件のうちgTLD(com、org等)、ccTLD(de、ru、jp等)別に件数を調べてみると、comが多いのは当然でとして、実際の各TLDの登録件数に比較して顕著に多いTLDが見られました。comは1.3億、netとdeは1600万、ruは540万ドメインが登録されていますが、ドメイン登録数に比べて、比率的にru、org、deは突出して多くまた、グラフ上はその他としていますが、マイナーなccTLDの国についても、比較的HPKP設定が多い国があります。また、eduが異常に少ないのも気になりました。その他には、ar/br/cl/il/pt/nl/tn/skなど、マイナーなものが 50近くありました。

    6. 今のHPKPの何がいけなかったのか

    hpkpの発想自体は、不正発行された証明書を使った偽サイトを防ぐための仕組みとして有用であり、ChromeやFirefoxのブラウザ組み込みのプリロートピンは うまく機能しているように思えます。 その一方でHPKPヘッダを使った方式は、 かなり運用が複雑で難しく、失敗すると 2ヶ月といった、長期間、一部のユーザは接続できないという、障害が発生するリスクも高いことがわかりました。

    個人や中小のサイトで不正証明書を使ってまで偽サイトを作るメリットは見当たらず、攻撃を受ける可能性も極めて低いため、HPKPを使ってサービス障害のリスクを取ってまでHPKPを導入する必要はないと思います。

    では、一般サイト向けにHPKPの普及が進むためには、運用のしやすいサービス障害が起きにくい仕様の変更が必要だと思いますが、どうすればこれが可能になるでしょうか?

    max-ageを2ヶ月と仮定して、 HPKPヘッダで運用上の課題なのは、証明書更新の2ヶ月前に、ピンが変更になるなら設定を事前設定しなければならず、間違えに気づいてヘッダ設定を直しても、2ヶ月は通信障害が発生するということです。

    そこで、間違えに気づいた時には、すぐに設定変更が反映できたり、サーバー側で暫定的にブラウザのHPKP検証を無効化できるキルスイッチがあるとよいと思うのです。深く考察した訳ではありませんが、例えば、HPKP更新日をヘッダに記載するなどして、設定に更新があればmax-ageに関わらず更新し、無効化するなら、無効化するといった機能を提供すれば、運用はmax-ageや設定ミスの呪縛から解放されるように思います。

    他にもこの問題の解決方法はあるかもしれませんが、何らかの手当てをしない限り、HPKPは普及しそうにはありません。

    7. おわりに

    以上、HPKPについて、どこにピンを打つか、max-ageはどうするかなど運用面から、 いろいろ考察や整理をしてみました。 現時点では、HPKPを導入するのは時期尚早で、 運用に負担をかけ、サービス停止のリスクも高いということも ご理解いただけたのではと思います。

    これで、自分がHPKPについて前から書きたいと思っていたことを、 落ち着いて整理でき、3年越しぐらいに吐き出せました。 わかりにくかったり、理解が間違っていたらすみません。 個人的には、HPKPについては、これでわだかまりとかモヤモヤ感というは概ね 払拭されたように思います。 まぁ、「ブログなんてそんなモノよね」ってことで、、、w

    8. (参考) HPKP関連の勉強になるリンク

    Netcraft: Secure websites shun HTTP Public Key Pinning
    HPKPが流行っていないことの統計。なぜ流行らないかの解説。良記事。
    Netcraft: HTTP Public Key Pinning: You're doing it wrong!
    Netcraft社の、世の中のHPKP対応サイトの設定誤りに関する解説。良記事。
    Scott HelmeさんのHPKPブログ記事
    CSPやHSTSやHPKPなどSSL関連技術の専門家で、HPKPなどのレポート先サイト report-uri.io を 運営しているScott Helmeさんのブログ。HPKP対応サイトのドメインリストなどのデータもあります。
    Qualys Blog: Is HTTP Public Key Pinning Dead?
    Ivan Ristic氏の、「HPKPが終わっているか?」に関する議論。
    Raymii.org: HTTP Public Key Pinning Extension HPKP for Apache, NGINX and Lighttpd
    解説は充実。各サーバー毎のHPKPヘッダの設定例。
    MDN: Public Key Pinning
    MozillaによるHPKP解説。ChromeやFirefoxでのHPKP対応バージョンの記述。サーバー設定例 レポート機能は新しいChromeしか使えない事の言及など、参考になる。
    Public Key Pinningについて - Chris Palmer (原文)
    Chris PalmerによるHPKP解説。誤解もあるが、初めて証明書チェーンのどこにピンを設定するか、そのケース分けについて考察した記事。
    ぼちぼち日記:不正なSSL証明書を見破るPublic Key Pinningを試す
    joviさんによるHPKP(ドラフト)に関する詳細かつ広範な解説です。
    Jxckさんのブログ:Public Key Pinning for HTTP(HPKP) 対応と report-uri.io でのレポート収集
    Jxckさんの解説。特にreport-uriの機能を試してみた報告が貴重。
    公開鍵ピンニングによるユーザ追跡 HPKP Supercookies
    今回の記事とはあまり関係ないですが、 にしむねあさんのHPKPを使ったクッキーを使わないユーザー特定の面白い試みに関するスライド資料。
    OWASP: Certificate and Public Key Pinning
    OWASPの解説記事。無駄な情報も多い。

    9. 追記

    9.1. 追記(2017.02.26) HPKPのブラウザサポート状況

    caniuse.comサイトでは様々なブラウザの機能のサポート状況を情報提供していますが、 2017年2月時点での HPKPのブラウザサポート状況についても 記載されているので、示しておきます。Firefox、Chrome、Opera、Android版Chromeでは サポートされていますが、それ以外ではサポートされていません。
    hpkp-caniuse

    9.2. 追記(2017.02.26) smashingmagazine.comで発生したHPKP障害

    その後、HPKPについて継続して調べ物をしていたら、 smashingmagazine.comのブログで、 HPKPにより発生した接続障害についての考察が書かれていました。 ここでは、以下のように書かれていました。

    • HPKPは中間者攻撃に対して有効な機能だが
    • HPKPの設定ミスで2016年10月21日から25日にかけHTTPS接続障害が発生
    • 証明書期限切れでHPKPヘッダを更新したらエラーになった
    • すでに証明書は期限切れでロールバックはできない
    教訓として、ブログでは、
    • 金融サイトなどならば、HPKPを使う価値はあるが、単なる情報提供サイト なら、その必要もない。HPKP設定ミスによるサービス停止は、中間者攻撃よりも大きな脅威だ
    • max-ageを短くすることにより問題を緩和できる
    私もサービス提供不能の方が、大きな問題だというのは同意ですが、 前にも述べた通り、max-ageを短すぎる値に設定するのは懸命ではなく、注意が必要です。 このサイトでは、max-ageを1年としているようですが、確かにこれは長すぎます。 新しく設定されたHPKPヘッダを見てみましたが、現行のSSLサーバー証明書の他に 3つピンが設定されており、max-ageは1日に設定されており、いろいろと設定には問題がありそうです。

    最新記事
    Categories
    Archives
    記事Google検索

    本ブログ内をGoogle検索
    Twitter
    Yahoo!アクセス解析
    Travel Advisor
    QRコード
    QRコード

    • ライブドアブログ