인텐트 리디렉션

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

개요

인텐트 리디렉션은 공격자가 취약한 앱의 컨텍스트에서 새 구성요소를 실행하는 데 사용되는 인텐트의 콘텐츠를 부분적으로 또는 완전히 제어할 수 있을 때 발생합니다.

새 구성요소를 실행하는 데 사용되는 인텐트는 여러 방식으로 제공될 수 있습니다. 가장 일반적으로는 extras 필드에 직렬화된 인텐트로 제공되거나 문자열로 마샬링되어 파싱됩니다. 매개변수를 부분적으로 제어할 때도 동일한 결과가 발생할 수 있습니다.

영향

다양하게 영향을 미칠 수 있습니다. 공격자가 취약한 앱에서 내부 기능을 실행하거나 내보내지 않은 ContentProvider 객체와 같은 비공개 구성요소에 액세스할 수도 있습니다.

완화 조치

일반

일반적으로 중첩된 인텐트 리디렉션과 관련된 기능은 노출하지 마세요. 노출이 불가피한 경우 다음 완화 조치를 적용하세요.

  • 번들로 묶인 정보를 적절하게 정리합니다. 플래그(GRANT_URI_PERMISSIONS)를 확인 또는 삭제하고 인텐트가 리디렉션되는 위치를 확인하는 것이 중요합니다. IntentSanitizer가 이 프로세스에 도움이 될 수 있습니다.
  • PendingIntent 객체를 사용합니다. 이렇게 하면 구성요소를 내보낼 수 없으며 타겟 작업 인텐트를 변경할 수 없게 됩니다.

앱은 ResolveActivity와 같은 메서드를 사용하여 인텐트가 리디렉션되는 위치를 확인할 수 있습니다.

Kotlin

val intent = getIntent()
// Get the component name of the nested intent.
val forward = intent.getParcelableExtra<Parcelable>("key") as Intent
val name: ComponentName = forward.resolveActivity(packageManager)
// Check that the package name and class name contain the expected values.
if (name.packagename == "safe_package" && name.className == "safe_class") {
    // Redirect the nested intent.
    startActivity(forward)
}

자바

Intent intent = getIntent()
// Get the component name of the nested intent.
Intent forward = (Intent) intent.getParcelableExtra("key");
ComponentName name = forward.resolveActivity(getPackageManager());
// Check that the package name and class name contain the expected values.
if (name.getPackageName().equals("safe_package") &&
        name.getClassName().equals("safe_class")) {
    // Redirect the nested intent.
    startActivity(forward);
}

앱은 다음과 유사한 로직을 사용하여 IntentSanitizer를 활용할 수 있습니다.

Kotlin

val intent = IntentSanitizer.Builder()
     .allowComponent("com.example.ActivityA")
     .allowData("com.example")
     .allowType("text/plain")
     .build()
     .sanitizeByThrowing(intent)

Java

Intent intent = new  IntentSanitizer.Builder()
     .allowComponent("com.example.ActivityA")
     .allowData("com.example")
     .allowType("text/plain")
     .build()
     .sanitizeByThrowing(intent);

일반적인 실수

  • getCallingActivity()가 null이 아닌 값을 반환하는지 확인합니다. 악성 앱은 이 함수에 null 값을 제공할 수 있습니다.
  • checkCallingPermission()이 모든 컨텍스트에서 작동하거나, 메서드가 실제로 정수를 반환할 때 예외가 발생한다고 가정합니다.

디버깅 기능

Android 12(API 수준 31) 이상을 타겟팅하는 앱의 경우 디버깅 기능을 사용 설정할 수 있으며 경우에 따라 이 기능은 앱이 안전하지 않은 방식으로 인텐트를 실행하는지 감지하는 데 도움이 됩니다.

앱이 다음 작업을 모두 실행하면 시스템에서 안전하지 않은 인텐트 실행을 감지하고 StrictMode 위반이 발생합니다.

  • 앱은 전달된 인텐트의 추가 항목에서 중첩된 인텐트를 분리합니다.
  • 앱은 인텐트를 startActivity(), startService() 또는 bindService()로 전달하는 등 즉시 중첩된 인텐트를 사용하여 앱 구성요소를 시작합니다.

리소스