固定を使用しないAFNetworkingポリシーでのホスト名検証の無効化

固定を使用しないAFNetworkingポリシーでのホスト名検証の無効化

説明

AFNetworking 4.0.1の AFSecurityPolicy.default() とpinning mode .none は、証明書や公開鍵の固定を行いませんが、既定でシステムの信頼チェーンと要求先のホスト名を両方検証します。証明書を固定していないことだけで、脆弱な設定になるわけではありません。

このポリシーで validatesDomainName を false にすると、AFNetworkingは要求先ドメインに結び付いたSSLポリシーではなく、基本的なX.509ポリシーでサーバー証明書を評価します。固定された証明書や公開鍵もないため、信頼チェーンは有効でも、別のホスト名に発行された証明書を受け入れるおそれがあります。通信経路を制御する攻撃者は、これを利用してサーバーになりすますことができます。

AFNetworking 4.0.1では、ドメインが指定されていてホスト名検証が有効な場合、固定を使用しないポリシーでの allowInvalidCertificates = true は拒否されます。この拒否を回避するためにホスト名検証も無効にすると、任意の証明書を受け入れるおそれがあります。接続先の証明書や公開鍵を事前に正しく配布して固定すれば、そのサービスの身元を確認する手段になります。

AFNetworkingは2023年1月17日に廃止され、新しいリリースは提供されていません。保守されているネットワークライブラリやプラットフォームAPIへ移行してください。

想定される影響

  • 信頼された認証局が別のホスト名に発行した証明書を利用する中間者攻撃。
  • サーバーの応答やリクエストデータの読み取り、改ざん。
  • セッションCookie、認証トークン、個人情報など、通信中の機密情報の窃取。

対処方法

  1. default() と .none のポリシーでは validatesDomainName を true に保ち、システムの信頼チェーンと要求先ホスト名を両方検証してください。
  2. 自己署名証明書のサーバーに接続するために、固定を使用しないポリシーで allowInvalidCertificates = true とホスト名検証の無効化を組み合わせないでください。公開の信頼された証明書を使用するか、正しい接続先の証明書や公開鍵を接続前に安全に配布してください。
  3. 脅威モデル上、固定が必要な場合にのみ .certificate または .publicKey を使用してください。対象ホストを限定し、鍵の更新、バックアップ用の固定値、失敗時の接続拒否を設計してください。標準のシステム信頼とホスト名検証で要件を満たす場合、固定は必須ではありません。
  4. AFNetworkingから、URLSession の既定のサーバー信頼処理や、保守されているAlamofireへ移行してください。2026年8月30日に確認したAlamofireの安定版は5.12.0です。独自の DefaultTrustEvaluator を使う場合、接続先固有の固定がサービスの身元確認を明示的に代替する構成でなければ、validateHost: true を維持してください。
  5. リリース構成で、ホスト名の不一致、期限切れ、信頼されていない発行者の証明書がすべて拒否されることをテストしてください。

例

変更前

swift
import AFNetworking

func insecurePolicy() -> AFNetworking.AFSecurityPolicy {
    let policy = AFNetworking.AFSecurityPolicy.default()
    policy.validatesDomainName = false
    return policy
}

変更後

swift
import AFNetworking

func standardPolicy() -> AFNetworking.AFSecurityPolicy {
    let policy = AFNetworking.AFSecurityPolicy.default()
    policy.validatesDomainName = true
    return policy
}

解説:

  • 変更前: 信頼チェーンは確認しますが、証明書のホスト名を要求先と照合しません。
  • 変更後: システムの信頼チェーンとホスト名の検証を両方維持します。validatesDomainName の既定値も true であり、この代入はセキュリティ要件を明示するためのものです。

プラットフォームの既定のサーバー信頼処理へ移行する際は、不要な認証チャレンジ処理を追加しないでください。

swift
import Foundation

func standardSession() -> URLSession {
    URLSession(configuration: .default)
}

参考資料