Zpět na seznam článků     Číst komentáře (9)     Verze pro tisk

Skrytí oprávnění v Androidu (CVE-2019-2089)

Autor: .cCuMiNn.   
1.3.2020

Jeden ze základních bezpečnostních prvků operačního systému Android je propracovaný systém oprávnění, který aplikacím zabraňuje přistupovat ke chráněným rozhraním bez předchozího souhlasu uživatele. Pojďme se v tomto článku podívat na to, jak na nerootnutém Android zařízení zprovoznit aplikaci s libovolnými oprávněními, které zůstanou očím uživatele skryty.


Požadavky na úspěšný útok

  • Cílový systém Android od 6.0 do 9.0
  • TargetSdkVersion < 23
  • Fyzický přístup k zařízení, nebo instalace z neznámého zdroje

Pár slov o aplikačním sandboxingu

Vzhledem k tomu, že je v Androidu sandboxing uplatňován na aplikace (na rozdíl od běžného Linuxu, kde je sandboxing uplatňován na uživatele), chová se každá nainstalovaná aplikace jako nový uživatel, který nemá přístup k datům a paměti jiné aplikace. Vždy, když nainstalujete novou aplikaci, je jí přiděleno nové UID a je vytvořen adresář pro data, jehož vlastníkem se tato aplikace stává. Aplikace díky tomu jako jediná získává právo pro čtení jejích dat.

Výpis příkazu ls -l
generic_x86_64:/data/data # ls -l

drwx------ 3 u0_a66 u0_a66 4096 2020-03-01 13:22 cz.soom.app1
drwx------ 3 u0_a65 u0_a65 4096 2020-03-01 13:22 cz.soom.app2


Na nových víceuživatelských systémem je situace ještě trochu komplikovanější, ale pro náše účely můžeme tyto skutečnosti vynechat.

Nově nainstalovaná aplikace přidá záznam do jednoho z klíčových souborů Androidu, kterým je package databáze data/system/pacakges.xml.

Můžete si všimnout, že je v tomto souboru přiřazeno aplikaci její userId.

Zkrácený výpis souboru packages.xml

<package name="cz.soom.app1" … userId="10066"></package>
<package name="cz.soom.app2" … userId="10065"></package>


Vždy, když konkrétní aplikaci spustíte, běží nově vytvořený proces pod jejím uid, čím má spuštěná aplikace umožněn přístup pouze ke svým vlastním datům.

Zkrácený výpis běžících procesů příkazem ps
generic_x86_64:/ # ps

system    1332  1     14148  3192  binder_thr 71d4ba39a7a7 S /system/bin/fingerprintd
system    1333  1     13116  3092  binder_thr 7eb17dd537a7 S /system/bin/gatekeeperd
u0_a65    3806  1318  1418976 53920    ep_poll 7e240b0f166a S cz.soom.app2
u0_a66    3910  1318  1417928 54012    ep_poll 7e240b0f166a S cz.soom.app1


SharedUserId

Pokud se podíváte na výpis příkazu ps, můžete si všimnout, že některé procesy běží pod shodným uid. Toto se týká hlavně systémových procesů. Není ovšem problém si vytvořit více svých vlastních aplikací běžících pod sdíleným uživatelem. Stačí tuto skutečnost uvést v Android Manifestu pomocí atributu android:sharedUserId="cz.soom.shareduser"

Výpis souboru AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="cz.soom.shared1"
   android:sharedUserId="cz.soom.shareduser">

    <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Vytvoříte-li druhou aplikaci, se stejným sharedUserId a po instalaci obou aplikací prozkoumáte obsah souboru packages.xml, zjistíte, že v něm přibyl element shared-user, který definuje nově vzniklého sdíleného uživatele, a že tento sdílený uživatel byl nastaven oběma aplikacím.

Zkrácený výpis souboru packages.xml

<package name="cz.soom.shared1" … sharedUserId="10067"></package>
<package name="cz.soom.shared1" … sharedUserId="10067"></package>

<shared-user name="cz.soom.shareduser" userId="10067"></shared-user>

Výpis příkazu ls -l
generic_x86_64:/data/data # ls -l
…                            
drwx------ 3 u0_a67 u0_a67 4096 2020-03-01 13:33 cz.soom.shared1
drwx------ 3 u0_a67 u0_a67 4096 2020-03-01 13:33 cz.soom.shared2

