寄付窓口はこちら

【Apple iOS ATS】一部サイトではPV減も。NSAllowsArbitraryLoads とその InWebContent は違う件。

NSAllowsArbitraryLoadsInWebContent の挙動が予想外な件について(2016/12/13 13:26 最新のiOS10.2について追記あり)

お知らせ

App Transport Securityについて、こちらの勉強会でたっぷりお話しいたます。ご参加いただけますと幸いです。

nsstudy.connpass.com

いよいよApp Transport Security(ATS)必須化目前!

iOSアプリからのHTTP通信をブロックするセキュリティ機能、ATSの利用が、2016年の終わりからAppStoreへ提出されるアプリに必須化されます。

一時期、これによってHTTPサイトはアプリからのアクセスが激減する、とも言われました。しかし、Webブラウジング機能をもつアプリ向けに、WebViewについてはHTTP接続を許可するというオプションが提供されるため、多くのWebサイトは引き続きアプリからアクセスできるはずです。が、そうでない場合もありますという話です。

一部アプリが NSAllowsArbitraryLoadsInWebContent を採用開始。表示できないサイトが出ている。

2016/12/12 現在、WebViewのHTTP接続を許可するオプションである NSAllowsArbitraryLoadsInWebContentTwitterアプリが実際に採用したようですが、URLを開こうとした時にSSLエラーで表示できないケースが出ているようです。(追記: 2016/12/14リリースの6.68.1では改善されています。NSAllowsArbitraryLoads になったようです)

これらが発生するのは、 NSAllowsArbitraryLoadsInWebContent を利用した場合、ATSのHTTPS通信に関する制限が有効になるためです。

大まかにATSはHTTP通信をブロックすると説明しましたが、実は、ATSには一部基準を満たさないHTTPSをブロックする機能もあります。

iOS9時代からの NSAllowsArbitraryLoads (=ATSの無効化オプション)を利用していた場合、HTTPSの基準を含めて全てのATSの機能が無効化されていました。

しかしiOS10で登場した NSAllowsArbitraryLoadsInWebContent は、WebViewにHTTP接続を許可しつつ、HTTPSの基準は維持します。

(2016/12/13 13:17 追記: これはバグです。iOS10.2からUIWebViewはHTTPSの基準も無効化されました。iOS10.0以上iOS10.2未満のUIWebViewと、iOS10.0以上のWKWebViewでは依然HTTPSの基準は有効です。)

したがって NSAllowsArbitraryLoads だったアプリが、ATS必須化に備えて NSAllowsArbitraryLoadsInWebContent に移行すると、従来接続できていたWebサイトに接続できないケースが発生します。

※アプリのSSLエラーで困っている利用者の方へ

この記事はアプリ開発者、Webサイト運営者向けの内容です。アプリでSSLエラーが発生して困っているユーザーの方は、URLをコピーしてSafariに貼り付けて開く、またはリンクを長押しして「Safariで開く」を選択できないか試してみて下さい。ATSの問題でエラーとなっている場合は、Safariを使えばWebサイトの閲覧自体は可能です。

記事の概要

  • ATSについて大まかに説明
  • NSAllowsArbitraryLoadsInWebContent の特性を説明
  • 対応方法
    • Webサイト
      • Webサイトに求められるHTTPSの基準
      • Webサイトにアクセス可能か確認する手順
    • iOSアプリ
      • 検討すべきこと
  • 進捗どうですか

ATSについて、おさらい

問題を理解するために、いったんATSについて大まかに説明します。

ATSとは

ATSはiOS9から導入されました。ATSはアプリを作成するとデフォルトで有効になっています。ATSは次の2種類の通信をブロックするアプリ単位のセキュリティ機能です。

  • HTTP通信
  • 基準を満たさない一部のHTTPS通信

ATSは盗聴が可能なHTTPや、暗号の強度が弱いHTTPS通信を遮断して、アプリのユーザーが安心して利用できる通信しか行わないようにします。

