[안드로이드 모의해킹] 액티비티 강제 실행

직접 연구하여 작성한 자료입니다. 공식 출처가 명시되지 않은 자료의 무단 복제, 사용을 금지합니다.
공격 기법은 학습용, 허가된 환경에서 실습 바랍니다. 실 운영망 대상 공격은 처벌받습니다. (정보통신망법 제48조 1항)
학습자료 apk파일은 https://github.com/colfax0483/Vulnerable_apk 에서 clone할 수 있습니다.

1. 개요

안드로이드 앱 환경은 PC 환경과 다르게 사용자와 앱의 상호작용이 항상 동일한 위치에서 시작하지 않는다. 일반적인 프로그래밍에서 메인(main) 함수부터 실행하는 것과 달리 안드로이드 시스템은 액티비티별 생명주기에 따른 단계별 콜백 함수 통해 앱 코드를 실행한다. 선언된 콜백 함수는 액티비티 클래스에서 관리된다. 예를 들어, 기존에 실행중인 앱 'A'에서 다른 앱 'B'의 특정 액티비티를 직접 호출할 수 있다. 이는 B앱의 기본 시작점이 아닌, 특정 목적을 가진 액티비티를 직접 실행하는 것을 의미한다. 전화 앱을 일반적으로 실행시켰을 때에는 다이얼 패드가 나타나는 화면이 표시된다. 하지만, 지도 앱이나 다른 앱에서 전화번호를 터치해서 전화 앱을 실행하면, 전화번호가 이미 입력되어 있는 전화 걸기 직전 화면이나, 전화를 발신하는 액티비티로 바로 이동할 수 있다.

 

앱에는 여러 화면이 포함되어 있으며, 화면은 여러 액티비티로 구성된다. 구성된 액티비티는 메타데이터 파일인 AndroidManifest.xml에 앱 구성 요소의 정보와 함께 정의된다. <activity> 태그는 액티비티 구성 요소를 선언하는 데 사용한다. 하지만 <activity> 태그 속성을 적절하게 설정하지 않거나 액티비티 실행 시 정상 실행 여부를 검증하지 않으면 액티비티 강제 실행 취약점이 발생할 수 있다.

 

액티비티 강제 실행 취약점은 공격자가 앱의 예상치 못한 액티비티를 강제로 실행시켜 민감한 정보에 접근하거나 비정상적인 동작을 유발할 수 있기 때문에 주의가 필요하다. 개발자는 액티비티를 설계할 때 해당 액티비티가 예상치 못한 방식으로 실행되지 않도록 보호 조치를 취해야 하며, AndroidManifest.xml에서 보안 관련 속성을 올바르게 설정하여 액티비티의 보안을 강화해야 한다.

💡 더 알아보기
안드로이드 앱 메타데이터 파일(AndroidManifest.xml)은 앱의 패키지명 뿐만 아니라 앱의 공용 API를 선언하기 위해서도 사용된다. 컴포넌트(액티비티, 서비스 및 브로드캐스트 리시버) ‘android:name’ 속성에 고유한 이름을 선언한다. 비공개가 아닌(android:exported 값이 true) 컴포넌트는 외부에서도 호출 가능한 API로 취급되며, 안드로이드 공식 문서에서는 앱 출시 이후에는 이름을 변경하지 않는 것을 권고하고 있다.

컴포넌트 이름의 변경은 연계 설정된 값(입력 방법, 접근성 서비스 등)을 기본 값으로 변경할 수 있으며, 개발자들은 이를 신중하게 관리해야 한다.

 

<manifest ... >
  <application ... >
    <activity
      android:name=".MyAuthActivity"
      android:exported="true"
      android:permission="com.myapp.permission.AUTH">
    </activity>
  </application ... >
      ...
</manifest >

 

예제의 경우 <activity>태그 내에 ‘android:exported’ 속성의 값이 참(‘true’)으로 설정되어 있어 해당 액티비티는 외부에 공개되어 있음을 알 수 있고 명시적으로 다른 컴포넌트에서 호출할 수 있다. 예제의 액티비티(.MyAuthActivity)가 사용자 인증 기능을 하는 액티비티이며, 외부 호출이 가능한 취약 액티비티라고 가정할 경우 다음의 위협이 발생할 수 있다.

 

