首页  >  文章  >  Java  >  要记住的边缘情况。 Android UI 中的部分时间检查使用时间竞争条件

要记住的边缘情况。 Android UI 中的部分时间检查使用时间竞争条件

WBOY
WBOY原创
2024-08-09 09:45:02353浏览

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

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

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

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

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

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

Android运行时权限

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

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

Edge Cases to Keep in Mind. Part  Time of Check to Time of Use Race Conditions in Android UI
图 1. 运行时权限对话框

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

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

Edge Cases to Keep in Mind. Part  Time of Check to Time of Use Race Conditions in Android UI
图 2. 应用程序权限屏幕

边缘案例无处不在

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

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

让我们检查一下运行时权限对话是否容易受到 TOCTTOU 的攻击。为此,我们可以创建一个超级简单的活动,在从对话框返回后检查实际授予的权限。请注意,除了标准的 onRequestPermissionsResult 参数检查之外,我们还将调用 Context#checkSelfPermission() 来获取 当前 权限授予状态。不要忘记将 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 -> "granted"
        PERMISSION_DENIED -> "denied"
        else -> "unknown"
    }
}

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

Edge Cases to Keep in Mind. Part  Time of Check to Time of Use Race Conditions in Android UI
图3.捕获的TOCTTOU

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

包起来

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

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

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

以上是要记住的边缘情况。 Android UI 中的部分时间检查使用时间竞争条件的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn