Android-Apps auf dem Seziertisch: Eine vertiefte Betrachtung

1. Was ist drin?Android APK-Checks

Apps bieten uns verschiedenste Funktionalitäten. Wir nutzen Apps, weil wir diese Funktionalitäten benötigen. Nicht immer ist jedoch klar, welches „Beiwerk“ wir uns gegebenenfalls mit „einfangen“.

Aufmerksame Leser des Kuketz-Blogs kennen natürlich bereits einige Möglichkeiten, sich diesbezüglich zu informieren, bzw. entsprechende Vorkehrungen zu treffen. So installiert Ihr beispielsweise Eure Apps vorwiegend von F-Droid oder aus meinem F-Droid Repo – beides Quellen, zu denen nur Open-Source-Apps Zugang haben und bei denen die jeweiligen Betreiber entsprechende Schutzmaßnahmen ergreifen bzw. ergriffen haben. Dennoch dürfte es für Euch interessant sein, wie dort und mit welchem Wasser gekocht wird. Nicht zuletzt um zu verstehen, welche Aspekte ggf. fehlen – 100% Sicherheit gibt es bekanntlich nicht nur in der IT nicht.

Einiges wurde Euch hier in der Vergangenheit bereits vorgestellt, und sei daher für den Gesamtblick nochmals erwähnt:

Der APK Library Scanner ist nach wie vor in meinem F-Droid Repo im Einsatz, seine Signaturen werden regelmäßig aktualisiert. Und Ihr könnt ihn nach wie vor auch selbst einsetzen, da er als Open Source Produkt frei verfügbar ist.

Sowohl bei Exodus Privacy als auch bei meinem APK Library Scanner ging es in erster Linie um in den APK Dateien enthaltene Bibliotheken. Darauf aufbauend, möchte ich Euch heute weitere Methoden vorstellen – die u. a. in meinem F-Droid Repo zum Einsatz kommen.

Gastbeitrag von Andreas Itzchak Rehberg

Itzchak, auch bekannt als IzzyOnDroid, betreibt sein eigenes F-Droid Repository, bietet Schulungen und Workshops an und ist freier Autor für das ct Magazin.

Feedback und Fragen können direkt an ihn gerichtet werden. Er freut sich auch über Spenden für seine Arbeit.

2. Android Manifest

Wikipedia beschreibt den Begriff „Manifest“ einleitend wie folgt:

Ein Manifest (von lateinisch *manifestus* ‚handgreiflich gemacht‘, ‚offenbart‘) ist eine öffentliche Erklärung von Zielen und Absichten

Android-Apps enthalten in der Regel gleich mehrere Manifeste in ihrer APK Datei, von der uns an dieser Stelle hauptsächlich eine Datei namens AndroidManifest.xml interessieren soll. In dieser werden sozusagen die Ziele und Absichten der zugehörigen App deklariert:

  • Name und Version der App
  • welche Berechtigungen sie verlangt
  • welche Komponenten (Aktivitäten, Services etc.) sie bereitstellt
  • und einiges mehr

In der APK Datei selbst liegt dieses AndroidManifest.xml in binärer Form („AXML“) vor, das sich aber z. B. mittels androguard axml <datei.apk> extrahieren und sodann analysieren lässt.

Unterstütze den Blog mit einem Dauerauftrag!

Unabhängig. Kritisch. Informativ. Praxisnah. Verständlich.

Die Arbeit von kuketz-blog.de wird vollständig durch Spenden unserer Leserschaft finanziert. Sei Teil unserer Community und unterstütze unsere Arbeit mit einer Spende.

Mitmachen ➡

2.1 Flags/Attribute

