مدیریت ایمن کلیپ بورد
با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
دسته OWASP: MASVS-CODE: کیفیت کد
نمای کلی
اندروید یک چارچوب قدرتمند به نام کلیپ بورد برای کپی و چسباندن داده ها بین برنامه ها ارائه می دهد. اجرای نادرست این ویژگی می تواند داده های مربوط به کاربر را در معرض عوامل یا برنامه های مخرب غیرمجاز قرار دهد.
خطر خاص مرتبط با قرار گرفتن در معرض داده های کلیپ بورد به ماهیت برنامه و اطلاعات شناسایی شخصی (PII) که در حال رسیدگی است بستگی دارد. این تأثیر بهویژه برای برنامههای مالی بسیار زیاد است، زیرا ممکن است دادههای پرداخت یا برنامههایی را که کدهای احراز هویت دو عاملی (2FA) را مدیریت میکنند، در معرض دید قرار دهند.
بردارهای حمله ای که می توان از آنها برای استخراج داده های کلیپ بورد استفاده کرد بسته به نسخه اندروید متفاوت است:
- نسخههای Android قدیمیتر از Android 10 (سطح API 29) به برنامههای پسزمینه اجازه میدهند به اطلاعات کلیپبورد برنامه پیشزمینه دسترسی داشته باشند، و به طور بالقوه امکان دسترسی مستقیم به هر داده کپی شده توسط عوامل مخرب را فراهم میکنند.
- از اندروید 12 به بعد (سطح API 31)، هر بار که یک برنامه به دادههای درون کلیپ بورد دسترسی پیدا میکند و آنها را جایگذاری میکند، یک پیام نان تست به کاربر نشان داده میشود که بیتوجهی به حملات را دشوارتر میکند. علاوه بر این، به منظور محافظت از PII، Android از پرچم ویژه
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);
اجرای آخرین نسخه های اندروید
اجرای برنامه در نسخههای اندرویدی بعدی یا برابر با Android 10 (API 29) از دسترسی فرآیندهای پسزمینه به دادههای کلیپبورد در برنامه پیشزمینه جلوگیری میکند.
برای اینکه برنامه فقط در Android 10 (API 29) یا جدیدتر اجرا شود، مقادیر زیر را برای تنظیمات نسخه در فایلهای ساخت Gradle در پروژه خود در Android Studio تنظیم کنید.
شیار
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"
...
}
...
}
...
محتوای کلیپ بورد را پس از مدت زمان مشخصی حذف کنید
اگر قرار است برنامه روی نسخههای اندروید پایینتر از Android 10 (سطح API 29) اجرا شود، هر برنامه پسزمینه میتواند به دادههای کلیپبورد دسترسی داشته باشد. به منظور کاهش این خطر، پیاده سازی تابعی مفید است که هر داده کپی شده در کلیپ بورد را پس از یک دوره زمانی مشخص پاک می کند. این عملکرد با شروع Android 13 (سطح API 33) به طور خودکار انجام می شود . برای نسخه های قدیمی اندروید، این حذف را می توان با قرار دادن قطعه زیر در کد برنامه انجام داد.
کاتلین
//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);
منابع
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2025-07-29 بهوقت ساعت هماهنگ جهانی.
[null,null,["تاریخ آخرین بهروزرسانی 2025-07-29 بهوقت ساعت هماهنگ جهانی."],[],[],null,["# Secure Clipboard Handling\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-CODE: Code Quality](https://mas.owasp.org/MASVS/10-MASVS-CODE)\n\nOverview\n--------\n\nAndroid offers a powerful framework referred to as the [clipboard](/develop/ui/views/touch-and-input/copy-paste#Clipboard) for\ncopying and pasting data between applications. An improper implementation of\nthis feature could expose user-related data to unauthorized malicious actors or\napplications.\n\nThe specific risk associated with the exposure of clipboard data depends on the\nnature of the application and the Personal Identifiable Information (PII) it is\nhandling. The impact is especially high for financial applications, as they may\nexpose payment data, or apps that handle two-factor-authentication (2FA) codes.\n\nThe attack vectors that could be leveraged in order to exfiltrate clipboard data\nvary depending on Android version:\n\n- [Android versions older than Android 10 (API level 29)](/about/versions/10/privacy/changes#clipboard-data) allow background applications to access foreground app clipboard information, potentially allowing direct access to any copied data by malicious actors.\n- From Android 12 onwards (API level 31), every time an application accesses data within the clipboard and pastes it, a toast message is shown to the user, making it more difficult for attacks to go unnoticed. Additionally, in order to protect PII, Android supports the `ClipDescription.EXTRA_IS_SENSITIVE` or `android.content.extra.IS_SENSITIVE` special flag. This allows developers to visually obfuscate the clipboard content preview within the keyboard GUI, preventing copied data from being visually shown in clear-text and potentially stolen by malicious applications. Not implementing one of the aforementioned flags could in fact allow attackers to exfiltrate sensitive data copied to the clipboard by either shoulder surfing or through malicious applications that, while running in background, take screenshots or record videos of a legitimate user's activities.\n\nImpact\n------\n\nThe exploitation of improper clipboard handling could result in user-related\nsensitive or financial data being exfiltrated by malicious actors. This may aid\nattackers in conducting further actions such as phishing campaigns or identity\ntheft.\n\nMitigations\n-----------\n\n### Flag Sensitive Data\n\nThis solution is employed to visually obfuscate the clipboard content preview\nwithin the keyboard GUI. Any sensitive data that can be copied, such as\npasswords or credit card data, should be flagged with\n`ClipDescription.EXTRA_IS_SENSITIVE` or `android.content.extra.IS_SENSITIVE`\nbefore calling [`ClipboardManager.setPrimaryClip()`](/reference/android/content/ClipboardManager#setPrimaryClip(android.content.ClipData)). \n\n### Kotlin\n\n // If your app is compiled with the API level 33 SDK or higher.\n clipData.apply {\n description.extras = PersistableBundle().apply {\n putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)\n }\n }\n\n // If your app is compiled with API level 32 SDK or lower.\n clipData.apply {\n description.extras = PersistableBundle().apply {\n putBoolean(\"android.content.extra.IS_SENSITIVE\", true)\n }\n }\n\n### Java\n\n // If your app is compiled with the API level 33 SDK or higher.\n PersistableBundle extras = new PersistableBundle();\n extras.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);\n clipData.getDescription().setExtras(extras);\n\n // If your app is compiled with API level 32 SDK or lower.\n PersistableBundle extras = new PersistableBundle();\n extras.putBoolean(\"android.content.extra.IS_SENSITIVE\", true);\n clipData.getDescription().setExtras(extras);\n\n### Enforce Latest Android Versions\n\nEnforcing the app to run on Android versions later or equal to Android 10 (API\n29) prevents background processes from accessing clipboard data in the\nforeground application.\n\nTo enforce the app to run only on Android 10 (API 29) or later, set the\nfollowing values for the version settings in the Gradle build files within your\nproject in Android Studio. \n\n### Groovy\n\n android {\n namespace 'com.example.testapp'\n compileSdk [SDK_LATEST_VERSION]\n\n defaultConfig {\n applicationId \"com.example.testapp\"\n minSdk 29\n targetSdk [SDK_LATEST_VERSION]\n versionCode 1\n versionName \"1.0\"\n ...\n }\n ...\n }\n ...\n\n### Kotlin\n\n android {\n namespace = \"com.example.testapp\"\n compileSdk = [SDK_LATEST_VERSION]\n\n defaultConfig {\n applicationId = \"com.example.testapp\"\n minSdk = 29\n targetSdk = [SDK_LATEST_VERSION]\n versionCode = 1\n versionName = \"1.0\"\n ...\n }\n ...\n }\n ...\n\n### Delete Clipboard content after a defined period of time\n\nIf the application is meant to run on Android versions lower than Android 10\n(API level 29), any background application can access clipboard data.\nIn order\nto reduce this risk, it's useful to implement a function that clears any data\ncopied to the clipboard after a specific period of time. This function is\n[automatically performed starting with Android 13 (API level 33)](https://blog.google/products/android/android-13/).\nFor older\nAndroid versions, this deletion can be performed by including the following\nsnippet within the application's code. \n\n### Kotlin\n\n //The Executor makes this task Asynchronous so that the UI continues being responsive\n backgroundExecutor.schedule({\n //Creates a clip object with the content of the Clipboard\n val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager\n val clip = clipboard.primaryClip\n //If SDK version is higher or equal to 28, it deletes Clipboard data with clearPrimaryClip()\n if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.P) {\n clipboard.clearPrimaryClip()\n } else if (Build.VERSION.SDK_INT \u003c Build.VERSION_CODES.P) {\n //If SDK version is lower than 28, it will replace Clipboard content with an empty value\n val newEmptyClip = ClipData.newPlainText(\"EmptyClipContent\", \"\")\n clipboard.setPrimaryClip(newEmptyClip)\n }\n //The delay after which the Clipboard is cleared, measured in seconds\n }, 5, TimeUnit.SECONDS)\n\n### Java\n\n //The Executor makes this task Asynchronous so that the UI continues being responsive\n\n ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();\n\n backgroundExecutor.schedule(new Runnable() {\n @Override\n public void run() {\n //Creates a clip object with the content of the Clipboard\n ClipboardManager clipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);\n ClipData clip = clipboard.getPrimaryClip();\n //If SDK version is higher or equal to 28, it deletes Clipboard data with clearPrimaryClip()\n if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.P) {\n clipboard.clearPrimaryClip();\n //If SDK version is lower than 28, it will replace Clipboard content with an empty value\n } else if (Build.VERSION.SDK_INT \u003c Build.VERSION_CODES.P) {\n ClipData newEmptyClip = ClipData.newPlainText(\"EmptyClipContent\", \"\");\n clipboard.setPrimaryClip(newEmptyClip);\n }\n //The delay after which the Clipboard is cleared, measured in seconds\n }, 5, TimeUnit.SECONDS);\n\nResources\n---------\n\n- [The clipboard framework](/develop/ui/views/touch-and-input/copy-paste#Clipboard)\n- [System notification shown when your app accesses clipboard data](/develop/ui/views/touch-and-input/copy-paste#PastingSystemNotifications)\n- [Add sensitive content to the clipboard](/develop/ui/views/touch-and-input/copy-paste#SensitiveContent)\n- [Privacy changes in Android 10](/about/versions/10/privacy/changes)\n- [Set app version information](/studio/publish/versioning#appversioning)"]]