Kategoria OWASP: MASVS-CODE: Jakość kodu
Przegląd
Ryzyko związane z uprawnieniami niestandardowymi pojawia się, gdy definicja uprawnień niestandardowych jest nieprawidłowa lub zawiera błędy, albo gdy w pliku manifestu jest nieprawidłowo używany odpowiedni atrybut android:protectionLevel.
Na przykład można wykorzystać te zagrożenia, tworząc niestandardowe uprawnienie o tej samej nazwie, ale zdefiniowane przez złośliwą aplikację i z zastosowanymi różnymi poziomami ochrony.
Uprawnienia niestandardowe umożliwiają udostępnianie zasobów i funkcji innym aplikacjom. Przykłady uzasadnionego użycia uprawnień niestandardowych:
- Kontrolowanie komunikacji międzyprocesowej (IPC) między co najmniej 2 aplikacjami
- Dostęp do usług innych firm
- Ograniczanie dostępu do udostępnionych danych aplikacji
Wpływ
Wykorzystanie tej luki w zabezpieczeniach może spowodować, że szkodliwa aplikacja uzyska dostęp do zasobów, które pierwotnie miały być chronione. Konsekwencje luki w zabezpieczeniach zależą od chronionego zasobu i uprawnień powiązanych z pierwotną usługą aplikacji.
Ryzyko: błędy w uprawnieniach niestandardowych
W pliku manifestu może być zadeklarowane uprawnienie niestandardowe, ale z powodu błędu w pisowni do ochrony eksportowanych komponentów Androida używane jest inne uprawnienie niestandardowe. Złośliwa aplikacja może wykorzystać aplikacje, w których nazwie uprawnienia występuje błąd pisowni, w jeden z tych sposobów:
- najpierw zarejestrować to uprawnienie,
- Przewidywanie pisowni w kolejnych aplikacjach
Może to umożliwić aplikacji nieautoryzowany dostęp do zasobów lub kontrolę nad aplikacją ofiary.
Na przykład podatna na ataki aplikacja chce chronić komponent za pomocą uprawnieniaREAD_CONTACTS, ale przypadkowo wpisuje je jako READ_CONACTS. Złośliwa aplikacja może zgłosić roszczenie do READ_CONACTS, ponieważ nie jest ona własnością żadnej aplikacji (ani systemu), i uzyskać dostęp do chronionego komponentu. Innym częstym wariantem tej podatności jest android:permission=True. Wartości takie jak true i false, niezależnie od wielkości liter, są nieprawidłowymi danymi wejściowymi w przypadku deklaracji uprawnień i są traktowane podobnie jak inne błędy w pisowni deklaracji uprawnień niestandardowych. Aby rozwiązać ten problem, zmień wartość atrybutu android:permission na prawidłowy ciąg uprawnień. Jeśli na przykład aplikacja potrzebuje dostępu do kontaktów użytkownika, wartość atrybutu android:permission powinna wynosić android.permission.READ_CONTACTS.
Środki ograniczające ryzyko
Sprawdzanie Lint w Androidzie
Podczas deklarowania uprawnień niestandardowych używaj kontroli lint Androida, aby wykrywać literówki i inne potencjalne błędy w kodzie.
Konwencja nazewnictwa
Używaj spójnej konwencji nazewnictwa, aby łatwiej zauważać błędy w pisowni. Dokładnie sprawdź deklaracje uprawnień niestandardowych w manifeście aplikacji pod kątem błędów pisowni.
Ryzyko: osierocone uprawnienia
Uprawnienia służą do ochrony zasobów aplikacji. Aplikacja może deklarować uprawnienia wymagane do uzyskania dostępu do zasobów w 2 różnych miejscach:
- AndroidManifest.xml: wstępnie zdefiniowane w pliku AndroidManifest.xml (jeśli nie określono, używane są uprawnienia
<application>), np. provider permission, receiver permission, activity permission, service permission; - Kod: zarejestrowany w kodzie środowiska wykonawczego, np.
registerReceiver().
Czasami jednak te uprawnienia nie są zdefiniowane przez odpowiedni tag
<permission> w pliku manifestu pakietu APK na urządzeniu. W takim przypadku są one nazywane osieroconymi uprawnieniami. Może to nastąpić z kilku powodów, np.:
- Może wystąpić rozbieżność między aktualizacjami w pliku manifestu a kodem ze sprawdzaniem uprawnień.
- Plik APK z uprawnieniami może nie zostać uwzględniony w kompilacji lub może zostać uwzględniona nieprawidłowa wersja.
- Nazwa uprawnienia w sprawdzaniu lub w pliku manifestu może być błędnie napisana.
Złośliwa aplikacja może zdefiniować osierocone uprawnienie i je uzyskać. Jeśli tak się stanie, uprzywilejowane aplikacje, które ufają osieroconemu uprawnieniu w zakresie ochrony komponentu, mogą zostać naruszone.
Jeśli uprzywilejowana aplikacja używa tego uprawnienia do ochrony lub ograniczenia dostępu do dowolnego komponentu, może to umożliwić złośliwej aplikacji dostęp do tego komponentu. Przykłady obejmują uruchamianie działań chronionych przez uprawnienia, uzyskiwanie dostępu do dostawcy treści lub nadawanie do odbiornika chronionego przez osierocone uprawnienia.
Może to również doprowadzić do sytuacji, w której uprzywilejowana aplikacja zostanie oszukana i uzna złośliwą aplikację za legalną, a w konsekwencji załaduje pliki lub treści.
Środki ograniczające ryzyko
Upewnij się, że wszystkie uprawnienia niestandardowe, których aplikacja używa do ochrony komponentów, są również zdefiniowane w pliku manifestu.
Aplikacja używa uprawnień niestandardowych my.app.provider.READ i my.app.provider.WRITE, aby chronić dostęp do dostawcy treści:
XML
<provider android:name="my.app.database.CommonContentProvider" android:readPermission="my.app.provider.READ" android:writePermission="my.app.provider.WRITE" android:exported="true" android:process=":myappservice" android:authorities="my.app.database.contentprovider"/>
Aplikacja definiuje i używa też tych uprawnień niestandardowych, co uniemożliwia to innym złośliwym aplikacjom:
XML
<permission android:name="my.app.provider.READ"/>
<permission android:name="my.app.provider.WRITE"/>
<uses-permission android:name="my.app.provider.READ" />
<uses-permission android:name="my.app.provider.WRITE" />
Ryzyko: nieprawidłowe użycie atrybutu android:protectionLevel
Ten atrybut opisuje potencjalny poziom ryzyka związany z uprawnieniem i wskazuje, jakie procedury powinien zastosować system, aby podjąć decyzję o przyznaniu lub odmowie przyznania uprawnienia.
Środki ograniczające ryzyko
Unikaj normalnego i niebezpiecznego poziomu ochrony
Użycie normalnego lub niebezpiecznego protectionLevel w przypadku uprawnień oznacza, że większość aplikacji może poprosić o przyznanie uprawnień i je uzyskać:
- „normal” wymaga tylko zadeklarowania,
- „niebezpieczne” zostanie zatwierdzone przez wielu użytkowników.
Dlatego te protectionLevels zapewniają niewielkie bezpieczeństwo.
Korzystanie z uprawnień sygnatury (Android ≥ 10)
W miarę możliwości używaj poziomów ochrony sygnatur. Korzystanie z tej funkcji zapewnia, że tylko inne aplikacje podpisane tym samym certyfikatem co aplikacja, która utworzyła uprawnienie, mogą uzyskać dostęp do tych chronionych funkcji. Upewnij się, że używasz dedykowanego (nieużywanego ponownie) certyfikatu podpisywania i przechowuj go w bezpiecznym magazynie kluczy.
Zdefiniuj uprawnienie niestandardowe w manifeście w ten sposób:
XML
<permission
android:name="my.custom.permission.MY_PERMISSION"
android:protectionLevel="signature"/>
Ogranicz dostęp np. do aktywności tylko do tych aplikacji, które mają przyznane to niestandardowe uprawnienie:
XML
<activity android:name=".MyActivity" android:permission="my.custom.permission.MY_PERMISSION"/>
Każda inna aplikacja podpisana tym samym certyfikatem co aplikacja, która zadeklarowała to niestandardowe uprawnienie, uzyska dostęp do działania .MyActivity i musi zadeklarować je w pliku manifestu w ten sposób:
XML
<uses-permission android:name="my.custom.permission.MY_PERMISSION" />
Uważaj na niestandardowe uprawnienia związane z podpisem (Android w wersji starszej niż 10)
Jeśli Twoja aplikacja jest przeznaczona na Androida w wersji starszej niż 10, to za każdym razem, gdy niestandardowe uprawnienia aplikacji zostaną usunięte z powodu odinstalowania lub aktualizacji, złośliwe aplikacje mogą nadal używać tych niestandardowych uprawnień, a tym samym omijać kontrole. Wynika to z luki w zabezpieczeniach związanej z eskalacją uprawnień (CVE-2019-2200), która została naprawiona w Androidzie 10.
Jest to jeden z powodów (obok ryzyka wystąpienia wyścigu), dla których zaleca się sprawdzanie podpisu zamiast korzystania z niestandardowych uprawnień.
Ryzyko: sytuacja wyścigu
Jeśli legalna aplikacja A zdefiniuje niestandardowe uprawnienie podpisu, które jest używane przez inne aplikacje X, ale zostanie później odinstalowana, złośliwa aplikacja B może zdefiniować to samo niestandardowe uprawnienie z innym protectionLevel, np. normal. W ten sposób B uzyskuje dostęp do wszystkich komponentów chronionych przez to uprawnienie niestandardowe w aplikacjach X bez konieczności podpisywania ich tym samym certyfikatem co aplikacja A.
To samo dzieje się, gdy B zostanie zainstalowana przed A.
Środki ograniczające ryzyko
Jeśli chcesz, aby komponent był dostępny tylko dla aplikacji podpisanych tym samym podpisem co aplikacja udostępniająca, możesz uniknąć definiowania niestandardowych uprawnień w celu ograniczenia dostępu do tego komponentu. W takiej sytuacji możesz użyć weryfikacji podpisu. Gdy jedna z Twoich aplikacji wysyła żądanie do innej, ta druga może przed jego wykonaniem sprawdzić, czy obie aplikacje są podpisane tym samym certyfikatem.
Zasoby
- Minimalizuj prośby o uprawnienia
- Omówienie uprawnień
- Opis poziomów ochrony
- CustomPermissionTypo Android Lint
- Korzystanie z narzędzia Android Lint
- Publikacja naukowa z dokładnym wyjaśnieniem uprawnień Androida i ciekawymi wynikami testów fuzzingowych