【问题标题】:Android facebook-sdk signature securityAndroid facebook-sdk 签名安全
【发布时间】:2012-04-29 13:20:07
【问题描述】:

我们一直在我们的 android 应用程序中实现 Facebook Android SDK,它需要将应用程序签名存储在 facebook 服务器上,以便可以验证从应用程序到 facebook 的调用。我们想将此系统用于我们自己的后端,以确保它仅被我们的应用程序使用,对此我有以下问题:

(相关类请参考https://github.com/facebook/facebook-android-sdk/tree/master/facebook/src/com/facebook/android

  1. 显然,要通过匹配签名来验证调用,需要将应用的签名发送到服务器。在 sdk 中,我似乎找不到这是在哪里完成的?
  2. 似乎没有使用https,对吗? (Util.java)
  3. 难道不能嗅探签名导致整个系统毫无意义吗?
  4. Facebook.java 在文件底部保存 facebook 应用程序的签名。改变这一点似乎微不足道。但是,据我了解,发送 Intent 的应用程序的签名可以通过该 Intent 解决。 Android 系统对此进行管理,因此无法伪造签名。但是,在调用 url 时,Android 系统是否可以将签名添加到协议中,使其不可变?我猜不是,这让我对上述问题感到好奇。

[编辑回复nitzan & zapl]

我想要实现的目标与 facebook sdk 要求您将签名存储在他们的服务器上的原因相同;确保对我们后端的调用是从我们的应用程序发送的,而不是其他任何东西。我们不想让机器人或其他应用程序访问我们的服务器 API。 facebook sdk 具有检查 Intent 是否来自 Facebook 应用程序的方法,这是安全的,因为 Android 系统对签名和 Intent 进行了封闭管理。解决这个问题的唯一方法是运行修改后的 Android 版本,该版本允许覆盖应用程序签名,但人们构建和运行的几率可以忽略不计。但是,运行应用程序,嗅探通过非 https 协议发送的签名并构建使用此签名和 api 调用的应用程序不是。似乎使这样的系统工作的唯一方法是使用 https,而 facebook sdk 似乎没有。

请注意,我在上面描述的 Intent 验证方法与对 facebook 服务器的 url 调用不同。 Intents 用于让设备上的 Facebook 应用程序与实现 SDK 的应用程序进行通信。 Android 系统确保与传入 Intent 一起发送的 Facebook 应用程序的签名不会被伪造,因此 Facebook 应用程序->应用程序通信系统是安全的。与这个内部系统相反,我的问题是关于向外发送 url 调用到服务器的外部系统,如果签名可以在调用中不可变地发送,这将是安全的,基本上实现与 Intent 系统相同的系统。

[编辑 2]

与我们的假设相反,事实证明应用签名很容易获取。虽然应用程序需要使用开发者私有密钥进行签名,但这不会损害 Android 上应用程序的安全性,但它显然不能用于验证服务器端的 api 调用。

这会引出更多问题:

  1. 为什么 Facebook 实施这个系统很容易被攻破?
  2. 是否有任何其他已知的实现来限制服务器 api 仅访问特定的应用程序? (混淆除外)

【问题讨论】:

  • 你到底想保护什么?
  • 嗨,nitzan,请查看我更新的问题
  • 这不安全,因为我可以修改 facebook 应用程序/api 以将任何内容返回到我想要的服务器。没有人强迫我告诉 facebook 服务器我是假的
  • @WillKru 你是怎么解决这个问题的?我面临着同样的问题/挑战,希望得到一些意见。

标签: android facebook security


【解决方案1】:
  1. 我不知道。
  2. 是的,它似乎将 fbconnect:// Uri 替换为 http://,这意味着使用此代码的连接没有加密。
  3. 我猜是的,尝试验证一下。
  4. 改变它是没有问题的,你可以反编译apks改变一些代码,如果你想把它们编译回来。你唯一不能做的就是再次签署apk(你缺少所需的密钥)。或者您可以在自己的代码中使用签名。
    您的应用程序的签名检查发生在安装时,如果您的签名不符合要求,您在清单中请求的权限将被删除。如果您更新您的 apk,新 apk 的签名将与旧的现有 apk 进行检查,如果签名不匹配,升级将失败。但是你可以卸载旧的并安装你的假的。
    如果您从您的应用发送和 Intent,则系统可能包含发件人的包裹,而您无权更改它。

而且,对服务器的整个验证点最终并不是安全问题,因为没有防弹的方法来验证应用程序。它用于使其他人更难滥用该 API,并用于跟踪谁在使用该 api。

身份验证机制要求您的 apk 中有某种密钥。但是,由于您将该 apk 发送给潜在的邪恶客户,因此您无法再控制它,并且可能会提取密钥并滥用它。您所能做的就是混淆密钥,以便更难获得它。但这最终是不可能的。


因此,假设您有一个与您的后端服务器通信的应用程序,我将您的应用程序下载到我的设备上。然后我可以从我的设备上获取.apk,反编译它并找到与您的服务器的通信是如何工作的——在创建 https 之前的明文。我还可以看到您的应用程序的签名是什么,它存储在设备上的 xml 文件和 apk 中。然后我会修改您的应用程序或创建一个新的应用程序,该应用程序使用该信息的行为与您的完全一样,只是它不是您的应用程序。用https没问题,我也可以给你发你想要的签名。

您无法阻止这种情况发生。你只能让它很难做到。

【讨论】:

  • 嗨 Zapl,这不是真的;您无法从该应用程序的反编译版本中获取原始应用程序的签名。签名是通过 Android 系统中的方法获取的,该方法又引用使用开发人员密钥创建的签名。由于反编译的用户没有此密钥,他们无法以返回原始签名的方式对应用程序进行签名。
  • 如果我无法通过反编译获得它,那么您的应用程序将无法发送它 - 设备无法获取用于创建签名的私钥,因此无法发送你那个。解压一个签名的 apk 文件并查看 META-INF 那里有您将发送到您的服务器的密钥。
  • META-INF 文件夹中有 3 个文件,它们似乎为每个资产定义了 SHA1-Digest 哈希值。我在哪里可以找到应用程序签名?
  • 各种。 SHA1-Digests 是使用您的私钥生成的文件的签名哈希,CERT.RSA 是您的公钥。验证过程类似于:您使用公钥解密散列并将原始散列与您生成的文件的散列进行比较,您可以验证文件来自您不知道您的私钥的方式。
  • Bwt,我明白你所说的私钥,显然使用开发者密钥创建的签名存储在 apk 中。就像我说的那样,您不能以开发人员所做的那样对反编译的 apk 进行签名,因为您没有开发人员密钥,但在这种特殊情况下,您确实只需要原始应用程序的签名即可将其用于 api 调用。所以是的,如果有人能够通过反编译找到签名,这个系统就会受到损害。
【解决方案2】:

要验证在不受信任的设备上运行的应用,服务器必须执行一些操作,例如要求来自应用的通信使用只有应用拥有的密钥进行数字签名。

应用程序作者必须在应用程序中隐藏密钥,以使其相对难以提取以用于冒名顶替者。但不能让它无法提取。

拥有应用程序提取密钥的冒名顶替者不应仅凭这一点就能够伪装成任意用户,但它可以允许具有真实密码的真实用户(有意或无意地)从伪装版本登录的应用程序。请注意,对于旨在简单地从不知情的用户那里窃取密码的假冒应用程序而言,实际上能够登录服务器可能不是必需的。

SSL 对保护应用程序本身的价值不大,因为应用程序可以安装在 SSL 损坏的平台上,或修补以破坏内部 SSL 实现以完成拦截。但是,有效的 SSL 可以帮助保护未受损设备上的应用用户。

【讨论】:

  • 在 android-facebook-sdk 之后,这个“只有应用程序拥有的密钥”将是应用程序签名。然而,正如 zapl 指出的那样,这个签名似乎是通过反编译暴露出来的。请注意,我们并没有试图保护应用程序,而是希望限制服务器 api 仅访问我们的应用程序。
  • 如果你的意思是jarsigner的结果,反编译几乎不需要,任何zipfile工具都可以。这很愚蠢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
相关资源
最近更新 更多