קטגוריה של OWASP: MASVS-CODE: איכות הקוד
סקירה כללית
מערכת Android מציעה מסגרת חזקה שנקראת לוח להעתקה ולהדבקה של נתונים בין אפליקציות. הטמעה לא תקינה של התכונה הזו עלולה לחשוף נתונים שקשורים למשתמשים לגורמים זדוניים לא מורשים או לאפליקציות לא מורשות.
הסיכון הספציפי שקשור לחשיפה של נתונים בלוח העריכה תלוי באופי האפליקציה ובפרטים האישיים המזהים (PII) שהיא מטפלת בהם. ההשפעה גבוהה במיוחד באפליקציות פיננסיות, כי הן עשויות לחשוף נתוני תשלום, או באפליקציות שמטפלות בקודי אימות דו-שלבי (2FA).
וקטורי התקיפה שאפשר לנצל כדי להעביר נתונים מלוח העריכה משתנים בהתאם לגרסת Android:
- בגרסאות Android ישנות יותר מ-Android 10 (רמת API 29), אפליקציות ברקע יכולות לגשת למידע בלוח של אפליקציות שפועלות בחזית, מה שעלול לאפשר לגורמים זדוניים לגשת ישירות לכל הנתונים שהועתקו.
- מגרסה Android 12 ואילך (רמת API 31), בכל פעם שאפליקציה ניגשת לנתונים בלוח ההעתקה ומדביקה אותם, מוצגת למשתמש הודעה קצרה, וכך קשה יותר להתקפות לעבור ללא תשומת לב. בנוסף, כדי להגן על פרטים אישיים מזהים (PII), מערכת Android תומכת בדגל המיוחד
ClipDescription.EXTRA_IS_SENSITIVEאוandroid.content.extra.IS_SENSITIVE. האפשרות הזו מאפשרת למפתחים להסתיר חזותית את התצוגה המקדימה של התוכן בלוח העריכה בממשק המשתמש הגרפי של המקלדת, ולמנוע את הצגת הנתונים שהועתקו כטקסט רגיל, וכך למנוע אפשרות של גניבת הנתונים על ידי אפליקציות זדוניות. אם לא תטמיעו את אחד מהדגלים שצוינו למעלה, יכול להיות שתאפשרו לתוקפים לגנוב מידע אישי רגיש שהועתק ללוח, באמצעות צפייה מעל הכתף או באמצעות אפליקציות זדוניות שפועלות ברקע, מצלמות את המסך או מקליטות סרטונים של פעילויות של משתמש לגיטימי.
השפעה
ניצול של טיפול לא תקין בלוח העתקה עלול לגרום לגורמים זדוניים להוציא מידע רגיש או פיננסי שקשור למשתמשים. המידע הזה יכול לעזור לתוקפים לבצע פעולות נוספות, כמו קמפיינים של פישינג או גניבת זהות.
אמצעי צמצום סיכונים
סימון מידע אישי רגיש
הפתרון הזה משמש להסתרה חזותית של התצוגה המקדימה של התוכן בלוח העריכה בממשק המשתמש הגרפי של המקלדת. צריך לסמן כל מידע אישי רגיש שאפשר להעתיק, כמו סיסמאות או פרטי כרטיס אשראי, באמצעות 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 (API 29) מונעת מתהליכים ברקע לגשת לנתונים בלוח באפליקציה בחזית.
כדי לאלץ את האפליקציה לפעול רק ב-Android 10 (API 29) ואילך, מגדירים את הערכים הבאים להגדרות הגרסה בקובצי ה-build של 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 (רמת API 29), כל אפליקציה שפועלת ברקע יכולה לגשת לנתונים בלוח. כדי להפחית את הסיכון הזה, כדאי להטמיע פונקציה שמנקה את כל הנתונים שהועתקו ללוח אחרי תקופה מסוימת. הפונקציה הזו מופעלת באופן אוטומטי החל מ-Android 13 (רמת API 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);
משאבים
- מסגרת ללוח
- התראת מערכת שמוצגת כשהאפליקציה ניגשת לנתונים בלוח העריכה
- הוספת תוכן רגיש ללוח
- שינויים בפרטיות ב-Android 10
- הגדרת פרטי גרסת האפליקציה