ATSを無効化する NSAllowsArbitraryLoads

しかし、Webブラウジングを必要とするアプリで http:// で始まるURLのサイトがATSにブロックされてアクセスできないと困ります。

そこで、自由な通信が必要なアプリでATSを無効化するために、iOS9で用意されていたオプションが NSAllowsArbitraryLoads です。

NSAllowsArbitraryLoads を利用すると、どんなHTTPにも、どんなHTTPSにも(不正でない限り)接続することが出来るようになります。

けれども、ATSの機能が有効か、 NSAllowsArbitraryLoads を使って全て無効化するか、2択では大雑把すぎます。そこで、iOS10になってから、より必要最低限の制限だけを部分的に解除出来るように、新しいオプションが増えました。

NSAllowsArbitraryLoadsInWebContent はその一つで、WebViewについてのみ、HTTPに接続可能にするオプションです。

NSAllowsArbitraryLoadsInWebContent の登場と、ATSの必須化のアナウンス

NSAllowsArbitraryLoadsInWebContent などの登場できめ細かなATSの制限コントロールが出来るようになるのと同時に、ATSの必須化もアナウンスされました。

どのアプリもなるべく安全に、ATSの制限解除は必要最低限にとどめることが求められます。

(予定通りならば、)2016年末から、Appleがすべてのアプリについて、AppStoreに公開される前のアプリの審査で、ATSの設定が適切かどうかチェックするようになります。

NSAllowsArbitraryLoadsInWebContent のバグ

NSAllowsArbitraryLoadsInWebContent は名前の通り、AppleがWebブラウジングを必要とするアプリのために設計したATSのオプションだと考えられます。

ATS必須化後のレビューでは、おそらくWebブラウジング機能を持ったアプリは NSAllowsArbitraryLoads の代わりに NSAllowsArbitraryLoadsInWebContent を使うように要求されるようになると思われます。

しかし、 NSAllowsArbitraryLoadsInWebContent のほうが制限が厳しくなるバグが有り、冒頭で述べた通り、一部のHTTPSのサイトへの接続がブロックされます。

NSAllowsArbitraryLoadsNSAllowsArbitraryLoadsInWebContent が違うバグ

AppleのATSについてのドキュメントを見てみます。

NSAllowsArbitraryLoads のDescriptionにはこのような記述があります。

NOTE Disabling ATS allows connection regardless of HTTP or HTTPS configuration, allows connection to servers with lower Transport Layer Security (TLS) versions, and allows connection using cipher suites that do not support perfect forward secrecy (PFS).

この記述には、 "HTTP通信を許可し、ATSの基準を満たさないHTTPSの通信も許可する" ということが書かれています。

ここで重要なのが、 "ATSの基準を満たさないHTTPSの通信も許可する" という点です。

ATSはHTTP通信をブロックするだけでなく、HTTPS通信についても、低いTLSのバージョンやPerfect Forward Secrecyをサポートしていない暗号化スイートをブロックします(Cocoa Keys - Availability of ATS for Remote and Local Connections)。

HTTP通信に加えて、これらの一部のHTTPS通信まで含めて、 NSAllowsArbitraryLoads を使うと制限がなくなり、接続できるようになります。

さて、この記述が NSAllowsArbitraryLoadsInWebContent にはありません。

では、記述がないだけなのか、機能がないのか、不安になりますが、残念なことに機能があったりなかったりします。バグです。

"NSAllowsArbitraryLoadsInWebContent" が基準を満たさないHTTPSへの接続をブロックするバグ

Appleが意図しているのかわかりませんが、実際に動作を確認した限りでは、 NSAllowsArbitraryLoadsInWebContent は、ATSの基準を満たさないHTTPSの通信をブロックするようです。

たとえば https://swift.org/HTTPSのWebサイトですが、 2016/12/12 07:57 時点で Perfect Forward Secrecy に対応していません(暗号化スイートが AES_128_GCM であるため)。

