SwiftのTrustKit設定での証明書固定の無効化

SwiftのTrustKit設定での証明書固定の無効化

説明

証明書の固定が必要なドメインで kTSKEnforcePinning: false を使うと、固定値の不一致が拒否されず、意図した追加の保護が適用されません。導入中に報告専用モードを使うことはできますが、検証後は要件に応じて固定を強制してください。固定は基本的なTLSの信頼検証とは別の制御であり、固定を強制するかどうかにかかわらず、サーバー証明書を検証する必要があります。

macOSで kTSKIgnorePinningForUserDefinedTrustAnchors が true の場合、ユーザー定義の信頼アンカーで終わる証明書チェーンには固定の検証が適用されません。この例外が組織の証明書ポリシーに合っているか確認してください。

想定される影響

  • 証明書固定の回避。
  • 固定によって拒否するはずの証明書を利用したサーバーへのなりすまし。
  • 攻撃者が通信経路と必要な証明書を確保した場合の、機密通信の漏えい。

対処方法

  1. 固定が必要なドメインの設定と配布方法を検証したうえで、kTSKEnforcePinning: true を設定してください。
  2. ネットワークdelegateのswizzlingを無効にする場合は、認証チャレンジの処理でTrustKitの TSKPinningValidator を直接呼び出してください。
  3. macOSでユーザー定義の信頼アンカーにも固定を適用する必要がある場合は、kTSKIgnorePinningForUserDefinedTrustAnchors: false を設定してください。組織のプロキシなど、意図した信頼ポリシーとの互換性も確認してください。

例

固定の強制設定を比較する部分的な例です。実際の構成では、固定値の一覧、TrustKitの初期化、ネットワークの認証チャレンジ処理との連携が必要です。

変更前

swift
let config = [
    kTSKPinnedDomains: [
        "api.example.com": [kTSKEnforcePinning: false]
    ]
]

変更後

swift
import TrustKit

private enum BuildEmbeddedPins {
    // 실제 배포에서는 빌드 시 생성한 서버 SPKI SHA-256 pin으로 교체합니다.
    static let primary = "HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY="
    static let backup = "0SDf3cRToyZJaMsoS17oF72VMavLxj/N7WBNasNuiR8="
}

func makeTrustKitConfiguration() -> [String: Any] {
    return [
        kTSKPinnedDomains: [
            "api.example.com": [
                kTSKEnforcePinning: true,
                kTSKPublicKeyHashes: [
                    BuildEmbeddedPins.primary,
                    BuildEmbeddedPins.backup
                ]
            ] as [String: Any]
        ]
    ]
}

解説:

  • 変更前: 固定への違反を強制的に拒否しません。
  • 変更後: 対象ドメインで固定を強制します。現在の鍵と、別途配布したバックアップ用のSPKI固定値を設定し、証明書の更新に備えます。例の値は実際のサーバーの固定値に置き換えてください。両方の固定値を署名済みアプリのビルドに含め、リモート入力やユーザー入力から取得しないでください。

参考資料