이 글에서는 경쟁 조건이 Android 런타임 권한 시스템에 어떤 영향을 미치는지 보여드리겠습니다.
개발자라면 경쟁 조건에 대해 들어본 적이 있을 것입니다. 이는 종종 몇 초 안에 수행되는 동시 백그라운드 작업과 관련이 있습니다. 그러나 특정 경쟁 조건은 UI에 나타날 수도 있으며 무한한 시간 동안 지속될 수도 있습니다. 이 기사에서는 경쟁 조건이 Android 런타임 권한 시스템에 어떤 영향을 미치는지 보여줍니다.
먼저 기본 용어에 대한 설명이 필요합니다.
경합 조건은 여러 작업이 동시에 발생하고 순서가 결과에 영향을 미치는 경우 발생합니다. 교과서 예제는 동일한 변수를 증가시키는 두 개의 스레드입니다. 사소한 것처럼 보이지만 일반적으로 이를 올바르게 구현하려면 스레드로부터 안전한 특수 요소를 사용해야 합니다.
Time of check to time of use(TOCTTOU 또는 TOCTOU, TOCK too로 발음)는 수행된 작업에 앞서 상태 확인이 이루어지는 특정 종류의 경쟁 조건입니다. 그리고 그 상태는 검사와 실제 실행 사이의 시간에 수정됩니다. 이는 로그인 시에만 사용자 권한을 확인하는 방식으로 설명되는 경우가 많습니다. 예를 들어, 로그인하는 순간 관리자이고 그 동안 관리자 액세스 권한이 취소되더라도 로그아웃할 때까지 권한을 사용할 수 있는 경우입니다.
Android 런타임 권한 기본 사항도 요약해 보겠습니다.
Android 6.0(API 레벨 23)부터 가장 위험한 권한은 앱 설치 시 한꺼번에 부여하는 것이 아니라 런타임 시 사용자가 명시적으로 부여해야 합니다. 여기서 가장 눈에 띄는 요소는 그림 1과 같이 DENY 및 ALLOW 버튼이 있는 시스템 대화상자입니다.
그림 1. 런타임 권한 대화상자
DENY 버튼을 클릭하면 onRequestPermissionsResult 콜백에서 PERMISSION_DENIED가 수신되며 이 권한에 의존하는 기능을 비활성화해야 합니다. 공식 스니펫에 따르면.
또한 사용자는 애플리케이션 설정의 앱 권한 화면을 사용하여 권한을 부여하거나 거부할 수도 있습니다. 그림 2에서 해당 화면을 볼 수 있습니다.
그림 2. 앱 권한 화면
런타임 권한 거부는 초간단 기능이고 깨질 수 있는 요소가 없다고 생각하시는 분들이 많을 것입니다. 글쎄요, 사실과 더 다를 수는 없습니다!
권한이 부여되지 않은 경우에만 대화상자가 나타납니다. 그래서 대화를 보여주기 직전에 점검의 시간을 갖게 됩니다. 그리고 사용시간 DENY 버튼을 클릭했을 때. 그 사이의 기간은 영원히 지속될 수 있습니다. 사용자는 대화 상자를 연 다음 홈 또는 최근 버튼을 눌러 앱이 있는 작업을 백그라운드로 이동하고 나중에 언제든지 돌아올 수 있습니다.
런타임 권한 대화 상자가 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과 같습니다.
그림 3. 캡처된 TOCTTOU
결과가 달라지는 것을 볼 수 있습니다. onRequestPermissionsResult 인수가 유효하지 않습니다. 따라서 DENY 버튼은 아무것도 거부하지 않습니다! 단순히 권한 상태에 대해 아무 작업도 수행하지 않고 거부된 결과를 앱에 반환합니다.
코드의 다양한 사항을 확인할 때 타이밍을 고려하는 것이 중요합니다. 검사 결과를 캐싱하면 버그나 이상한 효과가 발생할 수 있습니다. TOCTTOU 취약점은 플랫폼이나 프로그래밍 언어에 의존하지 않으므로 CWE-367로 분류되었습니다.
전체 소스코드는 GitHub에서 확인하실 수 있습니다.
프로젝트에는 문제를 보여주는 자동화된 UI 테스트도 포함되어 있습니다.
원본은 2017년 12월 14일 www.thedroidsonroids.com에 게시되었습니다.
위 내용은 명심해야 할 극단적인 경우. Android UI의 사용 시간 경쟁 조건에 대한 확인 시간의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!