電通総研 テックブログ

電通総研が運営する技術ブログ

自己署名証明書を調べてSNIとデフォルト証明書と.invalidドメインを掘り出した

はじめに

こんにちは、クロスイノベーション本部の藤川(善)です。
最近、あるWebサイトで「自己署名証明書」の使用が検出され、調査した内容を記事にします。
結論としては不備ではなくて、IPアドレス指定で共有ホスティング環境にアクセスした際に表示される自己署名証明書は、セキュリティ目的で意図的に設定されたダミー証明書でした。普段あまり目にしないであろう.invalidトップレベルドメイン(TLD)についても本記事内で触れます。


背景

サイバーセキュリティの中にASM(Attack Surface Management)という分野があります。インターネットに公開しているWebサイトを代表とする資産は、情報窃取やコンテンツ改ざんなどを狙う攻撃者からもアクセスされてしまいますが、不正侵入経路となりうる部分を把握・管理する活動です。イメージしやすい内容としては、脆弱性がないかツールを使用して定期的にスキャンし、もし脆弱性を検出した場合は優先度などを勘案して対策を打ちます。
代表的なところでは、以下のような脆弱性を検査しています。

  • Webアプリケーションの脆弱性(XSSなど)
  • 不要なポートの公開(FTPやPOP3)
  • 脆弱なミドルウェアの利用
  • 証明書設定の不備(有効期限切れなど)

上記の「証明書設定の不備」の一環で、あるWebサイトで「自己署名証明書を使用している」という事象が検出されたのが発端でした。
しかし当該Webサイトは、正規の認証局(CA)から発行されたサーバ証明書を使用しているはずで、自己署名証明書(Self-Signed Certificate)には心当たりがありませんでした。
以前、社内メンバーのみが利用するサイトでActiveDirectoryの証明書サービスで発行したプライベートCA署名証明書を組み込んだことがあります。用途次第では正規CAが発行した証明書でなくても問題ありませんが、今回対象となっているWebサイトは社外向けですので看過しづらいです。


初期調査

ドメイン指定でアクセスした場合は問題ないという情報もありました。まずアクセス方法による違いをWebブラウザで確認したところ、以下のように挙動が異なることがわかりました。(ドメイン名・IPアドレスは架空のものです)

ドメイン指定

https://example.com/ → ✅ 問題なし(正常な証明書)Web画面も正常表示

IPアドレス指定

https://203.0.113.1:443/ → ❌ 問題あり(自己署名証明書)エラー表示「この接続ではプライバシーが保護されません」

この結果から、「サーバ全体が誤設定されているわけではない」ことが見えてきました。利用者は通常はドメイン指定でアクセスしますから、正常な証明書を取得できていると考えられます。
IPアドレスを指定してアクセスすると問題が起きます。

さてインフラ構成を確認すると、当該Webサイトは共有ホスティング環境を使用していることが判明しました。


共有ホスティングとSNI

共有ホスティングでは、1つのIPアドレスに複数のドメインを対応させて運用します。
動作しているドメインごとにサーバ証明書は異なるものが使用されます。HTTPSでのアクセスを受けると、どの証明書を返すかを識別する必要があり、SNI(Server Name Indication) という仕組みを用いています。SNIでは、TLS通信の初期段階でクライアントからClient Helloメッセージを送り、その中でどのドメインに接続するかを伝えます。
SNIによる証明書識別の動作イメージ

SNIあり / ドメイン指定でのアクセス

ドメイン指定でアクセスした場合は、SNIで接続先ドメインを識別して、対応するサーバ証明書を返します。
ドメイン指定でのアクセス

SNIなし / IPアドレス指定でのアクセス

IPアドレス指定でアクセスした場合には、SNIによりドメインを識別できないため、共有ホスティングを行っているサーバはデフォルトの証明書を返します。デフォルト証明書とは言っても、異常なアクセスをされている扱いをしており、内容としてはエラーを示すものとなります。
IPアドレス指定でのアクセス


opensslコマンドによるサーバ証明書の確認方法

実際のサーバ証明書の内容を確認してみました。Webブラウザでも概要は参照できますが、 openssl コマンドで詳細に確認できます。今回は手近なAWSのCloudShellで以下のように実行しました。

ドメイン指定

openssl s_client -connect example.com:443 -servername example.com < /dev/null |\
openssl x509 -noout -text