액티비티 정상 실행 흐름 및 취약 실행 흐름

 

앱 개발자는 사용자의 민감정보나 중요 기능에 접근하기 전 인증 기능을 거치도록 앱을 구성할 수 있다. 그러나 액티비티에 대한 보안 설정을 취약하게 설정하여 외부로 노출된 경우, 각각의 액티비티를 실행 흐름에 관계없이 호출할 수 있다. 예를 들어 기존의 사용자 로그인 정보가 앱 내에 저장되어 있고, 두 번째 액티비티의 강제 실행을 통해 1차 인증을 우회하고 2차 인증만 통과하면 세 번째 액티비티의 민감정보에 접근할 수 있다. 세 번째 액티비티의 강제 실행이 가능한 경우, 앞의 두 단계에 대한 인증 로직을 우회하여 실행할 수 있다.

액티비티 강제 실행 취약점은 액티비티가 외부로 노출되어 있고 직접 호출이 가능하며, 각 액티비티가 시작할 때 이전 액티비티의 인증 절차가 구현되지 않았을 때 발생한다.

 

2. 진단방법

 

액티비티 강제실행 취약점을 진단하는 방법은 취약점이 발생하는 주된 위치인 인증, 권한 사용 기능에 대해 우회가 가능한지 확인하는 것이다. 인증 절차를 수행하는 데 사용되는 액티비티를 보호하지 않고 다른 앱이나 외부로부터 강제 실행을 허용하고 인증 이후 화면에 접근 가능하거나 민감정보의 탈취가 가능한 경우 취약으로 진단한다.

adb를 이용하여 액티비티를 직접 실행시킬 수 있다. 다음의 명령을 참고한다.

 


패키지 명 및 액티비티 명 확인

ADB # dumpsys package [패키지명] | grep -i activity

 

Activity 강제 호출

PC > adb shell su  -c am start -a android.intent.action.MAIN -n [패키지명]/[액티비티 경로명]

 

Activity 강제 중지

PC > adb shell am force-stop [패키지명]

 

현재 단말기 화면에 실행중인 Activity 확인

PC > adb shell “dumpsys window windows” | grep -E ‘mCurrentFocus|mFocusedApp’”

 

취약여부 설명
취약 adb, 스크립트 등으로 액티비티를 강제 실행시켜 인증 우회 또는 민감정보 유출이 가능하며 이후 기능을 정상적으로 사용할 수 있는 경우
양호 adb, 스크립트 등으로 액티비티의 강제 실행이 불가능한 경우

 

3. 보안대책

 

앱 내에서만 사용하는 액티비티는 앱 외부에 공개되거나 컴포넌트를 노출할 필요가 없다. 외부로부터의 악의적인 호출을 방지하기 위해 명시적으로 비공개로 설정한다.

 

<manifest ... >
  <application ... >
    <activity
		android:name=".PrivateActivity"
		android:label="@string/app_name"
		android:exported="false">
    </activity>
  </application ... >
      ...
</manifest >

 

민감한 작업을 수행하는 액티비티에는 적절한 권한 및 접근 제어 로직을 구현하는 것이 필수적이다. 액티비티를 설계할 때, 권한 확인 및 추가 인증 과정이 포함되도록 해야 하며, 외부에서 해당 액티비티를 실행할 때에도 인가된 사용자만이 접근할 수 있도록 해야 한다.

액티비티 내에서의 권한 확인은 사용자가 특정 기능에 접근하기 전에 인증 절차를 거치도록 하는 것을 의미한다. 추가 인증 과정은 민감한 작업을 수행하기 전에 이중으로 사용자를 확인하는 방법으로, 예를 들어 비밀번호, 지문 인식, 얼굴 인식 등 다양한 방법을 사용할 수 있다.

외부에서 액티비티를 실행하는 경우에도, 인가된 사용자만이 액티비티를 사용할 수 있도록 권한 체크 로직을 구현해야 한다. 이를 통해 앱 내부의 민감한 액티비티가 외부의 비인가된 접근으로부터 보호될 수 있다.

반응형