Das AndroidManifest definiert Application Elements, welche ich hier kurz als „Flags“ bezeichnen möchte. Diese sagen einiges über das Verhalten der App aus, und es gibt eine ganze Reihe davon – etwa in welche Kategorie eine App gehört, ob sie Backups ihrer Daten erlaubt, mit welchem Icon sie im App-Drawer präsentiert werden möchte, und mehr. Für das Thema „Sicherheit und Privatsphäre“ wären davon hauptsächlich drei Flags interessant:

  • android:debuggable: Dies ist sozusagen ein zweischneidiges Schwert. Einerseits ermöglicht es uns dieses Flag, die Anwendungsdaten der App auch unter Android 12 zu sichern – andererseits stellt es auch ein gewisses Sicherheitsrisiko dar, da sich mit Debug-Informationen teilweise auch sensible Informationen auslesen ließen, auf die man sonst von Außen keinen Zugriff hätte. Was natürlich hauptsächlich dann relevant wird, wenn Dritte Euer Gerät in die Finger bekommen. Dieses Flag ist für die Phase der App-Entwicklung gedacht. Normalerweise sollte eine App, die für die Weitergabe bestimmt ist, es daher nicht aufweisen. Hat der Entwickler dies vergessen, gibt es vielleicht auch noch andere „vergessene Dinge“ bzw. die App war eigentlich (noch) gar nicht zur Verteilung gedacht.
  • android:testOnly: Dieses Flag ähnelt stark dem vorigen. Die Dokumentation schreibt dazu, grob übersetzt: „Dieses Attribut gibt an, ob diese Anwendung nur zu Testzwecken dient. Sie könnte beispielsweise Funktionen oder Daten außerhalb ihrer selbst preisgeben, die eine Sicherheitslücke verursachen können, aber für Tests nützlich sind.“ Eine solche App habe ich bislang nicht gesichtet – aber „Vorsicht ist die Mutter der Porzellankiste“, oder so. Besser keine Elefanten hereinlassen.
  • android:usesCleartextTraffic: Internet-Traffic sollte verschlüsselt sein. Im Web-Browser bedeutet dies: https://. Ist android:usesCleartextTraffic aktiviert heißt dies, die App möchte auch unverschlüsselte Verbindungen nutzen. Hier gilt es genau nachzuschauen, wofür. Für Zugriffe innerhalb des Heimnetzes (etwa auf den selbst gehosteten Medienserver) ist es völlig OK – hier wäre es ja auch schwierig, ein valides Zertifikat erstellt zu bekommen, da dieser Server in der Regel ja von außen nicht erreichbar ist (und auch nicht sein soll). Werden allerdings (sensible) Daten unverschlüsselt ins „offene Netz“ übertragen, ist das mehr als nur fahrlässig – da es u. a. die Gefahr von MITM und das damit verbundene Abgreifen Eurer Daten durch unbefugte deutlich erhöht. „Der Hauptgrund für die Vermeidung von Klartextverkehr ist der Mangel an Vertraulichkeit, Authentizität und Schutz vor Manipulationen. Ein Angreifer im Netz kann die übertragenen Daten abhören und auch verändern, ohne entdeckt zu werden.“

2.2 Intent Filter

Bei den Intent Filtern verhält es sich ähnlich wie mit den Flags. Das Wort „Intent“ heißt ja so viel wie „Absicht“; sie geben somit an, was die App möglicherweise beabsichtigt. Und auch hier möchte ich aus der Reihe der Möglichkeiten nur diejenigen herausgreifen, die mir bislang als „sensibel“ aufgefallen sind – und die somit bei Apps in meinem Repo Warnungen auslösen, solange ihre Berechtigung ungeklärt ist:

  • android.accessibilityservice.AccessibilityService: Hier möchte eine App sich Android’s AccessibilityService zunutze machen. Das ist jetzt nicht unbedingt etwas Schlechtes oder Gefährliches, bietet aber deutliches Missbrauchspotential. Einige Aktionen werden bewusst implementiert, um sicherzustellen, dass sie von dem Menschen, der das Gerät bedient, direkt ausgeführt werden und nicht von einer App hinter seinem Rücken. AccessibilityServices ermöglichen, dies zu automatisieren (um „Benutzer mit Behinderungen bei der Nutzung von Android-Geräten und -Apps zu unterstützen“), sodass sichergestellt werden sollte, dass eine App sie auf verantwortungsvolle Weise nutzt.
  • android.net.VpnService: Wie der Name es bereits vermuten lässt, möchte diese App Android‘s VpnService nutzen – was auch das Abfangen des Netzwerk-Traffics ermöglicht. Dies sollte ausschließlich VPN-Apps vorbehalten sein – mit Ausnahmen für Apps wie NetGuard, Tracker Control und ähnlichen nicht-root-voraussetzenden Werbeblockern und Firewalls.
  • android.view.InputMethod: Eine Input-Methode (IME; Eingabemethode) ist etwas, mit dem Benutzereingaben erfasst werden – am bekanntesten sicher Tastatur-Apps wie AnySoftKeyboard oder HeliBoard, aber auch QR-Code Scanner zur Inventarisierung können dies nutzen. Und nur solchen Apps sollte dies auch vorbehalten sein.

2.3 Berechtigungen