NSAllowsArbitraryLoadsInWebContent を設定したアプリのWKWebViewからhttps://swift.org/へアクセスすると、表示できません。 WKWebViewのWKNavigationDelegateの webView(_ webView:didReceive challenge:completionHandler:) を実装しても呼ばれず、OSレベルで即通信が遮断されるようです。

NSAllowsArbitraryLoads を設定したアプリのWKWebViewからは https://swift.org/ に接続できます。

InWebContent がついているかどうかの字面から、てっきり制限のレベルは同じかと思いこんでしまいますが、実は、HTTPS通信についてはこのような制限の違いがあるのです(先月まで一緒だと信じていました)。(2016/12/13 13:26追記: そしてバグだった)

2016/12/13 13:26 追記

意図していないようです。これはバグです。

iOS10.2以降のUIWebViewは、ATSの基準を満たさないHTTPSの通信を許可するようになりました。WKWebViewは、依然としてATSの基準を満たさないHTTPS通信はブロックされます。

どうしたらいいのか

Webサイト運営者とアプリ開発者がすること

バグであることがわかったので、 NSAllowsArbitraryLoadsInWebContent によって一部HTTPSに接続できないiOSは減っていくと思われます。ただし、既にリリースされたiOS10.0, 10.1、そして10.2以降もWKWebViewについては一部のHTTPSに接続できないままです。

(この問題を無視する、という選択肢もありますが、)HTTPSのWebサイト運営者は、 NSAllowsArbitraryLoadsInWebContent を設定したアプリから無事Webサイトが閲覧できるように、対策をとっておく必要があります。

アプリ開発者は NSAllowsArbitraryLoadsInWebContent を自分のアプリで利用するのが適切かどうか判断する必要があります(もちろん、適切でないと判断してさらに制限を緩める場合、審査で説得を試みてみないと許可されるかどうかは分かりません)。

Webサイト運営者: 必要な基準と、Webサイトにアクセス可能かどうか確認する方法

サイト運営者は、サイトのセキュリティレベルをATSの基準を満たす水準にしましょう。

ATSがHTTPSに求める基準について

ATSの細かい基準についてはドキュメントのこの辺りに書かれています。

Cocoa Keys - Requirements for Connecting Using ATS

確認コマンド

このようなコマンドをMacで実行することで、URLのATS対応状況を確認できます。

nscurl --ats-diagnostics https://google.com/
HTTPSで基準を満たしている場合

このような出力があれば安心です。ATSが有効でも利用できます。

Default ATS Secure Connection
---
ATS Default Connection
Result : PASS
---
HTTPSで基準を満たしていない場合

HTTPSのサイトであるにも関わらず、FAILとなる場合、 NSAllowsArbitraryLoadsInWebContent が設定されたiOS10.0以上10.2未満のUIWebViewとiOS10.0以上のWKWebViewを利用したアプリからは接続できない、安全性の低いHTTPS通信になっています。

Default ATS Secure Connection
---
ATS Default Connection
2016-12-12 20:51:33.166 nscurl[52077:19714548] CFNetwork SSLHandshake failed (-9824)
2016-12-12 20:51:33.167 nscurl[52077:19714548] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Result : FAIL
---

このとき、TLSのバージョン基準を下げたり、PFS(Perfect Forward Secrecy)の基準を下げたりしてトライした場合の結果も表示してくれるので、FAILの場合に原因がどこにあるのかも探ることが出来ます。

HTTPの場合

HTTPのサイトであれば、ATSが有効なアプリからは接続できません。

NSAllowsArbitraryLoadsInWebContent が設定されたアプリからは接続することが出来ます。

アプリ開発者は?

