コンテンツにスキップ

Insecure TLS Certificate Validation

安全でないTLS証明書の検証

説明

安全でないTLS証明書の検証は、クライアントとサーバー間のセキュアな接続を確立する際の脆弱性です。TLS(Transport Layer Security)は、インターネット上でセキュアな通信を提供する暗号化プロトコルです。クライアントがTLS経由でサーバーに接続する際、サーバーのデジタル証明書を確認して身元を検証し、接続が安全であることを確認します。

安全でないTLS証明書の検証は、クライアントがサーバーの証明書を適切に検証できない場合に発生し、攻撃者がサーバーになりすまして、クライアントとサーバー間の通信を傍受または変更することを可能にします。これにより、機密情報が盗まれたり、変更されたり、公開されたりする可能性があります。

以下は、TLS証明書の検証における一般的な弱点の一部です。

  • 期限切れの証明書: 有効期限が切れた証明書は、もはや有効とは見なされません。しかし、証明書の有効期限を確認しないクライアントは、期限切れの証明書を受け入れる可能性があり、それは取り消されていたり、侵害されていたりする可能性があります。

  • 自己署名証明書: 自己署名証明書とは、証明書を発行したのと同じエンティティによって署名された証明書です。証明書の真正性を検証する独立した第三者が存在しないため、自己署名証明書を信頼するクライアントは、中間者攻撃(man-in-the-middle attack)に対して脆弱になる可能性があります。

  • ホスト名が一致しない証明書: 証明書は、特定のドメイン名またはIPアドレスに対して発行されます。クライアントが、ホスト名またはIPアドレスと一致しない証明書を持つサーバーに接続した場合、クライアントは中間者攻撃に対して脆弱になる可能性があります。

  • 信頼されていないルート証明書: ルート証明書は、証明書チェーンにおける最上位の証明書であり、チェーン内のすべての証明書の真正性を検証するために使用されます。クライアントがサーバーで使用されているルート証明書を信頼していない場合、別の信頼されていないルート証明書によって署名された不正な証明書を受け入れる可能性があります。

  • 失効した証明書: 証明書は、侵害された場合や、もはや信頼できると見なされなくなった場合に失効することがあります。証明書の失効状態を確認しないクライアントは、失効した証明書を受け入れる可能性があり、それが中間者攻撃の実行に使用される可能性があります。

import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.security.SecureRandom;

public class HttpsRequestWithoutTlsVerification {
    public static void main(String[] args) throws Exception {
        // Disable SSL/TLS verification
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() { return null; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        }};
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new SecureRandom());

        // Create connection and set SSL context
        URL url = new URL("https://example.com");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setSSLSocketFactory(sslContext.getSocketFactory());

        // Send HTTP request
        conn.setRequestMethod("GET");
        int responseCode = conn.getResponseCode();
        System.out.println("Response code: " + responseCode);
    }
}
import 'dart:io';

void main() async {
  var client = HttpClient();

  // Disable SSL certificate validation
  client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;

  // Make HTTP request
  var request = await client.getUrl(Uri.parse('https://example.com'));
  var response = await request.close();
  print('Response code: ${response.statusCode}');
  client.close();
}

推奨事項

安全でないTLS証明書の検証のリスクを軽減するためには、アプリケーションがクライアントとサーバーの両でセキュアな証明書検証メカニズムを実装することが推奨されます。これには以下が含まれます。

  • サーバーの証明書の有効性を確認し、期限切れでないこと、失効していないこと、および信頼できる認証局によって発行されていることを確認する。
  • 証明書がサーバーのドメイン名と一致することを確認するためにホスト名検証を構成し、無効なホスト名を持つ証明書を受け入れるのを防ぐ。
  • 信頼できる認証局を使用し、自己署名証明書や信頼されていないルート証明書を避ける。

さらに、アプリケーションや使用されているライブラリまたはフレームワークを最新のセキュリティパッチで最新の状態に保つこと、およびアプリケーションのセキュリティ態勢を定期的にテストして、存在する可能性のある脆弱性を特定することが重要です。

リンク

標準

  • PCI_STANDARDS:
    • REQ_2_2
    • REQ_4_2
    • REQ_6_2
    • REQ_6_3
    • REQ_6_4
    • REQ_11_3
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_6_7
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5