首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在运行时验证已安装的应用程序以防止钓鱼攻击?

如何在运行时验证已安装的应用程序以防止钓鱼攻击?
EN

Stack Overflow用户
提问于 2016-04-06 07:23:06
回答 3查看 3.6K关注 0票数 12

我的设备中有一个支付应用程序,我的应用程序连接到该应用程序的服务,以获得启动支付活动的待定意图,然后侦听onActivityResult()方法中的结果。

我为付款意向设置了包名。但你知道,这并不能保证付款申请是可信的。如果有人用相同的包名和相同的aidl服务实现通过未知的源安装假应用程序,那么它可以给我挂起的意图和钓鱼我的用户信息。

我用某种机制来验证支付结果,这样才能保证我的应用程序不受假支付结果的影响,但是我的应用程序用户在手机应用程序中输入他们的数据。(这一段说我的问题是不信任支付应用程序的响应,我的问题是在启动活动之前信任支付应用程序)

我知道一些方法,我可以检查其他应用程序签名和公钥。如果 Android OS 保证公钥和签名是只读的,并与已安装的应用程序匹配,我可以依赖它,并在向that.but发送意图之前检查支付应用程序的公钥--我想这些不是只准备好的,只有在安装时才检查匹配。

有什么建议(类似或不同的方法)来防止网络钓鱼攻击吗?

更新的:大约50%的应用程序的用户安装应用程序直接从我的公司网站(未知来源)。

EN

回答 3

Stack Overflow用户

发布于 2016-04-12 06:30:55

Android提供了一种本地方法来验证应用程序是否已从Play Store,甚至是Amazon安装。但是它在其他应用程序上工作吗?

请看一下方法:

PackageManager.getInstallerPackageName(String packageName) (Documentation)

幸运的是,getInstallerPackageName接受一个字符串包名,这意味着您可以为它提供邻居应用程序的包id,并让它返回安装它的包名!

此示例将告诉您您的邻居应用程序是否由Play Store (又名com.android.vending )安装。

代码语言:javascript
复制
if(context.getPackageManager().getInstallerPackageName("com.untrusted.app") ==
  "com.android.vending") {                          //   ^^^ CHANGE ^^^

  //Verified; app installed directly from Play Store
}

亚马逊应用商店有一个奇怪的包名:

代码语言:javascript
复制
if(context.getPackageManager().getInstallerPackageName("com.untrusted.app") ==
  "com.amazon.venezia") {

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

这应该是你所需要的一切,希望它能帮助你!

票数 6
EN

Stack Overflow用户

发布于 2016-04-15 23:58:49

您要寻找的是应用程序签名和权限的组合。为了澄清,这将只有当你拥有这两个应用程序,并可以用相同的密钥签署他们。

根据医生的说法:

“签名”:系统授予的权限,只有当请求的应用程序与声明该权限的应用程序使用相同的证书时才授予该权限。如果证书匹配,系统将自动授予权限,而不通知用户或请求用户明确批准。

这意味着Android操作系统本身强制两个应用程序的签名必须匹配,才能授予权限。这是您想要的,因为如果有人试图欺骗您的应用程序,则不会授予许可。因为他们不可能用你的私钥在他们的应用上签名,所以他们不可能伪造你的签名。

要在您的报表中为提供支付服务的应用程序创建权限,您应该如下所示:

代码语言:javascript
复制
<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保护它:

代码语言:javascript
复制
    ...
    <service android:name=".BillingService"
        android:permission="com.example.myapp.paymentservice.permission.PAYMENT" />
</manifest>

最后,在客户端应用程序中声明您使用了该权限:

代码语言:javascript
复制
<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>

只要这两个应用程序使用相同的签名密钥签名,操作系统就会授予该权限。有关更多信息,请访问http://developer.android.com/guide/topics/security/permissions.html#defininghttp://developer.android.com/guide/topics/manifest/permission-element.html

票数 4
EN

Stack Overflow用户

发布于 2016-04-14 16:18:32

如果主应用程序通过包管理器api获得支付应用的签名并对其进行验证(例如,通过签名的白名单),该怎么办?验证过程也可以在主应用服务器上进行。

编辑:有些事情是这样的

代码语言:javascript
复制
        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");
            }
        }
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36444172

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档