バグだったようなので事態は複雑です。

  • UIWebView
    • iOS10.0以上10.2未満において、 NSAllowsArbitraryLoadsInWebContent を利用するとATS基準を満たさないHTTPSに接続できない
    • iOS10.2以上において、 NSAllowsArbitraryLoadsInWebContent を利用するとすべてのHTTPとHTTPSに接続できる
  • WKWebView
    • iOS10.0以上において、 NSAllowsArbitraryLoadsInWebContent を利用するとATS基準を満たさないHTTPSに接続できない
    • 今後どのバージョンからか、 NSAllowsArbitraryLoadsInWebContent を利用するとすべてのHTTPとHTTPSに接続できるようになるはずである

アプリ開発者は、アプリの仕様として、サポートするiOSのバージョンと、安全性が十分でない(ATSの基準を満たさない)HTTPSのサイトの利用をサポートすることが必須かどうか検討する必要があります。

Appleは、おそらく NSAllowsArbitraryLoadsInWebContent を利用してほしいのではないでしょうか。 HTTPSを利用しているにも関わらず脆弱性があるサイトには接続できるべきではないと考えているかもしれません(とはいえバグである可能性もある)。 (→バグだった)

しかし、iOS10.0からどのようなWebサイトにも接続できるようにしたい場合、 NSAllowsArbitraryLoads を利用する必要があります。その場合は NSAllowsArbitraryLoadsInWebContent よりも審査の基準が難しくなるかもしれません。

バグのあるiOSバージョンではATS基準を満たさないHTTPS接続のサポートを諦めるという選択肢も考えられます。もっと諦めてSFSafariViewControllerを利用する道もあります。

デリゲートでSSLエラーを検知したら、Safariで開く選択肢を提示するような方法も考えられます。ただし、その場合メインフレームで読み込んでいるURLのATSによるSSLエラーは検知できますが、開いているサイトが外部から読み込んでいるJavaScriptなどのリソースがATSによってブロックされたことを検知することは出来ません。正しく動作しない可能性のあるWebサイトをアプリもユーザーも気づかないまま表示するおそれがあるので、是非について検討が必要です。

WebViewの利用目的がある程度限定されていて、特にこのサイトにはどうしても接続したい、というURLがある場合は、 NSAllowsArbitraryLoadsInWebContent を利用した上で、 NSExceptionDomains でそのサイトだけ接続できるような設定を利用するのがより良い手段だと思います。

バグの可能性もまだある バグだった

ドキュメントにおいて、 NSAllowsArbitraryLoadsInWebContent のDescriptionには次のように書かれています。

Set this key’s value to YES to obtain exemption from ATS policies in your app’s web views

このキーを設定するとアプリ内のWebViewがATSのポリシーの免除を受けられる、と書かれているので、HTTPS通信制限はATSのポリシーの一部ではないのか!!と突っ込みたくなります(とはいえ私は英語がわからないのでニュアンス的には文句言えない言い回しなのかもしれない)。

バグかもしれないし、バグではないのかもしれない。

2016/12/13 13:26 追記

バグでした。

↑フォーラムを見ると、バグが治るまで NSAllowsArbitraryLoads を使ってね、と書いているので、もしWKWebViewのバグが治らないままならば NSAllowsArbitraryLoads を利用しても審査で問題にならないかもしれない。

こうなって欲しいと思っていた

脆弱なHTTPSを駆逐したい気持ちもわかりますが、アプリとしてはそれでは不便な場合もあります。

ATSは、ドメイン毎に細かい条件を指定する事ができますが、これを "WebContent向けの細かい条件" のような切り口で設定できるようになったら良いのにな、と思ったのでした。

みんなでバグレポートを送ったら何か変わるかもしれない。

しかし、iOS10.1まではもう正式にリリースされてしまっているので、バグでも、改善がなされても、もうどうしようもないのですが。

ところでiOS開発者のみなさま進捗、どうですか?

TwitteriOS開発者の皆様にATS対応状況のアンケートをとってみました。まだ着手していない人も多数。案外対応は順調な方も多いようです。

f:id:niwatako:20161212202349p:plain

明日までですが投票はこちらから → にわタコ on Twitter: "ATS(App Transport Security)対応、進捗どうですか?"