【问题标题】:AlarmManager and WakefullBroadcastReceiver how private are the passed Extras?AlarmManager 和 WakefullBroadcastReceiver 传递的 Extras 有多私密?
【发布时间】:2017-02-16 20:01:19
【问题描述】:

我正在尝试使用AlarmManager 来实现一些警报调度。因为当触发警报时,我想使用 WakefulBroadcastReceiver 启动 IntentService 来做一些后台工作。

我有一些与警报意图传递的参数的安全/隐私相关的问题。

  1. 为警报设置 PendingIntent 时,我会执行以下操作:

    Intent myIntent = new Intent(context, MyReceiver.class);        
    myIntent.putExtra("test", "testValue");
    Bundle bundle = new Bundle();
    bundle.putParcelable("bundleValue", bundleTestValue2);
    myIntent.putExtra("test3", bundle);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
        myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    

我的问题是:对于警报的 pendingIntent,设置为 Extra 的值有多私密?是否有可能被其他应用程序读取,因为它们在预定后被 Android 警报管理器使用?

  1. 通过像这样的接收器

    public class MyReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
           startWakefulService(context, MyIntentService);
    }
    

在 android 清单上

 <receiver
            android:name=".receivers.MyReceiver"
            android:exported="false"/>

 <service 
          android:name=".MyIntentService" 
          android:exported="false"/>

还有服务

public class MyIntentService extends IntentService {

  @Override
  protected void onHandleIntent(Intent intent) {

     try {
          //logic here
     } catch{
     } finaly{
          MyReceiver.completeWakefulIntent(intent);
     } 
}

从我的 Activity 中调用

sendBroadcast(new Intent(context, MyReceiver.class).putExtra(...);

从警报中安排待处理意图

Intent myIntent = new Intent(context, MyReceiver.class);        
myIntent.putExtra("test", "testValue");

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
    myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

此接收器对其他应用的暴露程度如何?它可以对除我之外的其他应用程序做出反应吗?这会引发任何可能的安全问题吗?

谢谢。

后期编辑: 由于WakefullBroadcastReceiver 似乎是保证我的服务将获得部分唤醒锁的唯一方法,我怎样才能确保 100% 没有其他应用程序会知道我的接收器,并且我的接收器不会收到任何其他呼叫,除了那些来自我的活动或来自我的集合Alarm

WakefullBroadcastReceiver 模式与 CommonsWare 的 WakefulIntentService 相比如何工作?

后期编辑: 我终于设法完成了我的实现。

  1. 如前所述,我的WakefulBroadcastReceiverIntentService 在我的Android Manifest 中都声明为exported="false",据我了解,这意味着只有我的应用程序可以访问它们。由于receiver没有导出,是不是接收到app外的广播?

  2. 设置闹钟时我使用这个PendingIntent

    Intent myIntent = new Intent(context, MyReceiver.class);
    myIntent.putExtra("databaseId", "1"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

  3. 从我的 Activity 调用时,我会这样做:

sendBroadcast(new Intent(context, MyReceiver.class).putExtra("databaseId", "1"));

这就够了吗?

【问题讨论】:

  • WakefulBroadcastReceiverWakefulIntentService 使用 BroadcastReceiverIntentService 的组合。关于您的顾虑,它们是相同的。
  • @CommonsWare 非常感谢您抽出宝贵的时间。关于WakefullBroadcastReceiver 的安全性,您有什么可以告诉我的吗?如何确保其intent 不会被其他应用读取或其他应用通过向其发送广播与其交互?
  • 您已经对这个主题有一个冗长的答案。 Vasily 的开场白很好:“总的来说,我会说将敏感数据放入 Intent 是一种不安全的做法”。此外,您不需要将敏感数据放在Intent 中,Intent 会路由回您自己的应用程序。使用一些对外人来说没有意义但能识别如何加载数据的标识符(例如,数据库表的主键)。
  • “但是我仍然担心其他应用程序是否能够向我的接收器广播” - 任何时候使用PendingIntent,都不需要导出该组件,所以第三个-party 应用程序不应访问您的接收器。任何时候您使用自己的组件之一(例如,从接收方调用startService()),都不需要导出该组件。所以,你在这里不应该有问题。如果您使用明确的Intent 调用sendBroadcast(),则广播只会发送到该接收者;使用隐式Intent,广播会发送到所有注册的侦听器。
  • “sendBroadcast 已声明意图”——我不清楚这意味着什么。显式的Intent 类似于new Intent(this, YourReceiver.class)。那只会转到YourReceiver。隐含的Intent 类似于new Intent("your.custom.action.STRING")。这适用于任何选择收听此类广播的人。对于您的用例,不要在&lt;receiver&gt; 上使用&lt;intent-filter&gt;,并为您的广播使用显式Intent。或者,不要使用sendBroadcast(),而是直接调用您的IntentService,以防警报未触发。

标签: android alarmmanager android-alarms android-broadcastreceiver


【解决方案1】:

Intent extras 相关的隐私注意事项

一般来说,我会说将敏感数据放在Intent 中是一种不安全的做法。

理论上,如果Intent 只能由特定应用程序使用(稍后讨论),那么只有该应用程序才能看到其内容。但是,考虑到大量的 Android 设备和操作系统版本(包括根设备和自定义 ROM),我不会指望它。

您没有在Intent extras 中指定要传递的敏感数据类型,因此我只能给出以下一般性建议:

  1. 确保您了解相关数据的“机密级别”:它是机密的,还是只是受限制的?或者,它是公开的(在这种情况下不需要保护)?
  2. 尝试寻找另一种不涉及在Intent 中传递敏感数据的方法(我自己从未遇到过这种需求)。
  3. 如果您绝对必须在 Intent extras 中传递敏感数据 - 请考虑对其进行加密。加密模型应该足以满足数据的“机密级别”,以及如果该数据被拦截可能造成的潜在危害(它可以一直上升到“服务器端”加密)。

BroadcastReceiver 相关的隐私/安全注意事项

一般来说,BroadcastReceiver 是一个接收“系统范围”广播的组件。广播是“系统范围的”这一事实本身就应该说明与之相关的隐私级别。

话虽如此,开发人员可以通过一种机制来限制广播的范围:自定义权限。使用自定义权限允许对广播进行两个“控制级别”:

  1. 如果广播需要特定权限,那么只有BroadcastReceiver 拥有该权限,它才会接收广播。
  2. 如果BroadcastReceiver 按特定权限过滤传入的广播,则只有带有该权限的广播才会被传送到该接收者。

虽然上述几点乍一看似乎相似,但它们是可以单独使用或组合使用的不同方案。第一个方案将广播与权限相关联(并且该广播的发送者自己不一定拥有该权限),而第二个方案通过特定权限过滤所有广播(并且接收者必须具有该权限)。

适合您的情况的更好方法

编辑:如果“wakefullness”不是要求的一部分,这可能是一个更好的方法。但它是。由于无法保证由AlarmManager 启动的Service 将有机会获得唤醒锁——这种方法不适合OP 的情况。

请注意,广播和自定义权限的设计是为了在应用程序级别引入“解耦” - 该方案允许发送方应用程序完全不知道接收方应用程序,只要它们同意一个自定义权限(嗯,预安装的公共权限也采用相同的方案,但您不希望使用公共权限来保护您的敏感数据)。

但是,在您的情况下,发送者和接收者是同一个应用程序。在这种情况下,您实际上并不需要与广播相关的所有麻烦 - 只需在您的应用程序中构建启动所需的 ServicePendingIntent,您就可以立即获得所有内容:

  • PendingIntent 和关联的Intent 在您的应用程序中启动一个特定的Service(按名称),因此没有其他应用程序可以拦截它(理论上,请记住上面的讨论)。
  • 目标Service 不能导出,因此其他应用程序无法以任何方式访问它。

欢迎你:)

【讨论】:

  • 好吧@Vasiliy 哇。如此出人意料的详细回答。我知道这个系统广播的广泛可用性,这就是我问这个问题的原因。在我的应用程序中,我有一项服务需要与我使用过的活动交谈LocalBroadcastReceiver,因为它不会引发安全问题。至于意图,我没有传递“私人”数据,而是切换到传递数据库 id 并在应用程序唤醒时检索该行。我使用了WakefulBroadcastReceiver,因为它似乎是一种保持唤醒锁的便捷方式。我需要在没有它的情况下处理我的 IntentService 中的唤醒,对吗?
  • @Alin,对不起 - 我被问题的安全/隐私部分拖走了,错过了“清醒”的要求。不幸的是,据我所知,无法保证由AlarmManager 启动的Service 将有机会在设备进入睡眠状态之前获得唤醒锁。因此,如果需要“wakefullness”,则必须使用BroadcastReceiver。为了不误导其他人,我将编辑答案。
  • 好吧,如果我像我的另一个问题一样:stackoverflow.com/questions/41953458/… 我确实认为该服务将有机会获得唤醒......因为这是它做的第一件事......而且因为我需要从活动或警报中调用服务,所以我需要一种机制来保持服务本身的唤醒。有意义吗?
  • @Alin,我会在另一个问题中回答。
  • 似乎我可能会被WakefullBroadcastReceiver 卡住...添加了`exported=false',防止它被外部资源调用?这会增加额外的安全性吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
相关资源
最近更新 更多