注目の記事

[iOS 9] iOS 9 で追加された App Transport Security の概要

2015.08.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

iOS 9 で追加された「App Transport Security」について調べてみましたのでご紹介します。

目次

App Transport Security とは

App Transport Security (以降、ATS と呼びます) は iOS 9.0 または OS X 10.11 以上で有効な機能であり、アプリとウェブサービスとの間のセキュアな接続のために利用できます。

ATS が有効の場合、HTTP での通信はできません。また、Apple が推奨する必要条件を満たさない接続は強制的に接続失敗扱いになります。例えば、Apple 推奨の要件を満たさない Web ページを WKWebView で開こうとした場合、ページのロードは失敗します。その時の NSError の内容は以下のようになります。

Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={_WKRecoveryAttempterErrorKey=, NSErrorFailingURLStringKey=http://www.hoge.jp/, NSErrorFailingURLKey=http://www.hoge.jp/, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.}

Info.plist に特定のキーと値を追加すれば、ATS を無効にしたり一部の動作を変更したりすることができます。

App Transport Security の基本動作

iOS 9, OS X 10.11 以上向けのビルドの場合、すべての接続は基本的に ATS の動作に従うことになります。必要条件を満たさない接続は接続失敗となります。

  • 必要条件:
  • TLS バージョン 1.2 以上
  • 接続時に使用できる暗号スイート (暗号アルゴリズムの組み合わせ) は以下のものに制限される
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • サーバ証明書に求められる条件
  • SHA256 以上のフィンガープリント
  • 2048 ビット以上の RSA キー、もしくは 256 ビット以上の Elliptic-Curve (ECC) キー
  • 無効な証明書を使用した場合は強制的に失敗になり、接続できない

Info.plist に例外を設定

Info.plist にキーと値を追加することで ATS の基本動作の例外を設定したり、ATS をオフにしたりできます。

Info.plist 用のキー

  • NSAppTransportSecurity (Dictionary)
  • NSExceptionDomains (Dictionary)
  • NSAllowsArbitraryLoads (Bool)
  • <domain-name-for-exception-as-string> (Dictionary)
  • NSExceptionMinimumTLSVersion (String)
  • NSExceptionRequiresForwardSecrecy (Bool)
  • NSExceptionAllowsInsecureHTTPLoads (Bool)
  • NSRequiresCertificateTransparency (Bool)
  • NSIncludesSubdomains (Bool)
  • NSThirdPartyExceptionMinimumTLSVersion (String)
  • NSThirdPartyExceptionRequiresForwardSecrecy (Bool)
  • NSThirdPartyExceptionAllowsInsecureHTTPLoads (Bool)

NSAppTransportSecurity (Dictionary)

  • アプリの Info.plist ファイルのトップレベルに追加するキー
  • デフォルトの動作に対してオーバーライドしたい内容を含むディクショナリ

NSExceptionDomains (Dictionary)

  • 特定のドメインに対する例外を記載するディクショナリ

NSAllowsArbitraryLoads (Bool)

  • すべてのドメインに対して ATS を無効にできる
  • NSExceptionDomains 辞書に記載している特定のドメインは、そこに記載の内容が適用される
  • デフォルト値は NO
  • すべての接続が、ATS の動作の対象となる

<domain-name-for-exception-as-string> (Dictionary)

  • キーに「www.apple.com」のようなドメイン名を使用する
  • 特定のドメインに対する例外を記載する

ドメイン名の辞書の中に格納できる項目

  • NSExceptionMinimumTLSVersion (String)
  • 接続時に使用する、ミニマムの TLS version を記載
  • 使用できる文字列 (デフォルトは TLSv1.2)
  • TLSv1.0
  • TLSv1.1
  • TLSv1.2
  • NSExceptionRequiresForwardSecrecy (Bool)
  • デフォルト値は YES
  • 値が YES の場合は、使用できる暗号スイート (暗号アルゴリズムの組み合わせ) が「Default Behavior」セクションで紹介した暗号スイートに制限される
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • 値を NO にすると、以下の暗号スイートも受け入れられるようになる
  • TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_256_CBC_SHA
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • NSExceptionAllowsInsecureHTTPLoads (Bool)
  • HTTPS を使用する全ての接続に関する項目
  • 値を YES にすると、セキュアでない HTTPS 接続が可能になる
  • no certificate
  • with an error for a self-signed
  • expired
  • hostname mismatch certificate.
  • デフォルト値は NO
  • NSRequiresCertificateTransparency (Bool)
  • SSL 証明書に関する項目
  • Certificate Transparency (透かし入り証明書) を要求するかどうか
  • デフォルト値は NO
  • NSIncludesSubdomains (Bool)
  • 値のオーバーライドをサブドメインにも適用するかどうか
  • デフォルト値は NO
  • NSThirdPartyExceptionMinimumTLSVersion (String)
  • 動作的には「NSExceptionMinimumTLSVersion」を指定する場合と同じ
  • セキュリティー設定を開発者側でコントロールできない場合などはこちらを使う?
  • NSThirdPartyExceptionRequiresForwardSecrecy (Bool)
  • 動作的には「NSExceptionRequiresForwardSecrecy」を指定する場合と同じ
  • セキュリティー設定を開発者側でコントロールできない場合などはこちらを使う?
  • NSThirdPartyExceptionAllowsInsecureHTTPLoads (Bool)
  • 動作的には「NSExceptionAllowsInsecureHTTPLoads」を指定する場合と同じ
  • セキュリティー設定を開発者側でコントロールできない場合などはこちらを使う?

Info.plist の設定例

iOS 9 ベータ版では、以下のキーは使用できないようです。

  • NSExceptionAllowInsecureHTTPLoads

  • NSExceptionRequiresForwardSecrecy

  • NSExceptionMinimumTLSVersion

  • NSThirdPartyExceptionAllowsInsecur

  • NSThirdPartyExceptionMinimumTLSVer

  • NSThirdPartyExceptionRequiresForwa

問題が解消されるまでは「Temporary」を付け加えた Key を使うと良いようです。

In the first beta of iOS 9, these keys are incorrect and instead you’ll need to use the following:

  • NSTemporaryExceptionAllowsInsecureHTTPLoads
  • NSTemporaryExceptionRequiresForwardSecrecy
  • NSTemporaryExceptionMinimumTLSVersion
  • NSTemporaryThirdPartyExceptionAllowsInsecureHTTPLoads
  • NSTemporaryThirdPartyExceptionMinimumTLSVersion
  • NSTemporaryThirdPartyExceptionRequiresForwardSecrecy

These keys will undoubtedly be fixed in a future seed. If you can, you should use the first set of keys above that Apple is officially supporting, though if you’re using the temporary keys, they should continue to work in future betas. Thanks to Juan Leon for bringing this to my attention — I was told the same in the labs.

WORKING WITH APPLE’S APP TRANSPORT SECURITY より引用

全ての接続に対して ATS を有効にする

  • Info.plist には何も設定しなくてよい
  • 必要なのは NSURLSession を使うことだけ

ATS を無効にする (非推奨)

NSAppTransportSecurity

NSAllowsArbitraryLoads

基本的にATS を有効にし、ATS の対象にしないドメインを Info.plist に記載する

NSAppTransportSecurity

NSExceptionDomains

insecure.example.com

NSTemporaryExceptionAllowsInsecureHTTPLoads

基本的にATS を無効にし、ATS の対象にするドメインを Info.plist に記載する

NSAppTransportSecurity

NSAllowsArbitraryLoads
NSExceptionDomains

secure.example.com

NSTemporaryExceptionAllowsInsecureHTTPLoads

ATS の要件を下げる設定を Info.plist に記載する

  • ATS のベストプラクティスに従えない場合に、条件を緩くする
NSAppTransportSecurity

NSExceptionDomains

example.com

NSTemporaryExceptionMinimumTLSVersion
TLSv1.1
NSTemporaryExceptionRequiresForwardSecrecy

SSL/TLS 暗号スイート

ATS で受け入れられる暗号化方式は「TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384」といった形式で表現されています。これは暗号スイートと呼ばれるもので、暗号アルゴリズムの組み合わせを指定したものです。

SSL/TLS では,ハンドシェイクプロトコルによってサーバとクライアントの双方が利用可能な暗号アルゴリズムを決定します.利用する暗号アルゴリズムは,鍵交換方法(RSA, DHなど),共通鍵暗号アルゴリズム(AES, RC4 など)と暗号動作モード (CBC,GCM など) ,および ハッシュ関数(MD5, SHA1 など)の組み合わで,暗号スイート (Cipher Suite) と呼ばれます.

SSL/TLS プロトコルにおいて,どの暗号スイートを使うかは通信の安全性に大きな影響を及ぼします.そのため,安全性が低い暗号スイートは使わないようにするなど,サーバおよびクライアントにおける適切な設定が必要です.

SSL/TLS 暗号スイート - シニアエンジニアの庵 より引用

TLS プロトコルの暗号スイートの基本形は以下の通りです。

TLS_[鍵交換]_WITH_[暗号化]_[ハッシュ]

鍵交換

  • ATS で使用可能な「鍵交換方法」
  • ECDHE_ECDSA
  • ECDHE_RSA
  • DHE_RSA
  • RSA

暗号化

  • ATS で使用可能な「共通鍵暗号アルゴリズムと暗号動作モードの組合わせ」
  • AES_256_GCM
  • AES_128_GCM
  • AES_256_CBC
  • AES_128_CBC

ハッシュ

  • ATS で使用可能な「ハッシュ関数のアルゴリズム」
  • SHA384
  • SHA256
  • SHA

ログ出力について

環境変数「CFNETWORK_DIAGNOSTICS」に「1」を設定すると、ATS のエラーをログファイルに出力できます。これは、Xcode の scheme editor で設定できます。

まとめ

本記事では iOS 9 で追加された「App Transport Security」の概要をご紹介しました。

今後は App Transport Security の要件を満たすのが基本になりそうです。アプリのリリース審査の条件になる可能性もあるので、しっかり対応していきたいですね。

参考ページ

公式