Kategoria OWASP: MASVS-CODE: Code Quality
Omówienie
Android oferuje zaawansowany framework zwany schowkiem do kopiowania i wklejania danych między aplikacjami. Niewłaściwe wdrożenie tej funkcji może narazić dane użytkowników na nieautoryzowany dostęp ze strony osób lub aplikacji, które mają złe zamiary.
Konkretne ryzyko związane z wyłożeniem danych z bufora komunikacyjnego zależy od charakteru aplikacji i danych osobowych, z którymi ma ona do czynienia. W szczególności dotyczy to aplikacji finansowych, które mogą ujawniać dane do płatności, oraz aplikacji obsługujących kody uwierzytelniania dwuskładnikowego (2FA).
Wektory ataków, które można wykorzystać do wydobycia danych ze schowka, różnią się w zależności od wersji Androida:
- Wersje Androida starsze niż 10 (poziom interfejsu API 29) umożliwiają aplikacjom działającym w tle dostęp do informacji ze schowka aplikacji na pierwszym planie, co może umożliwić złośliwym podmiotom bezpośredni dostęp do skopiowanych danych.
- Od Androida 12 (poziom interfejsu API 31) za każdym razem, gdy aplikacja odczytuje dane z bufora i je wklei, użytkownik zobaczy komunikat wyskakujący, co utrudnia przeprowadzenie niezauważalnych ataków. Dodatkowo, aby chronić informacje o osobach, Android obsługuje flagę specjalną
ClipDescription.EXTRA_IS_SENSITIVE
lubandroid.content.extra.IS_SENSITIVE
. Umożliwia to deweloperom zaciemnianie podglądu treści skopiowanych do schowka w interfejsie graficznym klawiatury, co uniemożliwia wyświetlanie skopiowanych danych w postaci tekstu zwykłego i ich potencjalne kradzież przez złośliwe aplikacje. Niewdrożenie któregoś z wymienionych flag może umożliwić atakującym pozyskiwanie poufnych danych skopiowanych do schowka przez podglądanie przez ramię lub za pomocą złośliwych aplikacji, które podczas działania w tle wykonują zrzuty ekranu lub nagrywają filmy z działalności legalnego użytkownika.
Wpływ
Wykorzystanie nieprawidłowego zarządzania schowka może skutkować pozyskaniem przez osoby o złośliwych zamiarach poufnych danych użytkownika lub informacji o jego finansach. Może to ułatwić atakującym przeprowadzenie dalszych działań, takich jak kampanie phishingowe czy kradzież tożsamości.
Środki zaradcze
Oznaczanie danych wrażliwych
To rozwiązanie służy do zaciemnienia podglądu zawartości schowka w interfejsie graficznym klawiatury. Wszystkie informacje poufne, które można skopiować, takie jak hasła czy dane karty kredytowej, powinny być oznaczone jako ClipDescription.EXTRA_IS_SENSITIVE
lub android.content.extra.IS_SENSITIVE
przed nawiązaniem połączenia z 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);
Wymaganie najnowszych wersji Androida
Wymaganie uruchamiania aplikacji w wersjach Androida 10 lub nowszych (API 29) uniemożliwia procesom działającym w tle dostęp do danych schowka w aplikacji na pierwszym planie.
Aby wymusić uruchamianie aplikacji tylko na Androidzie 10 (interfejs API 29) lub nowszym, ustaw te wartości dla ustawień wersji w plikach kompilacji Gradle w projekcie w 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"
...
}
...
}
...
Usuwanie treści ze schowka po określonym czasie
Jeśli aplikacja ma działać na wersjach Androida starszych niż 10 (poziom interfejsu API 29), każda aplikacja działająca w tle może uzyskać dostęp do danych schowka. Aby zmniejszyć to ryzyko, warto wdrożyć funkcję, która po określonym czasie usuwa wszystkie dane skopiowane do schowka. Ta funkcja jest wykonana automatycznie od Androida 13 (poziom API 33). W starszych wersjach Androida można usunąć te pliki, dodając do kodu aplikacji ten fragment kodu.
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);
Materiały
- Framework schowka
- Powiadomienie systemowe wyświetlane, gdy aplikacja uzyskuje dostęp do danych ze schowka
- Dodawanie treści poufnych do schowka
- Zmiany dotyczące prywatności w Androidzie 10
- Ustawianie informacji o wersji aplikacji