Zkrácený výpis běžících procesů příkazem ps
generic_x86_64:/         # ps

u0_a67    4047  1318  1417928 54132    ep_poll 7e240b0f166a S cz.soom.shared2
u0_a67    4132  1318  1418976 54208    ep_poll 7e240b0f166a S cz.soom.shared1


Oba procesy nyní při spuštění běží pod shodným UID a mohou si tak vzájemně přistupovat ke svým zdrojům.

Poznámka: Aplikace, které spolu chtějí sdílet zdroje, tedy běžet pod stejným uživatelem musí být podepsány stejným klíčem. Není tedy možné svou aplikaci přidružit k jiným například systémovým aplikacím.

Oprávnění v Androidu

Každé oprávnění v Androidu ke všem akcím, které chce aplikace používat, musí být deklarováno v Android Manifestu.

Výpis souboru AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="cz.soom.app1">

    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
   
    <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Od Androidu verze 6.0 se oprávnění udělují aplikaci za běhu až před jeho prvním použitím a toto je pak zaznamenáno v souboru /data/system/users/[userId]/runtime-permissions.xml pro každého uživatele separátně. Před Androidem 6.0 se ovšem všechna oprávnění musela schválit již během instalace, nebo se instalace musela přerušit. Na těchto starších systémech se seznam udělených oprávnění zapsal k aplikaci do package databáze, tedy do souboru packages.xml.

Zkrácený výpis souboru packages.xml

<package name="cz.soom.app1" … userId="10068">
    <perms>
        <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="0" />
        <item name="android.permission.SEND_SMS" granted="true" flags="0" />
        <item name="android.permission.WRITE_CONTACTS" granted="true" flags="0" />
    </perms>
</package>


Na Androidech vyšších verzí než 6.0 je možné si vynutit udělení všech oprávnění při instalaci a jejich zápis do package databáze nastavením targetSdkVersion, které bude menší než 23. Takto zkompilovaná aplikace se bude i na nejnovějších adroidech chovat tak, jako by byla instalována na starších verzích systému. Jedinou nevýhodou je, že takto zkompilovanou aplikaci nebude možné distribuovat přes Google Play, neboť v současné chvíli je pro upload na Google Play vyžadováno targetSdkVersion 26 a vyšší.

Udělená oprávnění jsou nyní dohledatelná v zařízení

Oprávnění aplikace App1 Aplikace s oprávněním SMS

Permissions a SharedUserId

Zajímavé je sledovat, jak k oprávněním přistupují aplikace běžící pod sdíleným uživatelem. Vytvořím proto aplikaci shared1, která ve svém Android Manifestu nežádá o žádné oprávnění, ale ve svém kódu se pokouší odeslat SMS na zadané telefonní číslo. Pokud tuto aplikaci spustíte, dojde dle očekávání k jejímu zhroucení.

Nýní si vytvoříme druhou aplikaci shared2 běžící pod stejným uživatelem, která sice nic nedělá, ale při instalaci si nechá přidělit oprávnění pro odeslání SMS zprávy.

Když nyní použijeme aplikaci shared1 zjistíme, že již může bez problémů SMS zprávu odeslat, přestože k tomu patřičná oprávnění při instalaci nedostala.

Oprávnění aplikace Shared1

Proč tomu tak je, nám zodpoví pohled do souboru packages.xml.

Zkrácený výpis souboru packages.xml

<package name="cz.soom.shared1" … sharedUserId="10067">
    <perms>
        <item name="android.permission.SEND_SMS" granted="true" flags="0" />
    </perms>
</package>
<package name="cz.soom.shared2" … sharedUserId="10067">
    <perms>
        <item name="android.permission.SEND_SMS" granted="true" flags="0" />
    </perms>
</package>

<shared-user name="cz.soom.shareduser" userId="10067">
    <perms>
        <item name="android.permission.SEND_SMS" granted="true" flags="0" />
    </perms>
</shared-user>


Můžete si všimnout, že při použití sdílených uživatelů je oprávnění přiděleno nejen aplikaci, ale i samotnému účtu sdíleného uživatele, prostřednictvím kterého je oprávnění uděleno i ostatním apliacim se stejným sharedUserId.

