Platforma Android korzysta z ochrony opartej na użytkownikach systemu Linux, aby identyfikować i izolatować zasoby aplikacji. Pozwala to odizolować aplikacje od siebie nawzajem i chronić aplikacje oraz system przed złośliwymi aplikacjami. W tym celu Android przypisuje do każdej aplikacji na Androida unikalny identyfikator użytkownika (UID) i uruchamia ją w oddzielnym procesie.
Android używa identyfikatora UID do konfigurowania piaskownicy aplikacji na poziomie jądra. Rdzeń zapewnia bezpieczeństwo między aplikacjami a systemem na poziomie procesu za pomocą standardowych funkcji Linuksa, takich jak identyfikatory użytkowników i grup przypisane do aplikacji. Domyślnie aplikacje nie mogą ze sobą współpracować i mają ograniczony dostęp do systemu operacyjnego. Jeśli aplikacja A próbuje wykonać działanie złośliwe, np. odczytać dane aplikacji B lub zadzwonić bez zgody, nie może tego zrobić, ponieważ nie ma odpowiednich domyślnych uprawnień użytkownika. Piaskownica jest prosta, można ją sprawdzić i jest oparta na odseparowaniu procesów i uprawnień plików w stylu UNIX, które ma już kilkadziesiąt lat.
Piaskownica aplikacji znajduje się w jądrze, więc ten model zabezpieczeń obejmuje zarówno kod natywny, jak i aplikacje systemowe. Oprogramowanie znajdujące się nad jądrem, takie jak biblioteki systemu operacyjnego, framework aplikacji, środowisko wykonawcze aplikacji i wszystkie aplikacje, działa w piaskownicy aplikacji. Na niektórych platformach deweloperzy są ograniczeni do określonego frameworku programistycznego, zestawu interfejsów API lub języka. Na Androidzie nie ma żadnych ograniczeń dotyczących sposobu pisania aplikacji, które są wymagane do zapewnienia bezpieczeństwa. W tym zakresie kod natywny jest tak samo bezpieczny jak interpretowany.
Zabezpieczenia
Ogólnie, aby wyjść poza piaskownicę aplikacji na prawidłowo skonfigurowanym urządzeniu, trzeba naruszyć bezpieczeństwo jądra Linuksa. Podobnie jak w przypadku innych funkcji zabezpieczeń, pojedyncze zabezpieczenia stosowane w piaskowniku aplikacji nie są nie do złamania, dlatego ważne jest, aby zapewnić obronę wielowarstwową, która uniemożliwi wykorzystanie pojedynczych luk w zabezpieczeniach do skompromitowania systemu operacyjnego lub innych aplikacji.
Android korzysta z szeregu zabezpieczeń, aby egzekwować piaskownicę aplikacji. Te środki zostały wprowadzone z upływem czasu i znacznie wzmocniły pierwotną piaskownicę kontroli dostępu (DAC) opartą na identyfikatorze UID. Poprzednie wersje Androida zawierały te zabezpieczenia:
- W Androidzie 5.0 SELinux zapewniał obowiązkowe oddzielenie kontroli dostępu (MAC) między systemem a aplikacjami. Jednak wszystkie aplikacje innych firm działały w tym samym kontekście SELinux, więc izolacja między aplikacjami była głównie wymuszana przez UID DAC.
- W Androidzie 6.0 piaskownica SELinux została rozszerzona, aby izolować aplikacje na podstawie granicy fizycznego użytkownika. Android ustawia też bezpieczniejsze domyślne ustawienia danych aplikacji: w przypadku aplikacji z
targetSdkVersion >= 24
domyślne uprawnienia DAC w katalogu domowym aplikacji zmieniły się z 751 na 700. Dzięki temu można było zapewnić bezpieczniejsze domyślne ustawienia prywatnych danych aplikacji (chociaż aplikacje mogą je zastąpić). - W Androidzie 8.0 wszystkie aplikacje były uruchamiane z użyciem filtra
seccomp-bpf
, który ograniczał systemowe wywołania systemowe, z których mogły korzystać aplikacje, wzmacniając w ten sposób granicę między aplikacją a jądrem. - W Androidzie 9 wszystkie nieuprzywilejowane aplikacje z
targetSdkVersion >= 28
muszą działać w poszczególnych piaskownicach SELinux, zapewniając ochronę MAC na poziomie aplikacji. Ta ochrona poprawia oddzielenie aplikacji, zapobiega zastępowaniu bezpiecznych wartości domyślnych i (co jest najważniejsze) uniemożliwia aplikacjom udostępnianie danych na całym świecie. - W Androidzie 10 aplikacje mają ograniczony widok surowego systemu plików, bez bezpośredniego dostępu do ścieżek takich jak /sdcard/DCIM. Aplikacje zachowują jednak pełny dostęp do ścieżek związanych z ich pakietem, zwracanych przez dowolne odpowiednie metody, takie jak Context.getExternalFilesDir().
Wytyczne dotyczące udostępniania plików
Ustawienie danych aplikacji jako dostępnych dla wszystkich jest nieodpowiednią praktyką bezpieczeństwa. Dostęp jest przyznawany wszystkim, a nie można ograniczyć go tylko do wybranych odbiorców. Ta praktyka doprowadziła do wycieków informacji i niejasnych luk w zabezpieczeniach. Jest to ulubiony cel złośliwego oprogramowania, które atakuje aplikacje z danymi wrażliwymi (takie jak klienci poczty e-mail). W Androidzie 9 i nowszych udostępnianie plików w ten sposób jest wyraźnie zabronione w przypadku aplikacji z uprawnieniami targetSdkVersion>=28
.
Zamiast udostępniać dane aplikacji na całym świecie, podczas udostępniania plików postępuj zgodnie z tymi wytycznymi:
- Jeśli aplikacja musi udostępniać pliki innej aplikacji, użyj dostawcy treści. Dostawcy treści udostępniają dane z odpowiednią szczegółowością i bez wielu wad uprawnień UNIX dostępnych dla wszystkich (szczegółowe informacje znajdziesz w podstawach dotyczących dostawców treści).
- Jeśli w aplikacji są pliki, które powinny być dostępne dla wszystkich (np. zdjęcia), muszą one być plikami multimedialnymi (tylko zdjęcia, filmy i pliki audio) i przechowywane za pomocą klasy MediaStore. (więcej informacji o dodawaniu multimediów znajdziesz w artykule Uzyskiwanie dostępu do plików multimedialnych z pamięci współdzielonej).
Uprawnienia Storage w czasie wykonywania kontrolują dostęp do zbiorów o ścisłym typie za pomocą MediaStore.
Aby uzyskać dostęp do plików o słabo określonym typie, takich jak pliki PDF i klasa MediaStore.Downloads, aplikacje muszą używać intencji takich jak ACTION_OPEN_DOCUMENT
.
Aby włączyć działanie zgodne z Androidem 10, użyj atrybutu requestLegacyExternalStorage
w pliku manifestu i stosuj się do sprawdzonych metod dotyczących uprawnień aplikacji.
- Domyślna wartość flagi w pliku manifestu to
true
w przypadku aplikacji kierowanych na Androida 9 (i starszych). - Wartość domyślna to „fałsz” w przypadku aplikacji kierowanych na Androida 10. Aby tymczasowo zrezygnować z filtrowania widoku pamięci w aplikacjach kierowanych na Androida 10, ustaw wartość flagi pliku manifestu na
true
. - Korzystając z ograniczonych uprawnień, instalator tworzy listę dozwolonych aplikacji do pamięci nieobjętej piaskowni. Aplikacje nieumieszczające się na liście dozwolonych są umieszczane w piaskownicy.