Network Security Configurationについて - Android N
3月10日にAndroid NのPreview版がリリースされました。ようやくAndroid Mのセキュリティ回りの調査が一段落したと思っていたのに(全然調査内容ブログで書けてませんが…)もた調査の始まりですAndroid Mの時は、Runtime-Permissionという大きな機能が追加されました。現在ざっと見た感じ、NはMのような大きな変更はありませんが、それでも調査が必要な項目がいっぱいありました。皆さんマルチウインドウを色々試して盛り上がっているのを横目に、地味なセキュリティ回りの調査です。
公開されているアンドロイドアプリは脆弱性がいっぱいですが、特にHTTPS通信の証明書の検査不備はひどいもので、IPAから注意喚起が出るほどです。
宣伝になりますが、ちなみに、この脆弱性はRiskFinderでも検知ができ以下のようなメッセージが表示されます。
脆弱性が生み出される理由
さて、これらの脆弱性が生み出される理由は、何かというと、凡ミス、及び知っているか知っていないかの単純な知識不足です。
アンドロイドアプリの多くは、サーバと通信をします。ログイン等の処理があるときはhttpsを使用して通信を行います。しかしながら開発段階では、サーバの正式な証明書は用意されていません(正式なサーバ名も決まるのは、開発の最後の段階だったり、開発が終わってからだったりしますしね)。従って開発段階では、テストサーバを立てて開発を行います。テストサーバとhttps通信を行うとき、もちろんサーバー証明書が必要になりますが、パブリックCA局にお願いしてお金を払ってテストサーバ用サーバ証明書を作成するといった事にはなりません。普通自己証明書(通称オレオレ証明書)を自分で作成してサーバーに配置します。
しかしながら、クライアントから、自己証明書を持つテストサーバにアクセスした場合、正しい署名ではないということでエラーになります。この時このエラーを回避して、「とりあえず」動かすコードを書いてしまいます。
さて、開発は進み、正式なサーバーが用意されましたので、アクセス先のURLを書き換えます。このとき上記の署名のエラーを回避するコードがそのままですと、「SSLサーバ証明書検証不備」の脆弱性を持ったアプリが生み出されます。このような仕組みで、中間者攻撃が可能なアプリが大量に生産されています。
本当にたくさんのアプリが該当します。開発者の方は、一度チェックしてください
脆弱性を生み出さない仕組
話が長くなりましたが、セキュリティの世界では有名なこの話も、なかなか開発者には届きません。
またリリースコードでは削除しなければいけないと思っても削除し忘れという事も良くあります。
この脆弱性を生み出さないようにする仕組みが、Android Nで導入された、「NetWork Secutiry Config」に入っております。Network Security Config機能には、他にも機能が入っておりますが、デバック時のみ用意したCAを使うConfigring CAs for Debuggingという機能はHTTPS通信をする開発者の方にとっては知ってもらいたい機能となります。
まだ、最初のPreview版ですし、色々と今後変更はありますので、あまり深い検証はせずに、翻訳、解説していきたいと思います。
Network Security Configuration(超訳)
Adding a Security Configuration File
<?xml version="1.0" encoding="utf-8"?> ...<app ...> <meta-data android:name="android.security.net.config" android:resource="@xml/network_security_config" /> ...</app>
Customizing Trusted CAs
アプリは、プラットフォームデフォルトのCA(認証局)の代わりに、CAのカスタムセットを信頼したいことがあります。
これの一般的な理由は以下の通りです。
- カスタム認証局(企業内部CAを使用している等)を使用しているホストに接続する時
- プレインストールされているすべてのCAを信用する代わり、信頼したいCAのセットだけに制限したい時
- システムに含まれていない、信用するCAを追加したい時
デフォルトで、すべてのアプリケーションのセキュアコネクション(例:TLS,HTTPS)は、プレインストールされたシステムのCAを信頼します。またtarget API level23(Android M)以下では、デフォルト機能でユーザが追加したCAも信用します。(訳注:端末設定から、信頼できるCA証明書のインストールができる。そしてAndroid Nからはこの機能がなくなった。)
アプリケーションは、自分自身のコネクションについて、base-config(アプリ全体のカスタマイズ用)もしくはdomain-config(ドメイン毎のカスタマイズ用)を使用してカスタマイズ可能です。
Configuring a Custom CA
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config> </network-security-config>
Limiting the Set of Trusted CAs
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
Trusting Additional CAs
これはシステムまだCAを含めていないといった時や、アンドロイドシステムの要件にまだ含まれていなという原因である可能性があります。
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/extracas"/> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
Configuring CAs for Debugging
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="@raw/debug_cas"/> </trust-anchors> </debug-overrides> </network-security-config>
Opting Out of Cleartext Traffic
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config usesCleartextTraffic="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
Pinning Certificates
一般的にアプリケーションは全てのプレインストールされているルートCA証明書を信用します。
これらのルート証明書のいずれかが、不正な証明書を発行した場合、アプリケーションはMiTM(中間者攻撃)の危険があります。いくつかのアプリは、信頼するCAのセットを使用したり(訳注:AndroidNで新機能として追加)、証明書のピンニングのいずれかによって、受け入れる証明書セットを制限します。
証明書のピンニングは、公開鍵(X509証明書のSubjectPublicKeyInfo)のハッシュ値のセットを提供することで実現します。
証明書チェインのどれか一つピンニングされた公開鍵が含まれていれば有効です。証明書のピンニングを使う時バックアップキーも含むべきであることに注意してください。新しいキーに切り替える必要があるときや、CA(ルート署名、中間署名をピンニングする時)を変更する時にアプリの接続が影響を受けないようにします。そうしないと、接続を回復するために、アプリを更新する必要があります。
さらに、ピンニング有効期限を設定することができます。
これは、更新されていないアプリケーションでの接続上の問題を防ぐのに役立ちます。
しかし、ピンに有効期限を設定すると、ピンニングのバイパスを可能にすることができます。
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin> <!-- backup pin --> <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin> </domain-config> </network-security-config>
- トルコの認証局、中間CA証明書を誤発行--グーグルやMS、対応を明らかに
- Certificate and Public Key Pinning
- 不正なSSL証明書を見破るPublic Key Pinningを試す
Configuration Inheritance Behavior
res/xml/network_security_config.xml
:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </domain-config> </network-security-config>
Configuration File Format
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </base-config> <domain-config> <domain>android.com</domain> ... <trust-anchors> <certificates src="..."/> ... </trust-anchors> <pin-set> <pin digest="...">...</pin> ... </pin-set> </domain-config> ... <debug-overrides> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </debug-overrides> </network-security-config>
最後に
- ルート証明書が無条件で信用できなくなった→アプリ単位のCAカスタマイズ
- SSL証明書の検証不備→デバック用CAを使用可能
- CA局信用できないなー→Pinning
- クリアテキスト→んーなんか事件あったっけ?おまけ?