التعامل مع الحافظة بأمان
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
فئة OWASP: MASVS-CODE: جودة الرموز البرمجية
نظرة عامة
يوفّر Android إطار عمل فعّال يُشار إليه باسم الحافظة ل
نسخ البيانات ولصقها بين التطبيقات. يمكن أن يؤدي التنفيذ غير الصحيح
لهذه الميزة إلى تعريض البيانات المتعلّقة بالمستخدمين لجهات فاعلة أو
تطبيقات ضارة غير مصرّح بها.
يعتمد الخطر المحدّد المرتبط بعرض بيانات الحافظة على
طبيعة التطبيق ومعلومات تحديد الهوية الشخصية (PII) التي يعالجها. يكون التأثير مرتفعًا بشكل خاص في التطبيقات المالية، لأنّها قد تؤدي إلى
إظهار بيانات الدفع أو التطبيقات التي تتعامل مع رموز المصادقة الثنائية.
تختلف أدوات الهجوم التي يمكن استخدامها لاستخراج بيانات الحافظة
حسب إصدار Android:
- تسمح إصدارات Android الأقدم من Android 10 (المستوى 29 من واجهة برمجة التطبيقات) للتطبيقات التي تعمل في الخلفية بالوصول إلى معلومات الحافظة في التطبيقات التي تعمل في المقدّمة، ما قد يؤدي إلى السماح بالوصول المباشر إلى أي بيانات تم نسخها من قِبل الجهات الفاعلة الضارّة.
- بدءًا من الإصدار 12 من Android فصاعدًا (المستوى 31 لواجهة برمجة التطبيقات)، في كل مرة يصل فيها تطبيق إلى data ضمن الحافظة ويلصقها، يتم عرض رسالة فورية للمستخدم، مما يجعل من الصعب عدم ملاحظة الهجمات. بالإضافة إلى ذلك، لحماية معلومات تحديد الهوية الشخصية، يتيح Android العلامة الخاصة
ClipDescription.EXTRA_IS_SENSITIVE
أو
android.content.extra.IS_SENSITIVE
. يتيح ذلك للمطوّرين التمويه البصري لمعاينة محتوى الحافظة ضمن واجهة مستخدم لوحة المفاتيح، ما يمنع عرض البيانات المنسوخة بشكل مرئي في نص واضح ومن المحتمل أن يتم سرقتها من خلال التطبيقات الضارة. إنّ عدم تنفيذ أحد الإعدادات المذكورة أعلاه
قد يسمح للمهاجمين في الواقع بسرقة البيانات الحسّاسة التي تم نسخها إلى
الحافظة من خلال مراقبة الشاشة أو من خلال التطبيقات الخبيثة التي تلتقط لقطات شاشة أو تسجِّل فيديوهات لأنشطة مستخدم شرعي
أثناء تشغيلها في الخلفية.
التأثير
يمكن أن يؤدي استغلال التعامل غير السليم مع الحافظة إلى حصول الجهات الضارّة على بيانات حساسة أو مالية متعلقة بالمستخدم. وقد يساعد ذلك
المهاجمين في تنفيذ المزيد من الإجراءات، مثل حملات التصيّد الاحتيالي أو
سرقة الهوية.
إجراءات التخفيف
الإبلاغ عن البيانات الحسّاسة
يتم استخدام هذا الحلّ لإخفاء معاينة محتوى الحافظة visually
ضمن واجهة المستخدم الرسومية للوحة المفاتيح. يجب وضع علامة عليها باستخدام ClipDescription.EXTRA_IS_SENSITIVE
أو android.content.extra.IS_SENSITIVE
قبل الاتصال بفريق 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);
فرض أحدث إصدارات Android
إنّ فرض تشغيل التطبيق على إصدارات Android الأحدث أو الإصدارات التي تساوي Android 10 (واجهة برمجة التطبيقات
29) يمنع العمليات التي تعمل في الخلفية من الوصول إلى بيانات الحافظة في
التطبيق الذي يعمل في المقدّمة.
لفرض تشغيل التطبيق على نظام التشغيل Android 10 (الإصدار 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"
...
}
...
}
...
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"
...
}
...
}
...
حذف محتوى الحافظة بعد فترة زمنية محدّدة
إذا كان التطبيق مخصّصًا للتشغيل على إصدارات Android أقدم من Android 10
(المستوى 29 لواجهة برمجة التطبيقات)، يمكن لأي تطبيق يعمل في الخلفية الوصول إلى بيانات الحافظة.
للحدّ
من هذا الخطر، من المفيد تنفيذ دالة تمحو أي بيانات
تم نسخها إلى الحافظة بعد فترة زمنية معيّنة. تتم تنفيذ هذه الوظيفة تلقائيًا اعتبارًا من Android 13 (المستوى 33 لواجهة برمجة التطبيقات).
بالنسبة إلى الإصدارات القديمة من Android، يمكن تنفيذ هذا الحذف من خلال تضمين مقتطف الرمز التالي في رمز التطبيق.
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);
المراجع
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-26 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-26 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],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)"]]