2016-04-06 11 views
9

デバイスにペイメントアプリケーションがあり、アプリケーションがそのアプリケーションのサービスに接続して、支払いアクティビティの開始を待機してから、onActivityResult()メソッドの結果を聞きます(アプリ内購入シナリオと同様)フィッシング攻撃を防ぐために実行時にインストールされたアプリケーションを確認する方法は?

お支払い予定のパッケージ名を設定しました。しかし、あなたが知っている、それは支払いアプリケーションが信頼されているという保証はありません。同じパッケージ名と同じaidl-serviceインプリメンテーションを持つ未知のソースから偽のアプリケーションをインストールすると、保留中のインテントとフィッシングのユーザー情報が表示されます。

私は支払いの結果をいくつかの仕組みで検証し、私のアプリケーションは偽の支払い結果からしか保護されませんが、アプリケーションのユーザーはフィッシャーアプリケーションでデータを入力します。私は私が他のアプリケーションの署名と公開鍵を確認することができ、いくつかのアプローチを知って

(この段落は、私の問題は、ペイメントアプリケーションの応答を信頼していないと言う、私の問題は、前に、それらの活性を起動決済アプリケーションを信頼されます)。 の場合Android OS 公開鍵と署名が読み取り専用であり、インストール済みのアプリケーションと一致することが保証されていれば、支払いアプリケーションの公開鍵を確認してから送信することができます。インストール時のみ一致を確認してください。

フィッシング攻撃を防止するための提案(類似または異なるアプローチ)

: 私の法人のWebサイトからアプリケーションのユーザーインストールアプリケーションの約50%(Unknown-Source)を直接更新しました。

+0

私はあなたの要件を理解しているかどうかを確認してください。私がそれをしたことを確認してください。あなたはサーバーとクライアントを持っていて、サーバーが実際にあなたのものであり、要求中にデータを送信している間にハッカーではないことを確認する必要があります。私は正しいですか? – Ram

+0

@Ramいいえ、私はサービス(aidl-implementation)によって支払いアプリケーションに接続するアプリケーションを持っています。私はそれに私のユーザーを送信する前に支払いアプリケーションを確認したい。 (実際に私のアプリケーションと支払いアプリケーションの両方がサーバーを持っていますが、私の質問はそれらを確認することではありません) –

+3

Android OSはアプリケーションをインストールする前に公開鍵の検証を保証することができますが、 "不明なソース設定を避ける"など。アプリケーションを信頼することは、慎重であってもユーザーの手に委ねられます。デバイスが侵害されると、ユーザーのデータが侵害されます。デバイスがシステムにインストールされるたびに、アプリケーションが実行ごとに検証されることは期待できません。すべてはユーザーとOSの設定に依存します。インストール後にデータプライバシーがアプリケーションの手に入ります – Ram

答えて

3

AndroidはPlayストア、Amazon App Storeからアプリがインストールされているかどうかを確認するネイティブメソッドを提供しています。しかし、他のアプリでも動作しますか?

方法を見てみましょう:

PackageManager.getInstallerPackageName(String packageName)(Documentation)

あなたのために幸い

getInstallerPackageNameは、あなたがそれをあなたの隣人、アプリのパッケージIDを養うことができることを意味文字列のパッケージ名を受け入れ、それが返してきましたそれをインストールしたパッケージ名!あなたの隣人アプリがPlayストアでインストールした場合

この例では、別名com.android.vendingを教えてくれます:

if(context.getPackageManager().getInstallerPackageName("com.untrusted.app") == 
    "com.android.vending") {       // ^^^ CHANGE ^^^ 

    //Verified; app installed directly from Play Store 
} 

アマゾンアプリストアが奇数のパッケージ名を持っています

if(context.getPackageManager().getInstallerPackageName("com.untrusted.app") == 
    "com.amazon.venezia") { 

    //Verified; app installed directly from Amazon App Store 
} 

これがすべてでなければなりませんあなたが必要とする、それが助けて欲しい!

+0

ありがとうございますが、アプリケーションのユーザーの約半数が直接インストールすると言っています。インストーラを確認することをお勧めします。私はこのアイデアを使用しますが、あなたは未知のソースを通してインストールする別のユーザーのための提案です。 –

+0

