Insecure Bank2 취약점(1)

Insecure Bank2 취약점(1)

Description
브로드캐스트 리시버 결함
category
MobileHacking
Tag
Mobile Security
Andorid
Date
Jan 17, 2024 09:31 AM

브로드캐스트 리시버 결함

브로드캐스트 리시버란?

안드로이드 기기에서 이벤트가 발생하면 브로드캐스트 신호를 전송하는데 그 신호를 처리하는게 브로드캐스트 리시버이다.
신호를 받아 처리하기 위해선 AndroidManifest.xml에 설정을 해주어야 한다. 설정을 통해 작동할 작업을 정의 할 수 있다.
브로드캐스트 리시버의 사용 예로는 배터리 상태, 메세지 송.수신 등이 있다.
 

취약점 진단

취약점 진단을 위해 AndroidManifest.xml을 보면 <receiver>의 exported가 True로 이루어져 있는 것을 볼 수 있다. 따라서 모든 곳에서 엑세스가 가능하여 외부 접근이 가능해 취약하다.
코드를 살펴보면 theBroadcast가 생성 되면 MyBroadCastReceiver메서드를 호출하는 것을 알 수 있다.
<receiver android:name="com.android.insecurebankv2.MyBroadCastReceiver" android:exported="true"> <intent-filter> <action android:name="theBroadcast"/> </intent-filter> </receiver>
AndroidManifest.xml
 
MyBroadCastReceiver의 코드를 살펴보면 전화번호와 비밀번호를 변경하는 기능을 하는 것을 볼 수 있다.
변경 될 전화번호와 비밀번호는 intent의 phonenumber, newpass를 통해 가져온다. 만일 intent에 phonenumber값이 존재하지 않으면 “Phone number is null”을 호출한다.
따라서 임의로 theBroadcast를 호출해 비밀번호와 전화번호를 변경 할 수 있다.
package com.android.insecurebankv2; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.telephony.SmsManager; import android.util.Base64; /* loaded from: classes.dex */ public class MyBroadCastReceiver extends BroadcastReceiver { public static final String MYPREFS = "mySharedPreferences"; String usernameBase64ByteString; @Override // android.content.BroadcastReceiver public void onReceive(Context context, Intent intent) { String phn = intent.getStringExtra("phonenumber"); String newpass = intent.getStringExtra("newpass"); if (phn != null) { try { SharedPreferences settings = context.getSharedPreferences("mySharedPreferences", 1); String username = settings.getString("EncryptedUsername", null); byte[] usernameBase64Byte = Base64.decode(username, 0); this.usernameBase64ByteString = new String(usernameBase64Byte, "UTF-8"); 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); return; } catch (Exception e) { e.printStackTrace(); return; } } System.out.println("Phone number is null"); } }
com.android.insecurebankv2.MyBroadCastReceiver.class
 

ADB를 이용한 브로드캐스트 생성

ADB에서는 am(activity manager)을 통해 브로드캐스트를 생성 가능하다.
 
am을 통해 broadcast를 생성해보고 logcat을 통해 확인해보았다.
am broadcast -a theBroadcast -n com.android.insecurebankv2/.MyBroadCastReceiver
notion image
 
logcat
logcat
 
intent를 통해 아무런 값도 전송하지 않았기 때문에 Phone number is null을 메세지를 출력한다.
 
am에 —es 옵션을 사용하게 되면 변수를 전송 할 수 있다.
phonenumber와 newpass를 포함하여 전송해보았다.
am broadcast -a theBroadcast -n com.android.insecurebankv2/.MyBroadCastReceiver --es phonenumber 5555 --es newpass test
 
비밀번호가 변경되진 않았지만 기존 비밀번호가 평문으로 표기되는 것을 알 수 있다.
logcat
logcat
 

Drozer를 통한 브로드캐스트 생성

드로저는 위 주소에서 다운받아 사용가능하다.
 
해당 명령어를 통해 브로드캐스트 리시버의 정보를 확인 할 수 있다. 실행 결과 Permission은 null로 지정되어 있는 MyBroadCastReceiver를 확인 할 수 있다.
dz> run app.broadcast.info -a com.android.insecurebankv2
drozer 코드 실행화면
drozer 코드 실행화면
 
app.boradcast.send를 사용하면 브로드캐스트를 생성 할 수 있다. drozer는 —extra를 통해 변수를 추가 할 수 있다.
아래 코드를 통해 기존 암호를 평문으로 얻을 수 있다.
dz> run app.broadcast.send --component com.android.insecurebankv2 com.android.insecurebankv2.MyBroadCastReceiver --extra string phonenumber 4444 --extra string newpass drozetest
 
ADB와 동일하게 logcat을 통해 비밀번호를 확인이 가능하다.
notion image
 

대응방안

해당 취약점은 receiver의 export가 True로 되어 있기 때문에 외부 접근이 가능해 취약했다.
따라서 export 값을 아래 코드와 같이 False로 변경하게 되면 해당 앱의 UID만이 receiver에 대한 권한이 생기게 되어 더 이상 취약하지 않다.
<receiver android:name="com.android.insecurebankv2.MyBroadCastReceiver" android:exported="false"> <intent-filter> <action android:name="theBroadcast"/> </intent-filter> </receiver>
 
다른 방법으로는 receiver에 별도의 Permission을 부여하는 것이다.