인텐트 리디렉션 취약점 해결

이 정보는 인텐트 리디렉션 취약점이 있는 앱의 개발자를 대상으로 합니다.

현재 상태

하나 이상의 앱에 악성 앱이 비공개 앱 구성요소나 파일에 액세스하도록 허용할 수 있는 인텐트 리디렉션 문제가 있습니다. 앱 문제를 해결하려면 아래에 안내된 자세한 단계를 확인하세요. Play Console에 표시된 기한이 지난 후에도 보안 취약점 문제가 해결되지 않은 앱은 모두 Google Play에서 삭제됩니다.

필요한 조치​

  1. Play Console에 로그인한 후 알림 섹션으로 이동하여 영향을 받는 앱과 문제 해결 기한을 확인합니다.
  2. 아래에 설명된 단계를 참고하여 영향을 받는 앱을 업데이트합니다.
  3. 영향을 받는 앱의 업데이트된 버전을 제출합니다.

제출된 앱은 다시 검토 절차를 거치게 되며 이 절차는 몇 시간 정도 걸릴 수 있습니다. 앱이 검토 과정을 통과하고 게시가 완료되면 더 이상의 조치가 필요하지 않습니다. 앱이 검토 과정을 통과하지 못할 경우 새로운 앱 버전은 게시되지 않으며 이메일 알림을 받게 됩니다.

추가 세부정보

구성요소 실행(예: startActivity 호출) 또는 데이터 반환(예: setResult 호출)을 위한 신뢰할 수 없는 인텐트 사용은 위험하며 악성 앱이 다음과 같은 문제를 일으킬 수 있습니다. 

  1. 앱에서 민감한 파일 또는 시스템 데이터(예: SMS 메시지) 도용
  2. 악성 인수를 사용하여 앱의 비공개 구성요소를 실행

앱이 신뢰할 수 없는 인텐트에서 인텐트를 검사하거나 정리하지 않은 채 startActivity, startService, sendBroadcast 또는 setResult를 호출해서는 안 됩니다.

다음 중 한 가지 방법을 통해 이러한 취약점을 방지하는 것이 좋습니다.

옵션 1: 추출된 인텐트를 리디렉션하도록 영향을 받은 앱 구성요소를 비공개로 설정합니다.

영향을 받은 앱 구성요소가 다른 앱으로부터 인텐트를 수신하지 않아도 되는 경우 매니페스트에서 android:exported=”false”로 설정하여 앱 구성요소를 비공개로 설정할 수 있습니다.

옵션 2: 추출된 인텐트의 출처가 신뢰할 수 있는 곳인지 확인합니다.

getCallingActivity와 같은 메서드를 사용하여 원래 활동을 신뢰할 수 있는지 확인하세요. 예:

 // 원래 활동의 출처가 신뢰할 수 있는 패키지인지 확인
 if (getCallingActivity().getPackageName().equals(“known”)) {
   Intent intent = getIntent();
   // 중첩된 인텐트 추출
   Intent forward = (Intent) intent.getParcelableExtra(“key”);
   // 중첩된 인텐트 리디렉션
   startActivity(forward);
 }

참고:

  • getCallingActivity()가 null이 아닌 값을 반환하는지 확인하는 작업만으로는 취약점을 완전히 방지하기에 충분하지 않습니다. 악성 앱은 이 함수에 null 값을 제공할 수 있습니다.
  • Google Play 서비스 SMS Retriever Auth의 경우 SEND_PERMISSION으로 broadcast receiver를 보호하면 인텐트의 출처가 Play 서비스임을 보장할 수 있습니다.

옵션 3: 리디렉션될 인텐트가 유해하지 않은지 확인합니다.

리디렉션될 인텐트의 다음 사항을 확인해야 합니다.

  1. 앱의 비공개 구성요소로 전송되지 않음
  2. 외부 앱의 구성요소로 전송되지 않음 외부 앱을 타겟팅하기 위한 리디렉션의 경우 인텐트가 앱의 비공개 콘텐츠 제공업체 또는 시스템 데이터에 URI 권한을 부여하지 않아야 합니다.

앱에서 resolveActivity와 같은 메서드를 사용하여 인텐트를 리디렉션하기 전 처리하는 데 어떤 구성요소가 사용될지 확인할 수 있습니다. 예:

 Intent intent = getIntent();
 // 중첩된 인텐트 추출
 Intent forward = (Intent) intent.getParcelableExtra(“key”);
 // 구성요소 이름 가져오기
 ComponentName name = forward.resolveActivity(getPackageManager());
 // 패키지 이름과 클래스 이름이 맞는지 확인
 if (name.getPackageName().equals(“safe_package”) &&
     name.getClassName().equals(“safe_class”)) {
   // 중첩된 인텐트 리디렉션
   startActivity(forward);
 }

앱에서 getFlags와 같은 메서드를 사용하여 인텐트가 URI 권한을 부여하는지 확인할 수 있습니다. 예:

 // 중첩된 인텐트 추출
 Intent forward = (Intent) intent.getParcelableExtra(“key”);
 // 플래그 가져오기
 int flags = forward.getFlags();
 // 중첩된 인텐트에 URI 권한이 부여되지 않았는지 확인
 if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION == 0) &&
     (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION == 0)) {
   // 중첩된 인텐트 리디렉션
   startActivity(forward);
 }

또한 앱은 removeFlags를 사용하여 부여된 URI 권한을 삭제할 수 있습니다. 예:

 // 신뢰할 수 없는 인텐트
 Intent intent = getIntent();
 // 신뢰할 수 없는 인텐트에서 부여된 URI 권한 삭제
 intent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 intent.removeFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 // 신뢰할 수 없는 인텐트 전달
 setResult(intent);

알림 이해 및 방지 옵션 선택 

Play Console 알림은 앱이 신뢰할 수 없는 인텐트를 사용하여 startActivity, startActivityForResult, startService, sendBroadcast 또는 setResult를 호출하는 위치를 보고합니다. 가장 적절한 방지 옵션을 파악하려면 거꾸로 되돌아가 메서드 호출자를 살펴보면서 신뢰할 수 없는 인텐트가 어디에서 오는지 찾아보세요. 예를 들어 옵션 1의 경우 거꾸로 되돌아가 비공개로 설정할 구성요소를 결정합니다.

도움이 필요한 경우

취약점에 관해 기술적인 문의 사항이 있다면 'android-security' 태그를 사용하여 Stack Overflow에 질문을 올려 주시기 바랍니다. 이 문제를 해결하기 위해 취해야 할 단계를 명확하게 알아보려면 Google 개발자 지원팀에 문의해 주세요.

도움이 되었나요?

어떻게 하면 개선할 수 있을까요?
false
기본 메뉴
16722461028379537176
true
도움말 센터 검색
true
true
true
true
true
5016068
false
false