Zajímavé je, že když se podíváte na jednotlivá oprávnění, vidíte je pouze u té aplikace, která je deklarovala ve svém Android manifestu.

Oprávnění aplikace Shared1 Oprávnění aplikace Shared2 Aplikace s oprávněním SMS

Pokud nyní odinstalujete aplikaci shared2 a pokusíte se použít aplikaci shared1 k odeslání SMS zprávy, zjistíte, že se aplikace opět zhroutí. Po odinstalování aplikace shared2 se totiž odebrala oprávnění i ostatním aplikacím, které je sami nedeklarovaly.

O chybě CVE-2019-2089

Testováním jsem zjistil, že pokud je aplikaci shared2 uděleno oprávnění android.permission.BLUETOOTH, všechna další oprávnění, které aplikace shared2 deklarovala v Android Manifestu za oprávněním bluetooth, zůstanou aplikaci shared1 přidělena i po odinstalaci aplikace shared2.

Vytvořím tedy aplikaci shared3, která bude mít Android Manifest následujícího znění:


Výpis souboru AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="cz.soom.shared3"
   android:sharedUserId="cz.soom.shareduser">

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.SEND_SMS" />
   
    <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Když nyní nainstaluji aplikace shared1 a shared3, přičemž aplikaci shared3 ihned po instalaci zase odinstaluji, vypadá obsah souboru packages.xml následovně:

Zkrácený výpis souboru packages.xml

<package name="cz.soom.shared1" … sharedUserId="10067">
    <perms>
        <item name="android.permission.SEND_SMS" granted="true" flags="0" />
    </perms>
</package>

<shared-user name="cz.soom.shareduser" userId="10067">
    <perms>
        <item name="android.permission.SEND_SMS" granted="true" flags="0" />
    </perms>
</shared-user>


Podíváte-li se v zařízení na oprávnění jednotlivých aplikací, zjistíte, že žádná z nich nemá oprávnění pro odesílání SMS.

Oprávnění aplikace Shared1 Aplikace s oprávněním SMS

Pokud však aplikaci shared1 použijete, budete pravděpodobně překvapeni, protože s odesíláním SMS zpráv nebude mít vůbec žádný problém. Stejným způsobem je možné aplikaci udělit jakékoliv oprávnění, například odposlech mikrofonu, použití fotoaparátu, sledovaní GPS polohy, apd.

Možnosti zneužití

Z toho, co bylo uvedeno výše, vyplývá, že zneužití je limitováno hlavně nemožností distribuce vytvořených aplikací skrze Google Play. Útočník by tak musel získat fyzický přístup k vašemu zařízení, aby byl schopen do něj útočnou aplikaci nainstalovat z neznámého zdroje, nebo by musel použít sociotechniku a přinutit pomocí ní svou oběť k takové instalaci.

Další možnosti zneužití se pak nabízí na zařízeních s více uživatelskými účty, kdy by instalace podobné aplikace jedním uživatelem mohla mít vliv na další uživatele systému.

V neposlední řadě se v historii objevila také možnost přerušit aktivaci a konfiguraci zařízení při prvním spuštění tak, aby se při dalším spuštění tato aktivace opět vyvolala. Hrozí tak zneužití ze strany nepoctivých prodejců, kteří vám mohou prodat nové zařízení s předinstalovanou špionážní aplikací bez toho, aby museli zasahovat do nainstalovaného systému.

Co na to Google

Společnosti Google jsem zranitelnost hlásil prostřednictvím jejich Bug Bounty programu v září 2018.

Zranitelnost byla Googlem ohodnocena střední závažností a bylo jí přiřazeno CVE-2019-2089.

Zranitelnost byla odstraněna v Androidu 10 v září 2019, přičemž verze 6.0 až 9.0 zůstávají i nadále náchylné na popsaný typ útoku.

Pokud jste majiteli postižených verzí, měli byste si svá zařízení chránit před neoprávněným přístupem, protože stačí pouze pár vteřin na nainstalování útočné aplikace, která vás bude následně špehovat bez toho, abyste tato oprávnění byli schopni odhalit.


TIP:
Nemáte zkušenosti s etickým hackingem? Zvažte školení Hacking v praxi od Root.cz Další zajímavé IT školení najdete zde https://www.root.cz/skoleni/


Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.56/48

1  2  3  4  5    
(známkování jako ve škole)