@MojtabaAsg直接インストールしないユーザの場合、 'getInstallerPackageName'は' null'を返します。ですから、 'if'式で' == null'を使うだけです。 –

+0

したがって、ステップ1に戻ると、未知のソースからインストールされたこの種のアプリケーションを検証するために、公開鍵とapplication_という署名のみがあります。 –

2

メインアプリがパッケージマネージャーapiを介して支払いアプリの署名を取得し、それを(署名のウィットリストなどで)検証するとどうなりますか?確認プロセスは、メインのアプリサーバーでも行われます。

EDIT:あなたが探しているものをその

 List<byte[]> whitelist = ... ; // load from config or something... 

     PackageManager pm = this.getPackageManager(); 
     String packageName = "payment.app.package.name"; 

     PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 
     Signature[] signatures = packageInfo.signatures; 

     for (Signature sig : signatures) { 
      InputStream input = new ByteArrayInputStream(sig.toByteArray()); 
      CertificateFactory cf = CertificateFactory.getInstance("X509"); 
      X509Certificate cert = (X509Certificate) cf.generateCertificate(input); 

      PublicKey pb = cert.getPublicKey(); 
      if (! whitelist.contains(pb.getEncoded())) { 
       throw new Exception("public key is not valid"); 
      } 
     } 
+0

悪意のあるアプリが署名を変更したり、偽の署名を追加するとどうすればそれを検出できますか? –

+0

署名には支払いアプリの公開鍵が含まれています。支払いアプリがインストールされているので、一致する秘密鍵で署名しています。秘密鍵が盗まれていないと仮定すると、悪意のあるアプリケーションの署名はあなたのホワイトリストに公開鍵を含むことができません – Daniel

+0

@Danielはコード例を表示できますか?それともJschoolのアイデアと同じ考えですか? –

2

よう 気にいらないが、アプリの署名と権限を組み合わせたものです。明確にするために、これは両方のアプリケーションを所有し、同じキーで署名することができる場合にのみ機能します。ドキュメントによれば

「署名」:要求しているアプリケーションが 許可を宣言アプリケーションと同じ証明書で署名されている場合にのみ、システム許可許可。証明書が一致すると、システムは自動的に にユーザーに通知せずに、または ユーザーの明示的な承認を求めずに許可を与えます。

これは、Android OS自体が、許可を得るために2つのアプリケーションの署名が一致しなければならないことを強制します。誰かがあなたのアプリを偽造しようとすると、許可が与えられないので、これはあなたが望むものです。彼らはあなたの秘密鍵で自分のアプリに署名することはできないので、あなたの署名を偽造する方法はありません。

許可を作成するには、決済サービスを提供するアプリケーションのためのあなたのマニフェストでは、あなたはこのようにそれを宣言する必要があります、そして、

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.myapp.paymentservice" > 

    <permission android:name="com.example.myapp.paymentservice.permission.PAYMENT" 
     android:label="@string/permission_payment_label" 
     android:description="@string/permission_payment_description" 
     android:protectionLevel="signature" /> 
    ... 

、あなたのサービスを宣言するとき、あなたは宣言android:permissionとそれを守ります:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.myapp.clientapp" > 

    <uses-permission android:name="com.example.myapp.paymentservice.permission.PAYMENT" /> 
    ... 
</manifest> 

... 
    <service android:name=".BillingService" 
     android:permission="com.example.myapp.paymentservice.permission.PAYMENT" /> 
</manifest> 

最後に、あなたがその権限を使用しているクライアントアプリケーション(複数可)に宣言する

2つのアプリケーションが同じ署名鍵で署名されている限り、OSは許可を与えます。詳細については、http://developer.android.com/guide/topics/security/permissions.html#defininghttp://developer.android.com/guide/topics/manifest/permission-element.html

+0

これは便利です。両方のアプリケーションの "所有者"(あなたが署名者です)を必要としますか? –

+0

しかし、私のアプリケーションは、私のものではない第三者アプリケーションへの信頼を求めています。 –

+0

あなたが支払いアプリケーションを所有していなかったことはわかりませんでした。その場合、パーミッションは機能しません。ごめんなさい。ダニエルのコードはあなたが探しているものかもしれません。 – Jschools

関連する問題