مدیریت ایمن کلیپ بورد

رده OWASP: MASVS-CODE: کیفیت کد

نمای کلی

اندروید یک چارچوب قدرتمند به نام کلیپ‌بورد برای کپی و پیست کردن داده‌ها بین برنامه‌ها ارائه می‌دهد. پیاده‌سازی نادرست این ویژگی می‌تواند داده‌های مربوط به کاربر را در معرض دسترسی عوامل یا برنامه‌های مخرب غیرمجاز قرار دهد.

خطر خاص مرتبط با افشای داده‌های کلیپ‌بورد به ماهیت برنامه و اطلاعات شخصی قابل شناسایی (PII) که با آن سروکار دارد بستگی دارد. این تأثیر به ویژه برای برنامه‌های مالی زیاد است، زیرا ممکن است داده‌های پرداخت یا برنامه‌هایی که از کدهای احراز هویت دو مرحله‌ای (2FA) استفاده می‌کنند را افشا کنند.

بردارهای حمله‌ای که می‌توانند برای استخراج داده‌های کلیپ‌بورد مورد استفاده قرار گیرند، بسته به نسخه اندروید متفاوت هستند:

  • نسخه‌های اندروید قدیمی‌تر از اندروید ۱۰ (سطح API ۲۹) به برنامه‌های پس‌زمینه اجازه می‌دهند تا به اطلاعات کلیپ‌بورد برنامه‌های پیش‌زمینه دسترسی داشته باشند، که به‌طور بالقوه امکان دسترسی مستقیم به هرگونه داده کپی‌شده توسط عوامل مخرب را فراهم می‌کند.
  • از اندروید ۱۲ به بعد (سطح API 31)، هر بار که یک برنامه به داده‌های داخل کلیپ‌بورد دسترسی پیدا می‌کند و آنها را پیست می‌کند، یک پیام هشدار به کاربر نشان داده می‌شود که نادیده گرفتن حملات را دشوارتر می‌کند. علاوه بر این، برای محافظت از اطلاعات شخصی، اندروید از پرچم ویژه ClipDescription.EXTRA_IS_SENSITIVE یا android.content.extra.IS_SENSITIVE پشتیبانی می‌کند. این پرچم به توسعه‌دهندگان اجازه می‌دهد تا پیش‌نمایش محتوای کلیپ‌بورد را در رابط کاربری گرافیکی صفحه‌کلید به صورت بصری مبهم کنند و از نمایش بصری داده‌های کپی‌شده به صورت متن واضح و سرقت احتمالی آنها توسط برنامه‌های مخرب جلوگیری کنند. عدم پیاده‌سازی یکی از پرچم‌های فوق‌الذکر در واقع می‌تواند به مهاجمان اجازه دهد تا داده‌های حساس کپی‌شده در کلیپ‌بورد را از طریق گشت‌وگذار در حافظه موقت یا از طریق برنامه‌های مخربی که در پس‌زمینه اجرا می‌شوند، از فعالیت‌های یک کاربر قانونی اسکرین‌شات می‌گیرند یا فیلم ضبط می‌کنند، استخراج کنند.

تأثیر

سوءاستفاده از مدیریت نادرست کلیپ‌بورد می‌تواند منجر به سرقت داده‌های حساس یا مالی مربوط به کاربر توسط عوامل مخرب شود. این امر ممکن است به مهاجمان در انجام اقدامات بیشتر مانند کمپین‌های فیشینگ یا سرقت هویت کمک کند.

کاهش‌ها

داده‌های حساس را علامت‌گذاری کنید

این راهکار برای مبهم‌سازی بصری پیش‌نمایش محتوای کلیپ‌بورد در رابط کاربری گرافیکی صفحه‌کلید به کار گرفته می‌شود. هرگونه داده حساسی که قابل کپی شدن باشد، مانند رمزهای عبور یا اطلاعات کارت اعتباری، باید قبل از فراخوانی ClipboardManager.setPrimaryClip() ، با ClipDescription.EXTRA_IS_SENSITIVE یا android.content.extra.IS_SENSITIVE علامت‌گذاری شود.

کاتلین

// 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)
    }
}

جاوا

// 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);

اجرای آخرین نسخه‌های اندروید

اجرای برنامه روی نسخه‌های اندروید بالاتر یا برابر با اندروید ۱۰ (API 29) مانع از دسترسی فرآیندهای پس‌زمینه به داده‌های کلیپ‌بورد در برنامه پیش‌زمینه می‌شود.

برای اینکه برنامه فقط روی اندروید ۱۰ (API 29) یا بالاتر اجرا شود، مقادیر زیر را برای تنظیمات نسخه در فایل‌های Gradle build در پروژه خود در اندروید استودیو تنظیم کنید.

گرووی

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"
          ...
      }
      ...
    }
    ...

کاتلین

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"
          ...
      }
      ...
    }
    ...

حذف محتوای کلیپ‌بورد پس از مدت زمان مشخص

اگر قرار است برنامه روی نسخه‌های اندروید پایین‌تر از اندروید ۱۰ (سطح API ۲۹) اجرا شود، هر برنامه پس‌زمینه‌ای می‌تواند به داده‌های کلیپ‌بورد دسترسی داشته باشد. برای کاهش این خطر، پیاده‌سازی تابعی که هرگونه داده کپی‌شده در کلیپ‌بورد را پس از یک دوره زمانی خاص پاک کند، مفید است. این تابع از اندروید ۱۳ (سطح API ۳۳) به طور خودکار انجام می‌شود. برای نسخه‌های قدیمی‌تر اندروید، این حذف را می‌توان با گنجاندن قطعه کد زیر در کد برنامه انجام داد.

کاتلین

//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)

جاوا

//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);

منابع