Auch die Berechtigungen, die eine App gern haben möchte, werden im AndroidManifest.xml deklariert und lassen sich somit hier auslesen. Manche davon sind eher „harmlos“ – andere sollten als „sensitiv“ betrachtet werden. So habe ich in meinem Repo eine Liste solch „sensitiver Berechtigungen“ angelegt, bei denen Warnungen ausgelöst werden. Etwa beim Zugriff auf persönliche Daten (Kontakte, Kalender, Storage, dem Auflisten, Installieren oder Löschen von Apps (auch „unschuldige Selbst-Updater“ würden sich ja an meinen Scans vorbeischleichen), und einige mehr. Diese Liste ist nicht „in Stein gemeißelt“ und kann sich mit der Zeit ändern.

Wie bei den Flags und den Intent Filtern, lösen diese sensiblen Berechtigungen zunächst eine Warnung aus – und werden sodann für die betroffene App geprüft. Passen sie zur Funktionalität, werden sie mit einer Begründung versehen und somit „erlaubt“ (keine weiteren Warnungen bei zukünftigen Updates) – andernfalls bleibt die Warnung bestehen, bis die Entwickler nachgebessert haben. Im schlimmsten Fall kann auch eine Entfernung der App aus meinem Repo erfolgen – etwa bei erzwungenen Selbst-Updatern.

3. Zertifikate und Signaturen

Eine App muss von ihren Entwicklern signiert sein, sonst verweigert Android die Installation. Für das Signieren benötigt man ein Zertifikat, das man sich allerdings selbst erstellen kann. Dieses muss man jedoch für zukünftige Updates beibehalten. Andernfalls wird das Update mit der Fehlermeldung „Signature mismatch“ abgewiesen. So soll sichergestellt werden, dass die Aktualisierungen auch aus „autorisierter Quelle“ erfolgen. Weshalb diese Zertifikate in meinem F-Droid Repository auch für jede App „gepinnt“ sind: Stimmt die Signatur nicht überein, gelangt eine solche APK-Datei also gar nicht erst in den Index – und kann also auch nicht für eine Neuinstallation genutzt werden.

Nun gibt es zwei verschiedene Arten von Zertifikaten (auch als „Signierschlüssel“ bezeichnet). Debug-Zertifikate sind für die Entwicklung selbst gedacht, nicht jedoch für den „Vertrieb“ – und Release-Zertifikate für die Apps, die zur Nutzung für die Allgemeinheit freigegeben wurden. Wer sich für Hintergründe interessiert, warum eine APK-Datei mit Debug-Zertifikat nichts in der „freien Wildbahn“ zu suchen hat, der kann sich u. a. hier informieren:

Erkennen lassen sich Debug-Zertifikate recht einfach an ihrer „DN“:

Signer #1 certificate DN: C=US, O=Android, CN=Android Debug

Und wer sich die Zertifikate einer APK-Datei selbst einmal anschauen möchte, kann dies mithilfe von apksigner oder (für ältere Apps) jarsigner tun:

  • apksigner verify --verbose --print-certs <datei.apk>
  • jarsigner -verify -verbose -certs <datei.apk>

4. Signing Blocks & BLOBs

Eine letzte Prüfung, die ich Euch hier vorstellen möchte, betrifft den Bereich, der die Signaturinformationen der App beinhaltet. Und hier wird es ein wenig technischer…

In den sogenannten „Signing Blocks“ findet sich ggf. deutlich mehr als nur etwa Signatur-Informationen. Und so wies mich Fay darauf hin, dass es hier mitunter recht merkwürdig zugehen kann. Es finden sich hier natürlich Dinge, die hier auch hingehören und die man hier vermuten würde:

OK_BLOCKS = dict(
    # https://source.android.com/docs/security/features/apksigning/v2#apk-signing-block-format
    APK_SIGNATURE_SCHEME_V2_BLOCK=0x7109871a,
    APK_SIGNATURE_SCHEME_V3_BLOCK=0xf05368c0,
    APK_SIGNATURE_SCHEME_V31_BLOCK=0x1b93ad61,
    VERITY_PADDING_BLOCK=0x42726577,
)

Daneben aber leider auch noch einiges andere, was für Open-Source Apps eher nicht zuträglich ist:

  • DEPENDENCY_INFO_BLOCK: Dies soll eine binäre Darstellung der build dependencies sein – also was bei der App zur Erstellung zum Einsatz kam. Dummerweise ist es mit einem Public Key verschlüsselt, der Google gehört – sodass nur Google selbst dies lesen und mit Sicherheit sagen kann, was dort wirklich drin ist. Für alle anderen ist dies ein opaker „BLOB“ (Binary Large OBject). Eingefügt wird dieser beim Signieren der App – also entweder von Google selbst nach dem Hochladen in den PlayStore, oder aber von Software wie Android Studio oder IntelliJ IDEA. Entwickler haben zum Glück relativ einfache Möglichkeiten, dies zu vermeiden – welche ich ihnen beim Auffinden dieses BLOBs auch jeweils nahelege.
  • GOOGLE_PLAY_FROSTING_BLOCK: Wem es beim Namen fröstelt: Ja, dieser BLOB ist nur für den PlayStore interessant. In der Open-Source-Welt haben wir dafür keine Verwendung. Trifft man diesen also an weiß man: Die APK stammt aus dem PlayStore. Ein Post bei StackOverflow gibt ein wenig Hintergrund dazu, das Wesentliche übersetzt: „Der Frosting-Block wird vom Play Store hinzugefügt, was beweist, dass eine bestimmte Datei aus dem Play Store heruntergeladen wurde […] Seltsamerweise enthält das Frosting einen Metadaten-Chunk, der mit protbuf kodiert ist. Die Struktur ist ziemlich komplex …“
  • Zu SOURCE_STAMP_V1_BLOCK und SOURCE_STAMP_V2_BLOCK finden sich Informationen in den Kommentaren der Quellcode-Datei SourceStampVerifier.java. Ich übersetze den wesentlichen Teil mal schnell mit DeepL: „SourceStamp verbessert die Rückverfolgbarkeit von Apps im Hinblick auf eine nicht autorisierte Verbreitung. Der Stempel ist Teil der APK, die durch den Signierblock geschützt ist. Der Hash des APK-Inhalts wird mit dem Stempelschlüssel signiert und als Teil des Signierblocks gespeichert.“ In der Open-Source-Welt stehen die Apps unter freien (libre) Lizenzen, und die Four Essential Freedoms of Free Software sind garantiert. Diese beinhalten u. a. „The freedom to redistribute copies so you can help your neighbor“ (freedom-2) und „The freedom to distribute copies of your modified versions to others“ (freedom-3). So etwas wie „nicht autorisierte Verbreitung“ kann es da also nicht geben, womit für diese Blöcke auch kein Bedarf besteht.

Bis hierhin schaut es noch fast ein wenig harmlos aus. Bei meinen Recherchen stieß ich aber noch auf einen weiteren Block:

  • MEITUAN_APK_CHANNEL: Hier hat die chinesische Firma Meituan einen Weg gefunden, Payload in den Signing Blöcken unterzubringen. Einen Beleg für diesen Block findet Ihr hier – und einen Beleg dafür, dass er für Payload (in diesem Fall in Form von JSON) verwendet wird, hier. Payload in einem Signing Block darf durchaus als Sicherheitsrisiko angesehen werden, weshalb man hier wachsam sein sollte.

Ja aber, Scanner würden so etwas doch sicherlich finden und Alarm schlagen? Leider ist mir außer dem bei mir verwendeten Scanner (der von Fay und mir entwickelt wurde) kein weiterer bekannt, der dies täte (einzig Pithus gibt einen „sanften Hinweis“). Was noch weitaus schlimmer ist: In einem Versuch konnte Fay in eine bestehende, signierte APK Datei, von der sie den Signierschlüssel nicht hatte, einmal einen Signierblock mit der EICAR Testdatei und einmal mit einem beliebigen ELF Binary unterbringen. Eine anschließende Prüfung bescheinigte der so manipulierten APK-Datei, dass sie ordnungsgemäß signiert sei – als wäre die Datei so vom Entwickler gekommen. Und auch die Malware-Scanner zeigten sich unbeeindruckt: nur 2 der 64 Scanner bei VirusTotal bemerkten das EICAR Sample. Kein einziger hingegen das ELF Binary. Fay’s ursprünglichen POC findet Ihr bei Github.

Aber die entsprechenden Blöcke sollten sich doch erkennen lassen?!? Theoretisch schon. Stellt man es schlau an, bemerken aber weder Androguard noch apksigner etwas. Beide gehen nämlich davon aus, dass eine BlockID nur jeweils einmal pro APK-Datei vorkommen kann. Dummerweise ist dem aber nicht so. Und da einer der beiden einfach nur den ersten und der andere nur den letzten Treffer wahrnimmt, braucht man nur die gleiche ID dreimal verwenden, und seinen „Payload“ in die Mitte zu legen. Der bei IzzyOnDroid verwendete Scanner würde dann jedoch melden, dass eine ID (und welche) mehrfach genutzt wurde, und somit Alarm schlagen.

5. Welche Checks sind wo umgesetzt?

Check F-Droid IzzyOnDroid
LibraryCheck limited¹ ja²
*.jar/*.aar³ ja nein
Manifest Flags nur debuggable ja
Intent Filter nein ja
Berechtigungen nur manuell⁴ ja
Self-Updater nein ja⁵
Zertifikate nein⁶ ja
Zertifikat-Pinning teilweise⁷ generell
Signing Blocks nein ja
Live-/Verhaltenschecks teilweise⁸ nein
VirusTotal ja ja
Exodus Privacy ja⁹ nein¹⁰
APK-Quelle selbst aus Quellcode erstellt vom Entwickler bereitgestellt

¹ hardcoded in fdroidserver („usual suspects“) plus einige Definitionen aus F-Ddroid SUSS
² ständig gepflegte Signaturliste
³ externe Bibliotheken als Binärdateien, ohne dass der Quellcode zur Verfügung steht. Im IzzyOnDroid Repo implizit durch den APK Library Check mit abgedeckt.
⁴ i. d. R. nur bei Erstaufnahme
⁵ anhand der Berechtigung REQUEST_INSTALL_PACKAGES sowie Updater-Bibliotheken
⁶ F-Droid signiert überwiegend selbst. Nur bei reproducible builds Übernahme vom Entwickler
⁷ nur bei reproducible builds
⁸ üblicherweise manuell bei Neuaufnahme der App (und nur dann)
⁹ durch IzzyOnDroid automatisiert eingereicht. Automatisierte Prüfung durch F-Droid nur bei Neuaufnahme einer App
¹⁰ Exodus Privacy unterstützt leider das IzzyOnDroid Repository (noch?) nicht

6. Fazit

Um die Sicherheit und Konfiguration einer App zu beurteilen, reicht es leider nicht, die APK-Datei durch einen Malware-Scanner zu jagen – dafür sind weitere Prüfungen notwendig, die dort leider i. d. R. nicht stattfinden. Die technisch versierten unter Euch können dies, wie aufgezeigt, durchaus selbst machen; alle anderen müssen sich darauf verlassen, dass dies an der Quelle ihrer Apps geschieht. Insbesondere bei der Prüfung der Signaturblöcke gibt es da jedoch deutlichen Nachbesserungsbedarf.

Bildquellen:

Apk: Freepik from www.flaticon.com is licensed by CC 3.0 BY

Über den Autor | Gastbeitrag

Gastbeiträge werden von Autoren verfasst, die nicht zum festen Redaktionsteam des Kuketz-Blogs gehören. Bevor ein Gastbeitrag veröffentlicht wird, findet eine inhaltliche Abstimmung mit mir statt. Dabei übernehme ich die redaktionelle Bearbeitung des Textes, prüfe den Inhalt und bereite den Beitrag sorgfältig für die Veröffentlichung im Blog vor.

Gastbeitrag ➡

SpendeUnterstützen

Die Arbeit von kuketz-blog.de wird zu 100% durch Spenden unserer Leserinnen und Leser finanziert. Werde Teil dieser Community und unterstütze auch du unsere Arbeit mit deiner Spende.

Folge dem Blog

Wenn du über aktuelle Beiträge informiert werden möchtest, hast du verschiedene Möglichkeiten, dem Blog zu folgen:

Bleib aktuell ➡


Diskussion

Ich freue mich auf Deine Beteiligung zum Artikel

HilfeWenn du Ergänzungen oder konkrete Fragen zum Beitrag hast, besuche das offizielle Forum. Dort kann der Beitrag diskutiert werden. Oder besuche den Chat, um dein Anliegen zu besprechen. zur Diskussion ➡

Abschließender Hinweis

Blog-Beiträge erheben nicht den Anspruch auf ständige Aktualität und Richtigkeit wie Lexikoneinträge (z.B. Wikipedia), sondern beziehen sich wie Zeitungsartikel auf den Informationsstand zum Zeitpunkt des Redaktionsschlusses.

Kritik, Anregungen oder Korrekturvorschläge zu den Beiträgen nehme ich gerne per E-Mail entgegen.