이 정보는 인텐트 리디렉션 취약점이 있는 앱의 개발자를 대상으로 합니다.
현재 상태
하나 이상의 앱에 악성 앱이 비공개 앱 구성요소나 파일에 액세스하도록 허용할 수 있는 인텐트 리디렉션 문제가 있습니다. 앱 문제를 해결하려면 아래에 안내된 자세한 단계를 확인하세요. Play Console에 표시된 기한이 지난 후에도 보안 취약점 문제가 해결되지 않은 앱은 모두 Google Play에서 삭제됩니다.
필요한 조치
- Play Console에 로그인한 후 알림 섹션으로 이동하여 영향을 받는 앱과 문제 해결 기한을 확인합니다.
- 아래에 설명된 단계를 참고하여 영향을 받는 앱을 업데이트합니다.
- 영향을 받는 앱의 업데이트된 버전을 제출합니다.
제출된 앱은 다시 검토 절차를 거치게 되며 이 절차는 몇 시간 정도 걸릴 수 있습니다. 앱이 검토 과정을 통과하고 게시가 완료되면 더 이상의 조치가 필요하지 않습니다. 앱이 검토 과정을 통과하지 못할 경우 새로운 앱 버전은 게시되지 않으며 이메일 알림을 받게 됩니다.
추가 세부정보
구성요소 실행(예: startActivity 호출) 또는 데이터 반환(예: setResult 호출)을 위한 신뢰할 수 없는 인텐트 사용은 위험하며 악성 앱이 다음과 같은 문제를 일으킬 수 있습니다.
- 앱에서 민감한 파일 또는 시스템 데이터(예: SMS 메시지) 도용
- 악성 인수를 사용하여 앱의 비공개 구성요소를 실행
앱이 신뢰할 수 없는 인텐트에서 인텐트를 검사하거나 정리하지 않은 채 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: 리디렉션될 인텐트가 유해하지 않은지 확인합니다.
리디렉션될 인텐트의 다음 사항을 확인해야 합니다.
- 앱의 비공개 구성요소로 전송되지 않음
- 외부 앱의 구성요소로 전송되지 않음 외부 앱을 타겟팅하기 위한 리디렉션의 경우 인텐트가 앱의 비공개 콘텐츠 제공업체 또는 시스템 데이터에 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 개발자 지원팀에 문의해 주세요.