toshiki

ACMでCertificate Transparencyを無効化する話

· DevelopersIO #130

ACMで証明書のCTログ登録を無効化する手順と背景。透明性とプライバシーのトレードオフを起承転結で整理する。

  • #security
  • #tls
  • #aws
  • #acm
  • #certificate-transparency

#なぜ今日これを選んだか

セキュリティに踏み込んでいくなら、TLS周りで「常識として知られているが、その裏に必ずトレードオフがある」テーマこそ拾っておきたい。Certificate Transparency(以下CT)は「全部透明にすれば安全」という綺麗な絵に見えて、実務では「透明であること自体が情報漏洩」になる現場がある。Rustや組込みに進んでも、自前のサーバーや管理画面でTLS証明書を発行する場面は必ず出てくる。今のうちに、CTを「使う/使わない」を判断するための材料を頭に入れておく。

#CTとは何か、なぜ生まれたか

Certificate Transparencyは、ブラウザが信頼するTLS証明書の発行履歴を 公開ログ(CTログ) に書き込み、第三者が常時監査できるようにする仕組みだ。背景には、過去に認証局(CA)が侵害されたり誤発行を起こした事件がある。代表例は2011年のDigiNotar事件で、攻撃者が *.google.com を含む偽証明書を大量に発行し、イラン国内のユーザーが中間者攻撃にさらされた。

このとき問題になったのは「CAが偽証明書を発行しても、誰も気付けない構造」だった。CTはその穴を塞ぐために設計されている。CAが証明書を発行するとCTログサーバーに登録し、署名付きタイムスタンプ(SCT)を返してもらう。そのSCTが証明書に埋め込まれ、ブラウザは「このSCTがある=公開ログに載っている」ことを検証する。Chromeは2018年4月以降、すべての公的TLS証明書にSCTを必須化した。CTのおかげで、ドメイン所有者は crt.sh のような検索サービスで「自分のドメインに対して、いつ、どのCAが、どんな証明書を発行したか」をリアルタイムに監視できるようになった。

#それでも「公開したくない」ケースがある

ところが現場に出ると、CTの透明性そのものが攻撃面になる場面が必ず出てくる。

代表的なのは 未公開のサブドメインがCTログ経由で攻撃者に発見されるケース。例えば社内システム internal-admin.example.com や、リリース前の新サービス next-product.example.com を立てるためにACMで証明書を発行した瞬間、CTログにそのFQDNが書き込まれる。攻撃者は crt.sh をスクレイピングするだけで、世界中の組織の「いま立ち上がりつつある資産」を発見し、ステージング環境への直撃や、ブランド情報のスクープを狙える。バグバウンティの偵察フェーズでは定番の手口だ。

AWS ACMはこれに対応していて、証明書発行時の CertificateTransparencyLoggingPreferenceDISABLED にすれば、CTログへの登録をスキップして証明書を発行できる。

aws acm request-certificate \
  --domain-name internal.example.com \
  --validation-method DNS \
  --options CertificateTransparencyLoggingPreference=DISABLED

既存の証明書も update-certificate-options で切り替え可能。コマンド1個で済むのは便利だが、この「便利さ」の裏に、次に書くトレードオフが隠れている。

#無効化したら何が壊れるか

CTを無効化した証明書には、決定的な制約がある。**主要ブラウザ(Chrome / Edge / Safariなど)は、SCTのない公的証明書を信頼しない。**Chromeでは NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED が出てページに辿り着けない。つまり、CT無効化は「人間がブラウザでアクセスする用途」では基本的に使えない。

ではどこで使えるかというと、Botや内部APIなど、SCTを検証しないクライアントだけが叩く経路に限られる。社内VPN越しの管理APIや、サーバー間通信で叩くだけのエンドポイントなら、SCT検証を行わないクライアントを選べば成立する。あるいは社内ブラウザに対してEnterprise Policyで「このドメインだけCT検証をスキップ」と配るパターン。いずれにしても「人間のブラウザはターゲットにしない」という強い設計判断とセットで初めて使える機能だ。

さらに地味に効いてくるのが、過去にCTログへ書き込まれた情報は消せないという点。一度ACMがログ登録モードで証明書を発行してしまったら、そのドメイン名は永遠にパブリックログに残る。後から「やっぱりCT無効化に切り替える」では遅い。最初の発行時点で意思決定する必要がある。これは「あとで直せばいい」が通用しない、運用上のクセが強いポイント。

#自分ならどう判断するか

整理すると、CT無効化は「セキュリティを上げる」ものでも「下げる」ものでもなく、漏洩面の取捨選択だ。CTを有効にすれば「偽証明書発行を検知できる」というメリットが立ち、無効にすれば「ドメイン名そのものを隠せる」というメリットが立つ。両取りはできない。

セキュリティに興味がある立場として、自分の判断軸はこうしたい:

  1. デフォルトはCT有効のまま動かす。 偽証明書発行の検知という公共財に乗っかれる利点の方が、ほとんどの場面で大きい。
  2. 無効化する候補は「人間のブラウザが触らないドメイン」だけ。 内部API、サーバー間通信、踏み台用エンドポイントなど。
  3. 「ドメイン名を隠す」は最終防衛線にしない。 CT無効化は obscurity による隠蔽であり、DNSのパッシブ収集や横スキャンで結局見つかることも多い。本命は認証・認可・ネットワーク境界の方。
  4. 新サービスの命名段階で意識する。 next-product のような将来情報が漏れる名前を、本当に証明書のCNに入れる必要があるか。ワイルドカード証明書 + 内部DNSで十分なケースも多い。

CTひとつ取っても、「透明性は良いことだ」だけで終わらせず、誰の何を守るための仕組みで、どこに歪みが出るかまで見ておく。この視点はRust + ハードウェアに進んでも、ファームウェア更新の署名検証やデバイスID管理など、まったく同じ構図で出てくると思う。今日はここまで。