Penanganan Papan Klip yang Aman

Kategori OWASP: MASVS-CODE: Kualitas Kode

Ringkasan

Android menawarkan framework canggih yang disebut sebagai papan klip untuk menyalin dan menempelkan data antar-aplikasi. Penerapan fitur ini yang tidak tepat dapat mengekspos data terkait pengguna kepada aplikasi atau pihak tidak bertanggung jawab yang berbahaya.

Risiko spesifik yang terkait dengan eksposur data papan klip bergantung pada sifat aplikasi dan Informasi Identitas Pribadi (PII) yang ditanganinya. Dampaknya sangat tinggi untuk aplikasi keuangan, karena aplikasi tersebut dapat mengekspos data pembayaran, atau aplikasi yang menangani kode autentikasi dua faktor (2FA).

Vektor serangan yang dapat dimanfaatkan untuk mengeksfiltrasi data papan klip bervariasi bergantung pada versi Android:

  • Versi Android yang lebih lama dari Android 10 (API level 29) memungkinkan aplikasi latar belakang mengakses informasi papan klip aplikasi latar depan, yang berpotensi memungkinkan akses langsung ke data apa pun yang disalin oleh pelaku berbahaya.
  • Mulai Android 12 dan seterusnya (API level 31), setiap kali aplikasi mengakses data dalam papan klip dan menempelkannya, pesan toast akan ditampilkan kepada pengguna, sehingga serangan lebih sulit untuk tidak terdeteksi. Selain itu, untuk melindungi PII, Android mendukung flag khusus ClipDescription.EXTRA_IS_SENSITIVE atau android.content.extra.IS_SENSITIVE. Hal ini memungkinkan developer untuk secara visual mengaburkan pratinjau konten papan klip dalam GUI keyboard, sehingga mencegah data yang disalin ditampilkan secara visual dalam cleartext dan berpotensi dicuri oleh aplikasi berbahaya. Tidak menerapkan salah satu flag yang disebutkan di atas sebenarnya dapat memungkinkan penyerang mengeksfiltrasi data sensitif yang disalin ke papan klip dengan cara mengintip atau melalui aplikasi berbahaya yang, saat berjalan di latar belakang, mengambil screenshot atau merekam video aktivitas pengguna yang sah.

Dampak

Eksploitasi penanganan papan klip yang tidak tepat dapat menyebabkan data sensitif atau keuangan terkait pengguna diekstrak oleh pelaku berbahaya. Hal ini dapat membantu penyerang melakukan tindakan lebih lanjut seperti kampanye phishing atau pencurian identitas.

Mitigasi

Menandai Data Sensitif

Solusi ini digunakan untuk mengaburkan pratinjau konten papan klip secara visual dalam GUI keyboard. Setiap data sensitif yang dapat disalin, seperti sandi atau data kartu kredit, harus ditandai dengan ClipDescription.EXTRA_IS_SENSITIVE atau android.content.extra.IS_SENSITIVE sebelum memanggil ClipboardManager.setPrimaryClip().

Kotlin

// If your app is compiled with the API level 33 SDK or higher.
clipData.apply {
    description.extras = PersistableBundle().apply {
        putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
    }
}

// If your app is compiled with API level 32 SDK or lower.
clipData.apply {
    description.extras = PersistableBundle().apply {
        putBoolean("android.content.extra.IS_SENSITIVE", true)
    }
}

Java

// If your app is compiled with the API level 33 SDK or higher.
PersistableBundle extras = new PersistableBundle();
extras.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
clipData.getDescription().setExtras(extras);

// If your app is compiled with API level 32 SDK or lower.
PersistableBundle extras = new PersistableBundle();
extras.putBoolean("android.content.extra.IS_SENSITIVE", true);
clipData.getDescription().setExtras(extras);

Menerapkan Versi Android Terbaru

Memaksa aplikasi untuk berjalan di versi Android yang lebih baru atau sama dengan Android 10 (API 29) akan mencegah proses latar belakang mengakses data papan klip di aplikasi latar depan.

Untuk mewajibkan aplikasi hanya berjalan di Android 10 (API 29) atau yang lebih baru, tetapkan nilai berikut untuk setelan versi dalam file build Gradle dalam project Anda di Android Studio.

Groovy

android {
      namespace 'com.example.testapp'
      compileSdk [SDK_LATEST_VERSION]

      defaultConfig {
          applicationId "com.example.testapp"
          minSdk 29
          targetSdk [SDK_LATEST_VERSION]
          versionCode 1
          versionName "1.0"
          ...
      }
      ...
    }
    ...

Kotlin

android {
      namespace = "com.example.testapp"
      compileSdk = [SDK_LATEST_VERSION]

      defaultConfig {
          applicationId = "com.example.testapp"
          minSdk = 29
          targetSdk = [SDK_LATEST_VERSION]
          versionCode = 1
          versionName = "1.0"
          ...
      }
      ...
    }
    ...

Menghapus konten Papan Klip setelah jangka waktu yang ditentukan

Jika aplikasi dimaksudkan untuk berjalan di versi Android yang lebih rendah dari Android 10 (API level 29), aplikasi latar belakang apa pun dapat mengakses data papan klip. Untuk mengurangi risiko ini, sebaiknya terapkan fungsi yang menghapus data apa pun yang disalin ke papan klip setelah jangka waktu tertentu. Fungsi ini dilakukan secara otomatis mulai dari Android 13 (API level 33). Untuk versi Android yang lebih lama, penghapusan ini dapat dilakukan dengan menyertakan cuplikan berikut dalam kode aplikasi.

Kotlin

//The Executor makes this task Asynchronous so that the UI continues being responsive
backgroundExecutor.schedule({
    //Creates a clip object with the content of the Clipboard
    val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clip = clipboard.primaryClip
    //If SDK version is higher or equal to 28, it deletes Clipboard data with clearPrimaryClip()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        clipboard.clearPrimaryClip()
    } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
    //If SDK version is lower than 28, it will replace Clipboard content with an empty value
        val newEmptyClip = ClipData.newPlainText("EmptyClipContent", "")
        clipboard.setPrimaryClip(newEmptyClip)
     }
//The delay after which the Clipboard is cleared, measured in seconds
}, 5, TimeUnit.SECONDS)

Java

//The Executor makes this task Asynchronous so that the UI continues being responsive

ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();

backgroundExecutor.schedule(new Runnable() {
    @Override
    public void run() {
        //Creates a clip object with the content of the Clipboard
        ClipboardManager clipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
        ClipData clip = clipboard.getPrimaryClip();
        //If SDK version is higher or equal to 28, it deletes Clipboard data with clearPrimaryClip()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            clipboard.clearPrimaryClip();
            //If SDK version is lower than 28, it will replace Clipboard content with an empty value
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            ClipData newEmptyClip = ClipData.newPlainText("EmptyClipContent", "");
            clipboard.setPrimaryClip(newEmptyClip);
        }
    //The delay after which the Clipboard is cleared, measured in seconds
    }, 5, TimeUnit.SECONDS);

Referensi