Swift NWConnectionでTLS・DTLSなしに機密情報を送信

Swift NWConnectionでTLS・DTLSなしに機密情報を送信

説明

AppleのNetwork.frameworkは、TCP、UDP、TLS、DTLSなどを直接構成する低レベルのネットワークAPIです。URL Loading SystemのApp Transport Security(ATS)は適用されないため、アプリケーション側で通信保護と接続相手の認証を正しく設定する必要があります。

Network.NWParameters.tls はTLSとTCPを、Network.NWParameters.dtls はDTLSとUDPを組み合わせます。Network.NWParameters.tcp と Network.NWParameters.udp は、それぞれTLSとDTLSを追加しません。Network.NWParameters(tls: nil, tcp: ...) や Network.NWParameters(dtls: nil, udp: ...) も、これらの保護を明示的に省略します。

機密情報を送る前に、実際のプロトコルと接続相手の認証を確認してください。送信メソッドの呼び出しだけでは、接続が成功したか、別のアプリケーション層の保護があるかは判断できません。

想定される影響

上位のアプリケーションプロトコルにも認証付き暗号化がない場合、次の問題が起こるおそれがあります。

  • ネットワーク上の第三者や中継機器による認証情報・個人情報の読み取り
  • 攻撃者による送信データの改ざん
  • サーバーや接続相手へのなりすまし
  • 別途防止策がない場合の、記録したメッセージの再送攻撃

対処方法

  1. TCPには Network.NWParameters.tls または nil ではないTLSオプションを、UDPには Network.NWParameters.dtls または nil ではないDTLSオプションを使用してください。
  2. システム既定のサーバー信頼評価を維持し、すべての証明書や接続相手を受け入れるコールバックを設定しないでください。
  3. HTTPやURLベースのリソースには、HTTPSと URLSession を使用し、ATS例外を最小限にしてください。
  4. 送る機密情報を最小限にしてください。TLS終端の先も脅威モデルに含む場合は、独立した鍵管理、一意なNonce、再送防止を備えたアプリケーション層の認証付き暗号化を追加してください。認証された通信の代わりにはなりません。
  5. リリースビルドの通信を調べ、平文データや想定外のプロトコル経路がないか確認してください。

例

変更前

swift
import Dispatch
import Foundation
import Network

func sendCredential(clientSecret: Data) {
    let connection = Network.NWConnection(
        host: "api.example.com",
        port: 443,
        using: Network.NWParameters.tcp
    )
    let queue = DispatchQueue(label: "cleartext-connection")
    connection.start(queue: queue)
    connection.send(content: clientSecret, completion: .contentProcessed { _ in })
}

変更後

swift
import Dispatch
import Foundation
import Network

func sendCredential(clientSecret: Data) {
    let connection = Network.NWConnection(
        host: "api.example.com",
        port: 443,
        using: Network.NWParameters.tls
    )
    let queue = DispatchQueue(label: "tls-connection")
    connection.start(queue: queue)
    connection.send(content: clientSecret, completion: .contentProcessed { _ in })
}

解説:

  • 変更前: ポート番号が443でも、Network.NWParameters.tcp 自体はTLSを追加しません。独立した認証付きの上位プロトコルがなければ、clientSecret は保護されません。
  • 変更後: Network.NWParameters.tls が既定のTLS/TCPスタックを構成します。サーバー信頼評価を無効にせず、実際のアプリケーションでは接続状態と送信エラーも処理してください。

参考資料