首頁> Java> java教程> 主體

Edge Cases to Keep in Mind. Part Time of Check to Time of Use Race Conditions in Android UI

WBOY
發布: 2024-08-09 09:45:02
原創
226 人瀏覽過

In this article, we’ll show how race conditions affect Android runtime permission system.

If you are a developer you’ve probably heard about race conditions. They are often associated with concurrent background operations performed in the fractions of seconds. However, certain race conditions may also appear in UI and last for the infinite time. In this article, we’ll show how race conditions affect Android runtime permission system.

Race condition & Time of check to time of use — what does it mean?

Firstly, we need to explain some basic terms.

Race conditionoccurs if multiple operations occur at the same time and their order affects the result. A textbook example is two threads incrementing the same variable. It seems to be trivial, however, usually, we need to use special, thread-safe elements to implement it properly.

Time of check to time of use(TOCTTOU or TOCTOU, pronouncedTOCK too) isa specific kind of race condition where a performed operation is preceded by state checking and that state is modified in the time between a check and actual execution. It is often illustrated by checking user privileges at the login time only. For example, if you are an administrator at the moment when you sign in and you can use your privileges until you sign out, even if your admin access is revoked in the meantime.

Android runtime permissions

Let’s also summarise Android runtime permissions basics.

Starting from Android 6.0 (API level 23) the most dangerous permissions has to be explicitly granted by a user at runtime rather than all at once on app installation time. The most noticeable element here is a system dialogue with DENY and ALLOW buttons like shown in figure 1.

Edge Cases to Keep in Mind. Part  Time of Check to Time of Use Race Conditions in Android UI
Figure 1. Runtime permission dialog

After clicking on DENY button we receive PERMISSION_DENIED in onRequestPermissionsResult callback and we shoulddisable the functionality that depends on this permission. According to the official snippet.

Additionally, user can also grant or deny permissions by usingApp permissionsscreen in application settings. You can see that screen in figure 2.

Edge Cases to Keep in Mind. Part  Time of Check to Time of Use Race Conditions in Android UI
Figure 2. App permissions screen

Edge cases are everywhere

Most of you may think that runtime permission denial is a super simple feature and there is no element which can be broken. Well, nothing could be further from the truth!

A dialogue appears only if permission is not granted. So we have thetime of checkjust before displaying a dialogue. Andtime of usewhen DENY button is clicked. A period between them can last forever - user can open a dialogue then press home or recent button to move the task with the app to background and return anytime later.

Let’s check if runtime permission dialogue is vulnerable to TOCTTOU. To do so, we can create a super simple activity which checks actual granted permissions after returning from the dialog. Note that apart from standard onRequestPermissionsResult arguments check we'll call Context#checkSelfPermission() to obtaincurrentpermission grant status. Don't forget to set targetSdkVersion to 23 or higher. The code should look like this:

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, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) val checkResultTextView = findViewById(R.id.grantResultTextView) val grantResultTextView = findViewById(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" } }
登入後複製

Now we can perform a test. To do that we need a device or AVD with Android 6.0 (API 23) or newer. Test result is shown on figure 3.

Edge Cases to Keep in Mind. Part  Time of Check to Time of Use Race Conditions in Android UI
Figure 3. Captured TOCTTOU

We can see that results differs. onRequestPermissionsResult argument is not valid. So DENY button is not denying anything! It simply does nothing with permission status but returns denied results to app.

Wrap up

It is important to keep timing into account when checking various things in the code. Caching check results may cause bugs and weird effects. TOCTTOU vulnerability does not depend on either platform or programming language so it has been classified as CWE-367.

You can check the full source code on GitHub.
The project also contains automated UI test demonstrating the issue.

Originally published at www.thedroidsonroids.com on December 14, 2017.

以上是Edge Cases to Keep in Mind. Part Time of Check to Time of Use Race Conditions in Android UI的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!