在本文中,我们将展示竞争条件如何影响 android 运行时权限系统。

如果您是开发人员,您可能听说过竞争条件。它们通常与在几分之一秒内执行的并发后台操作相关。然而,某些竞争条件也可能出现在 ui 中并持续无限时间。在本文中,我们将展示竞争条件如何影响 android 运行时权限系统。

竞态条件和检查时间到使用时间——这是什么意思?

首先,我们需要解释一些基本术语。

竞争条件如果同时发生多个操作并且它们的顺序影响结果,就会出现竞争条件。一个教科书的例子是两个线程递增同一个变量。这看起来很简单,但是,通常我们需要使用特殊的、线程安全的元素来正确实现它。

检查时间到使用时间(tocttou 或 toctou,也发音为tock)是一种特定类型的竞争条件,其中执行的操作之前进行状态检查,并且在检查和执行之间的时间内修改状态实际执行。通常通过仅在登录时检查用户权限来说明。例如,如果您在登录时是管理员,则可以使用您的权限直到您注销,即使您的管理员访问权限同时被撤销。

android运行时权限

我们还总结一下 android 运行时权限基础知识。

从 android 6.0(api 级别 23)开始,最危险的权限必须由用户在运行时显式授予,而不是在应用程序安装时一次性授予。这里最引人注目的元素是带有 deny 和 allow 按钮的系统对话,如图 1 所示。

图1.运行时权限对话框

点击 deny 按钮后,我们在 onrequestpermissionsresult 回调中收到 permission_denied,我们应该禁用依赖于此权限的功能。根据官方片段。

此外,用户还可以使用应用程序设置中的应用程序权限屏幕来授予或拒绝权限。您可以在图 2 中看到该屏幕。

图 2. 应用程序权限屏幕

边缘案例无处不在

大多数人可能认为运行时权限拒绝是一个超级简单的功能,没有任何元素可以被破坏。好吧,事实并非如此!

仅在未授予许可的情况下才会出现对话。所以我们在显示对话之前有检查时间。以及使用时间单击“拒绝”按钮时。它们之间的一段时间可以永远持续 - 用户可以打开一个对话,然后按主页或最近按钮将任务与应用程序移至后台,并在以后随时返回。

让我们检查一下运行时权限对话是否容易受到 tocttou 的攻击。为此,我们可以创建一个超级简单的活动,在从对话框返回后检查实际授予的权限。请注意,除了标准的 onrequestpermissionsresult 参数检查之外,我们还将调用 context#checkselfpermission() 来获取 current 权限授予状态。不要忘记将 targetsdkversion 设置为 23 或更高。代码应该如下所示:

class MainActivity : Activity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)
    requestPermissions(arrayOf(WRITE_EXTERNAL_STORAGE), 1)
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out string>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    val checkResultTextView = findViewById<textview>(R.id.grantResultTextView)
    val grantResultTextView = findViewById<textview>(R.id.checkResultTextView)

    val checkPermissionResult = checkSelfPermission(WRITE_EXTERNAL_STORAGE).toPermissionResult()
    val grantPermissionResult = grantResults.firstOrNull()?.toPermissionResult()
    checkResultTextView.text = "checkSelfPermission: $checkPermissionResult"
    grantResultTextView.text = "onRequestPermissionsResult: $grantPermissionResult"
}

private fun Int.toPermissionResult() = when (this) {
    PERMISSION_GRANTED -&gt; "granted"
    PERMISSION_DENIED -&gt; "denied"
    else -&gt; "unknown"
}

}
登录后复制

现在我们可以进行测试了。为此,我们需要配备 android 6.0 (api 23) 或更高版本的设备或 avd。测试结果如图3所示。

图3.捕获的tocttou

我们可以看到结果不同。 onrequestpermissionsresult 参数无效。所以“拒绝”按钮并不否认任何事情!它只是对权限状态不执行任何操作,而是将拒绝的结果返回给应用程序。

包起来

在检查代码中的各种内容时,考虑时间很重要。缓存检查结果可能会导致错误和奇怪的效果。 tocttou 漏洞不依赖于平台或编程语言,因此它被归类为 cwe-367。

您可以在 github 上查看完整的源代码。
该项目还包含演示该问题的自动化 ui 测试。

最初于2017年12月14日发布于www.thedroidsonroids.com。

    ?以上就是Android UI 中使用时间竞争条件检查的部分时间需要记住的边缘情况的详细内容,更多请关注php中文网其它相关文章!