細かな説明は省きますがs_clientコマンドにより、実際にサーバに接続します。-servernameオプションで接続するドメイン名を提示しています(なお現在一般的なバージョンでは、-servernameオプションを省略すると-connectのドメイン名がSNIに使用されるため、同じ結果になります)。
後半のx509コマンドでは証明書のバイナリからテキスト形式でドメイン一覧(SAN;後述)を取り出しています。

IPアドレス指定

openssl s_client -connect 203.0.113.1:443 < /dev/null |\
openssl x509 -noout -text

こちらでは-servernameオプションを指定しておらず、加えて-connectもIPアドレス指定としているため、接続するドメイン名が提示されません。

出力結果のうち、今回の調査に関わる主要確認ポイントは下表のとおりです。

項目 意味
Subject (CN) 証明書の対象
Issuer (CN) 発行した認証局
SAN(Subject Alternative Name) 有効なドメイン一覧

サーバ証明書の内容比較

出力結果から主要確認ポイントを抜き出すと以下のようになりました。

ドメイン指定

Subject: CN=example.com
Issuer=(正規CA)
X509v3 Subject Alternative Name: 
  DNS:example.com

→ ✅ 正常 正規の認証局が発行した証明書、SAN(Subject Alternative Name)の中にドメインexample.comが記載されている

IPアドレス指定

Subject: CN=reject.invalid, O=Reject vhost (self-signed)
Issuer: CN=reject.invalid, O=Reject vhost (self-signed)
X509v3 Subject Alternative Name: (表示されない;SANフィールド自体が証明書に含まれていない)

→ ❌ ドメイン不一致 self-signedとあるので自己署名証明書である。SANがなくIssuerはreject.invalid


reject.invalidの正体と自己署名証明書

自己署名証明書のIssuerに表示されているreject.invalidとは何でしょうか。

.invalid:RFC 6761(元はRFC 2606)で予約されている、存在しないトップレベルドメイン。.invalid自体とサブドメインは、実在のドメイン名と衝突する心配がなく、無効であることが明確
reject:拒否

つまりこの証明書は
「正しいドメイン名でアクセスしていないため拒否する」ことを示すためのダミー証明書
です。
DNSレジストラは.invalid TLDに含まれるドメインを登録してはいけない決まりとなっています。CAに証明書の発行を依頼しても拒否されるでしょうし、ダミー証明書として共有ホスティング環境が生成した自己署名証明書を使うのは自然だと受け取りました。

余談ですが、example.comexample.netもRFC 6761に記載されています。


デフォルト証明書の考え方

なぜ正しいドメイン名を伝達していない場合にIssuer:reject.invalidのデフォルト証明書を返したのでしょうか。いずれかのドメインの証明書(当記事の例ではexample.com)を返すこともできそうに思えます。

これについては、デフォルト証明書として正規の証明書を返してしまうと、IPアドレス直接指定でも証明書が取得可能となり、証明書情報(SANなど)が外部に露出しやすくなることが懸念されます。結果として攻撃者によるスキャンや調査を誘引することになります。
一方でreject.invalidの証明書を返すことは、SNI前提の設計原則に沿っていますし、不正アクセスを明示的に拒否することで不要な情報露出を防ぐ効果があります。一見、設定ミスのようでもありますが、「正しいホスト名でアクセスしてください」というサーバからの明確な意思表示とも言え、意図的な設計だと考えられます。
なお、この挙動によって攻撃そのものが完全に防げるわけではありません。IPアドレスに対応するドメイン名は各種手法で特定可能であるため、意図的な攻撃者はドメイン名を指定してアクセスすることができます。あくまで軽減策です。


まとめ

今回の調査では以下のポイントが判明しました。

  • 共有ホスティング環境ではSNI(Server Name Indication)により、クライアントが提示したドメインに対応するサーバ証明書が返される
  • IPアドレス指定でアクセスした際は、ドメイン指定がないため拒否を示すデフォルト証明書(自己署名証明書)が返された
  • デフォルト証明書のIssuer:reject.invalidは誤設定ではなく、防御的設計と考えられる

不具合かのように見える挙動でも、実際にはセキュリティ設計上の意図であるケースがあり、背景を理解して判断することが重要だと考えさせられた調査結果でした。心当たりのない自己署名証明書について調査する際に参考にしてください。

私たちは一緒に働いてくれる仲間を募集しています!

電通総研 キャリア採用サイト

執筆:@jiffy
レビュー:@nagamatsu.yuji
Shodoで執筆されました