내보낸 구성요소에 대한 권한 기반 액세스 제어

OWASP 카테고리: MASVS-PLATFORM: 플랫폼 상호작용

개요

Android 권한은 제한된 데이터 또는 작업에 대한 액세스를 요청하기 위해 앱의 매니페스트에 선언된 문자열 식별자이며 Android 프레임워크에서 런타임에 적용됩니다.

Android 권한 수준은 권한과 관련된 잠재적인 위험을 나타냅니다.

  • 일반: 위험도가 낮은 권한이며 설치 시 자동으로 부여됩니다.
  • 위험: 민감한 사용자 데이터에 대한 액세스를 허용할 수 있는 위험성이 높은 권한으로, 런타임에 명시적인 사용자 승인이 필요합니다.
  • 서명: 권한을 선언하는 앱과 동일한 인증서로 서명된 앱에만 부여되며 일반적으로 시스템 앱 또는 동일한 개발자의 앱 간의 상호작용에 사용됩니다.

권한 기반 액세스 제어와 관련된 취약점은 앱의 구성요소 (예: 활동, 수신자, 콘텐츠 제공자 또는 서비스)가 다음 기준을 모두 충족하는 경우 발생합니다.

  • 구성요소가 Manifestandroid:permission와 연결되어 있지 않습니다.
  • 구성요소가 사용자가 이미 승인한 권한이 있는 민감한 작업을 수행합니다.
  • 구성요소를 내보냅니다.
  • 구성요소가 수동 (매니페스트 또는 코드 수준) 권한 확인을 실행하지 않습니다.

이 경우 악성 앱이 취약한 구성요소의 권한을 악용하여 취약한 앱의 권한을 악성 앱에 프록시하는 방식으로 민감한 작업을 실행할 수 있습니다.

영향

취약한 구성요소를 내보내면 민감한 리소스에 액세스하거나 민감한 작업을 실행하는 데 사용할 수 있습니다. 이러한 원치 않는 동작의 영향은 취약한 구성요소의 컨텍스트와 권한에 따라 다릅니다.

완화 조치

민감한 작업에 권한 필요

민감한 권한이 있는 구성요소를 내보낼 때는 수신되는 모든 요청에 동일한 권한을 요구합니다. Android 스튜디오 IDE에는 이 취약점을 감지하고 적절한 권한을 요구하도록 권장하는 수신기서비스의 린트 검사가 있습니다.

개발자는 다음 예와 같이 서비스를 구현할 때 Manifest 파일에서 또는 코드 수준에서 선언하여 수신 요청에 권한을 요구할 수 있습니다.

XML

<manifest ...>
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <application ...>
        <service android:name=".MyExportService"
                 android:exported="true"
                 android:permission="android.permission.READ_CONTACTS" />

        </application>
</manifest>

Kotlin

class MyExportService : Service() {

    private val binder = MyExportBinder()

    override fun onBind(intent: Intent): IBinder? {
        // Enforce calling app has the required permission
        enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.")
        // Permission is enforced, proceed with export logic
        return binder
    }

    // Inner class for your Binder implementation
    private inner class MyExportBinder : Binder() {
        // Permission is enforced, proceed with export logic
    }
}

자바

public class MyExportService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // Enforce calling app has the required permission
        enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.");

        return binder;

    }

    // Inner class for your Binder implementation
    private class MyExportBinder extends Binder {
        // Permission is enforced, proceed with export logic

    }
}

구성요소를 내보내지 않음

절대적으로 필요한 경우가 아니라면 민감한 리소스에 액세스할 수 있는 구성요소를 내보내지 마세요. Manifest 파일에서 android:exported를 구성요소의 false로 설정하면 됩니다. API 수준 31 이상에서는 이 속성이 기본적으로 false로 설정됩니다.

XML

<activity
    android:name=".MyActivity"
    android:exported="false"/>

서명 기반 권한 적용하기

개발자가 제어하거나 소유한 두 앱 간에 데이터를 공유할 때는 서명 기반 권한을 사용합니다. 이러한 권한에는 사용자 확인이 필요하지 않으며 대신 데이터에 액세스하는 앱이 동일한 서명 키를 사용하여 서명되었는지 확인합니다. 이 설정은 더 간편하고 안전한 사용자 환경을 제공합니다. 맞춤 권한을 선언하는 경우 해당 보안 가이드라인을 고려하세요.

XML

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <permission android:name="my_custom_permission_name"
                android:protectionLevel="signature" />

단일 작업 엔드포인트

관심사 분리 디자인 원칙에 따라 앱을 구현합니다. 각 엔드포인트는 특정 권한으로 소수의 특정 작업만 실행해야 합니다. 또한 이 좋은 설계 관행을 통해 개발자는 각 엔드포인트에 세분화된 권한을 적용할 수 있습니다. 예를 들어 캘린더와 연락처를 모두 제공하는 단일 엔드포인트를 만들지 마세요.

리소스