Penanganan Papan Klip yang Aman

Kategori OWASP: MASVS-CODE: Kualitas Kode

Ringkasan

Android menawarkan framework canggih yang disebut papan klip untuk menyalin dan menempelkan data antar-aplikasi. Penerapan fitur ini yang tidak tepat dapat mengekspos data terkait pengguna ke aplikasi atau pelaku kejahatan yang tidak sah.

Risiko spesifik yang terkait dengan eksposur data papan klip bergantung pada sifat aplikasi dan Informasi Identitas Pribadi (PII) yang ditanganinya. Dampaknya sangat besar 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 mengekstrak data papan klip berbeda-beda 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, sehingga berpotensi memungkinkan aktor berbahaya mengakses langsung data yang disalin.
  • Mulai Android 12 (level API 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 mengaburkan pratinjau konten papan klip secara visual dalam GUI keyboard, mencegah data yang disalin ditampilkan secara visual dalam teks biasa dan berpotensi dicuri oleh aplikasi berbahaya. Tidak menerapkan salah satu tanda di atas dapat memungkinkan penyerang mengeksfiltrasi data sensitif yang disalin ke papan klip dengan 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 diekstraksi 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. Data sensitif apa pun yang dapat disalin, seperti sandi atau data kartu kredit, harus diberi tanda 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

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

Untuk mewajibkan aplikasi berjalan hanya di Android 10 (API 29) atau yang lebih baru, tetapkan nilai berikut untuk setelan versi dalam file build Gradle di 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 tertentu

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 (level API 33). Untuk Android versi 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);

Resource