GitHubのセキュリティ研究者が「mTLS認証」にまつわる誤った実装を警告:何に気を付けるべきなのか
セキュリティ研究者のマイケル・ステパンキン氏は、適切に実装されていない「mTLS認証」は認証情報が盗み出される可能性があると警告する記事をGitHubブログで公開した。
GitHubでセキュリティ研究者のマイケル・ステパンキン氏は2023年8月17日(米国時間)、相互TLS認証(mTLS)の誤った実装によるセキュリティリスクを警告する記事をGitHubの公式ブログで公開した。
TLS認証は、GmailやGitHubなどのWebサイトに接続する際、クライアントであるブラウザ側は、サーバから提供された証明書を確認し、本当に接続したいWebサイトであるかどうかを検証している。mTLS認証は、クライアントとサーバの両方が本当に正しいクライアント、サーバかどうかを相互で検証、認証する方式を指す。
ステパンキン氏は「近年、ゼロトラストネットワークにおいて、クライアント認証の手段として、mTLS認証が使用されるようになっている。X.509証明書に基づくmTLS認証は、パスワードやトークンに比べて利点があるが、複雑さも増す」と指摘する。
JavaのWebアプリケーションにおけるmTLSの利用例
JavaでmTLS認証を利用する場合、最低限必要な設定は、アプリケーションの設定でmTLSを有効にし、信頼できるルート証明書の場所を以下のように指定することだ。
$ cat application.properties … server.ssl.client-auth=need server.ssl.trust-store=/etc/spring/server-truststore.p12 server.ssl.trust-store-password=changeit
またcurlなどのクライアントから、どの証明書をサーバに送信するか指定する必要がある。
$ curl -k -v –cert client.pem http://localhost/hello
攻撃パターン1:不適切な証明書の抽出
実際のアプリケーションにおいては、開発者はしばしばTLSハンドシェイク中に提示された証明書にアクセスする必要がある。Javaにおいて、証明書にアクセスする一般的な方法は2つある。
X509Certificate[] certificates = sslSession.getPeerCertificates(); // another way X509Certificate[] certificates = request.getAttribute("javax.servlet.request.X509Certificate");
ステパンキン氏は、さまざまなアプリケーションにおいてこれらのAPIをどのように使用しているか調査した。ステパンキン氏によると、以下のような正しい実装例と危険な実装例を見つけたという。
String user = certificates[0].getSubjectX500Principal().getName();
//way 2 is dangerous for (X509Certificate cert : certificates) { if (isClientCertificate(cert)) { user = cert.getSubjectX500Principal().getName(); } }
危険な実装例では、特定の条件に合致する証明書を配列内で探索していた。ステパンキン氏は「JavaのTLSライブラリは、配列内の最初の証明書のみを検証し、厳密な順序での送信を要求していないためリスクがある」とした上で、シングルサインオンソフトウェアの「Keycloak」における不適切な証明書検証(CVE-2023-2422)を例に、問題点を解説した。
Keycloakでは、配列内の全ての証明書の中から、client_idフォーム、パラメーターに一致する証明書を検索する。一致する証明書を見つけた場合、TLSハンドシェイク中に検証されている証明書だとして信頼する。
X509Certificate[] certs = null; ClientModel client = null; try { certs = provider.getCertificateChain(context.getHttpRequest()); String client_id = null; ... if (formData != null) { client_id = formData.getFirst(OAuth2Constants.CLIENT_ID); } … matchedCertificate = Arrays.stream(certs) .map(certificate -> certificate.getSubjectDN().getName()) .filter(subjectdn -> subjectDNPattern.matcher(subjectdn).matches()) .findFirst();
ステパンキン氏は「クライアントは必要なだけ証明書を送信可能であり、サーバは最初の証明書のみを検証するため、攻撃者は、一連の動作を悪用し、別のユーザー名で認証する可能性がある」と指摘した。その上で対策方法として、配列の最初にある証明書のみを使用すべきとした。
攻撃パターン2:インジェクション攻撃
大規模なシステムの場合、サーバが全てのルート証明書と中間証明書をローカルに保存せず、外部のストレージやデータベースを使用しているケースがある。この場合、証明書の拡張子を悪用したSSRF(Server Side Request Forgery)攻撃を起こされるリスクがあるという。また証明書の拡張仕様であるAIA(Authority Information Access)を利用している場合、証明書に含まれる「Subject」「Issuer」「Serial」などの情報を利用したインジェクション攻撃が起きるリスクもあるとする。
ステパンキン氏は対策方法として、外部のストレージやデータベースを使用する際には、証明書に記載されている証明書情報の各値は信頼できないものとして扱い、適切にバリデーションやエスケープ処理をすべきとした。
攻撃パターン3:証明書の失効チェックにおけるSSRF攻撃とRCE
証明書が失効した(または無効化させる必要が生じた)場合、証明書が信頼できなくなり、セキュリティ上のリスクが生じる可能性があるため、適切な失効チェックの実施が求められる。失効情報の保存場所は、アプリケーション内にハードコーディングするか、拡張子を使って証明書自体から取得できる。
ステパンキン氏は、mTLS認証をサポートし、証明書の失効チェックを支援する「Apereo CAS」での認証情報の漏えい(CVE-2023-28857)を例に挙げ、「証明書が提供する失効情報のURLをアプリケーションが直接使用することは危険であり、攻撃者はそのURLを操作してSSRF攻撃やRCE(リモートコード実行)を試みる可能性がある」と警告している。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
PayPal、可用性の高いキーバリューストア「JunoDB」をオープンソースで公開
PayPalは、可用性の高いキーバリューストア「JunoDB」を公開した。JunoDBの最優先事項はセキュリティで、TLSのサポートとペイロードの暗号化により、ワイヤ上と静止状態の両方でデータを保護する。Azureへのサインインはもう不要! Azure仮想マシンへの安全な接続を実現するAzure Bastionの「共有可能なリンク」が一般提供開始
Microsoftは「Azure Bastion」の「Standard」プランで、新機能「共有可能(な)リンク」の一般提供を開始しました。この機能を利用すると、Azure仮想マシンにパブリックIPを割り当て、ポートを許可せず、また、Azureサブスクリプションへのアクセス許可を全く与えずに、Azure仮想マシンへの安全な接続を提供できます。IEモードはどうなる? IE 11のTLS 1.0/1.1が「2022年9月下旬」から既定で無効化、その影響は?
Microsoftは数年前から同社のWebサイトやサービス、ブラウザなどについて、脆弱(ぜいじゃく)性問題のある「Transport Layer Security(TLS)1.0および1.1」の利用を廃止し、より安全なプロトコルであるTLS 1.2以降への移行を進めてきました。IE 11については当初2020年中に既定での無効化が予定されていましたが、延期を繰り返してきました。いよいよ、2022年9月20日以降に無効化が実施されます。