[InsecureBankv2] 액티비티 컴포넌트 취약점
[ 액티비티 컴포넌트 취약점 ]
: 애플리케이션 액티비티가 보안적으로 취약하면 로직을 무시하고 공격자가 필요한 액티비티를 강제로 호출해서
권한이 없는 사용자가 특정 액티비티에 접근해서 권한 없이 특정 기능 활성화 가능한 취약점
< 안드로이드 액티비티 >
- 앱을 구성하는 가장 기본적인 구성 단위 중 하나로,
안드로이드 애플리케이션과 사용자 간의 상호 작용에 필요한 기능을 제공
( 전화를 걸거나 이메일 전송 위한 화면 등 )
- 액티비티는 AndroidManifest.xml의 <activity> 요소에 선언
- 하나의 애플리케이션은 하나 이상의 액티비티로 구성됨
- 하나의 특정 액티비티는 "메인 액티비티"라 불리고, 매니페스트에 메인 액티비티로 선언
- 메인 액티비티 : 애플리케이션 시작 시 나타나는 화면으로, 앱 실행 후 조건에 따라 설정된 액티비티 호출
- 새로운 액티비티가 시작되면 이전에 실행된 액티비티는 잠시 멈추고 새로운 액티비티 실행
- 멈춘 액티비티는 시스템에서 스택으로 관리하고, 새로운 액티비티가 종료되거나 스마트폰의 "뒤로가기" 버튼을 누르면
스택에서 관리하던 액티비티 화면이 다시 실행되어 사용자에게 나타남.

애플리케이션의 액티비티가 보안적으로 취약하게 선언되어 있으면 로직을 무시하고 공격자가 필요한
액티비티를 강제로 호출하며, 해당 취약점을 악용하는 경우 권한이 없는 사용자가 특정 액티비티에
접근해 권한 없이 특정 기능을 활성화할 수도 있음.
( 로그인 안하고 계좌이체 화면으로 넘어가거나, 계좌 조회 등의 액티비티 호출 등)
< 취약점 진단 과정 >
1) ADB 이용
1. 액티비티 내용 중 exported=true 항목 확인
2. adb로 액티비티 실행
adb shell am start -n com.android.insecurebankv2/.ChangePassword

2) 드로저 이용
1. 애플리케이션에 노출된 액티비티 확인
run app.activity.info -a com.android.insecurebankv2

액티비티 사용을 위한 Permission(권한)이 설정되어 있지 않은 것 확인 가능.
여기서 출력되는 항목들은 매니페스트에 선언된 액티비티 요소 중 exported 속성이 true인 경우로, 공격이 가능함.
2. 드로저로 액티비티 실행
run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.ChangePassword


액티비티를 실행하면 사용자 이름이 세팅되어 있지 않으므로 비밀번호가 변경되지 않는다.
ChangePassword.class 액티비티 소스 코드
protected void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
setContentView(2130968601);
this.serverDetails = PreferenceManager.getDefaultSharedPreferences((Context)this);
this.serverip = this.serverDetails.getString("serverip", null);
this.serverport = this.serverDetails.getString("serverport", null);
this.changePassword_text = (EditText)findViewById(2131558503);
this.uname = getIntent().getStringExtra("uname");
System.out.println("newpassword=" + this.uname);
this.textView_Username = (TextView)findViewById(2131558502);
this.textView_Username.setText(this.uname);
this.changePassword_button = (Button)findViewById(2131558504);
this.changePassword_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View param1View) {
(new ChangePassword.RequestChangePasswordTask()).execute((Object[])new String[] { this.this$0.uname });
}
});
}
액티비티를 실행할 때 uname에 사용자 이름을 전달하고,
이 값을 textView_Username.setText(this.uname)을 통해
화면에 표시한다는 것을 알 수 있다.
비밀번호를 입력 한 후 "ChangePassword.RequestChangePasswordTask가 실행.
이 후에 나오는 코드는 입력된 값을 서버로 전송한다
< 특정 사용자의 비밀번호를 변경하는 공격 >
1. 액티비티 실행
run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.ChangePassword --extra string uname jack


jack 의 비밀번호를 Test!123$로 변경하고 Change Password를 누르면
비밀번호가 성공적으로 변경된 것을 확인 할 수 있다.
( 변경된 비밀번호로 정상적인 로그인이 가능 )
< 대응 방안 >
1. exported 속성을 false로 변경
<activity
android:name=".ChangePassword"
android:exported="false"
android:label="@string.title_activity_change_password" >
</activity>
AndroidManifest.xml 파일에 선언된 액티비티 요소에 포함된 android:exported 속성 값을 true에서 false로 변경한
후 에뮬레이터나 안드로이드 장치에서 실행한다.
2. 만약 액티비티를 노출해야 하는 경우 액티비티에 Permission을 추가한 후
특정 권한을 가진 경우에만 실행하도록 설정