Mastodon IzzyOnDroid


Say thanks!
Privacy Links
↓ Your product here? ↓
Das inoffizielle Android-HandbuchDas inoffizielle Android-Handbuch
Für 16,99 € bei Amazon kaufen
Die Daten, die ich rief: Wie wir unsere Freiheit an Großkonzerne verkaufenDie Daten, die ich rief: Wie wir unsere Freiheit an Großkonzerne verkaufen
Für 9,00 € bei Amazon kaufen
Sie kennen dich! Sie haben dich! Sie steuern dich!: Die wahre Macht der DatensammlerSie kennen dich! Sie haben dich! Sie steuern dich!: Die wahre Macht der Datensammler
Für 9,99 € bei Amazon kaufen
Sie wissen alles: Wie Big Data in unser Leben eindringt und warum wir um unsere Freiheit kämpfen müssen -Sie wissen alles: Wie Big Data in unser Leben eindringt und warum wir um unsere Freiheit kämpfen müssen -
Für 2,76 € bei Amazon kaufen
Android Security CookbookAndroid Security Cookbook
Für 37,99 € bei Amazon kaufen
Android Forensics: Investigation, Analysis and Mobile Security for Google AndroidAndroid Forensics: Investigation, Analysis and Mobile Security for Google Android
Für 57,73 € bei Amazon kaufen
Bitdefender Total Security 2021 1 Gerät / 18 Monate (Code in a Box)|Standard|1|18 Monate|PC/Mac/Android|DownloadBitdefender Total Security 2021 1 Gerät / 18 Monate (Code in a Box)|Standard|1|18 Monate|PC/Mac/Android|Download
Für 40,90 € bei Amazon kaufen
The Android Malware Handbook: Detection and Analysis by Human and MachineThe Android Malware Handbook: Detection and Analysis by Human and Machine
Für 31,99 € bei Amazon kaufen
Penetration Testing with Kali NetHunter: Hands-on Android and iOS penetration testing (English Edition)Penetration Testing with Kali NetHunter: Hands-on Android and iOS penetration testing (English Edition)
Für 39,94 € bei Amazon kaufen
Stand: 2024-07-22 16:41
Preis & Verfügbarkeit können sich geändert haben.
enhelp

Zusätzliche APK-Checks im IzzyOnDroid Repo

Security Lock

Wir verwenden Apps, weil wir ihre Funktionalität schätzen. Aber manchmal enthalten sie auch Komponenten, die wir selbst nicht ausgewählt hätten, wenn man uns gefragt hätte. Teile des Codes, die entweder für die geschätzte Funktionalität der App nicht benötigt werden (wie Werbung oder Tracker) – oder Module, die nicht FOSS sind, wodurch die FOSS-App zu einer „befleckten“ App wird, die streng genommen nicht mehr FOSS ist. Zwei frühere Artikel auf dieser Seite geben einige Einblicke in diese Problematik:

Der im IzzyOnDroid repo verwendete LibraryScanner, welchen der letztgenannte Artikel beschreibt und der unter einer FOSS-Lizenz verfügbar ist, macht transparent, welche Bibliotheken/Module eine APK-Datei enthält. Ein Überblick über die aktuell im IzzyOnDroid Repo eingesetzten Maßnahmen findet sich im Abschnitt What about security? in der Info-Seite des Repos.

Im Januar 2024 wurden zusätzliche Sicherheitsmaßnahmen für das IzzyOnDroid Repository eingeführt. Sie sollen in diesem Artikel nicht nur vorgestellt werden, sondern auch ein paar Hintergrundinformationen erhalten.

Scans des AndroidManifests

Wikipedia beschreibt den Begriff „Manifest“ eingangs wie folgt:

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

an AndroidManifest
Beispiel eines AndroidManifest.xml

In der Anwendungsprogrammierung gibt es etwas ähnliches: die Manifest Datei. 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:

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. Dies geschieht für jede APK-Datei, die in das IzzyOnDroid-Repositorium gelangt, wobei die folgenden Prüfungen durchgeführt werden:

Überprüfen von Flags

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 und daher bei Scans berücksichtigt:

Heikle Berechtigungen

Diese lösen eine Warnung aus, welche eine manuelle Prüfung nach sich zieht. Passen sie zum Einsatzzweck der App und sind für die angepriesene Funktionalität notwending, kommen sie in die „Allow-List“ der App – etwa CONTACTS für eine Adressbuch-App oder CALL_PHONE für einen Dialer. Andere werden im Abschnitt „Berechtigungen“ der entsprechenden APK hervorgehoben - oder können zur Entfernung (bzw. Nichtaufnahme) der App führen. Eine Liste dieser „heiklen“/sensiblen Berechtigungen findet sich in Issue 475 sowie in der entsprechenden Library-Datei. Diese Berechtigungen betreffen sowohl Sicherheitsthemen als auch Fragen des Datenschutzes.

Eine spezielle Berechtigung in diesem Kontext ist REQUEST_INSTALL_PACKAGES, welche üblicherweise auf einen integrierten Selbst-Updater hindeutet – und somit auf eine Verletzung der Aufnahme-Kriterien des Repos, da ein solcher die bestehenden Sicherheitskontrollen umgehen würde. Daher wende ich mich in einem solchen Fall an die jeweiligen Entwicker, um dies zu prüfen (die Berechtigung könnte durchaus anders begründet sein; z. B. könnte ein Dateimanager sie für die Installation lokal gespeicherter APK Dateien brauchen). Sollte es sich tatsächlich um einen Selbst-Updater handeln, bitte ich um ein separates Build-Flavor ohne diesen Selbst-Updater, oder zumindest um die Implementierung eines Opt-In mit entsprechenden Hintergrund-Informationen, wie es die Beispiel-Screenshots der App RiMusic unter diesem Absatz zeigen. Ausnahmen davon gibt es nur sehr selten – etwa für dedizierte Test-Versionen von Apps, etwa „beta channels“, die dann aber auch klar als solche erkennbar sein müssen. Bislang stießen meine diesbezüglichen Anfragen weitgehend auf Verständnis.

Opt-In 1 Opt-In 2
Opt-In: Korrektes Einholen der Zustimmung mit Angabe des Kontexts
(ein Klick auf die Screenshots vergrößert diese)

Sensible Berechtigungen werden manuell überprüft, bevor eine neue App zum Repo hinzugefügt wird, aber auch automatisch bei jeder eingehenden Aktualisierung. Gerechtfertigte werden der „Allow-List“ der App hinzugefügt (und wieder von selbiger entfernt, sollten sie aus der App wieder entfernt worden sein). Bei Unklarheiten wende ich mich an die jeweiligen Entwickler, die diese dann i. d. R. klären oder aber auch entfernen bzw. ersetzen (ein Prozess, der bisher sehr gut funktioniert hat). Die übrigen sind, wie bereits erwähnt, deutlich gekennzeichnet oder können in schwerwiegenden Fällen zur Entfernung der App aus dem Repo führen.

Sensible Intent-Filter

Bei Android-Apps ist ein „Intent“ die abstrakte Beschreibung einer auszuführenden Operation. Grundlegend gibt es dabei drei Hauptanwendungsfälle: Das Starten einer Aktivität, eines Service, und um Nachrichten an einen BroadcastReceiver zu übermitteln, den andere Anwendungen abonnieren können, um diese Nachrichten zu empfangen.

package details
Beispiel der für eine APK angezeigten Details

Einige dieser Intent-Filter lösen bei den Scans analog zu den „heiklen Berechtigungen“ Warnungen aus, da sie auf unerwünschtes Verhalten hinweisen könnten – und werden dann genau so behandelt: manuelle Prüfung, Anfrage bei den Entwicklern sofern nötig. Anschließend wiederum: Aufnahme in die „Allow-Liste“, auslösen eines Anti-Features – oder Ausschluss (Entfernung) der App aus dem Repo.

Intent-Filters werden bei der Aufnahme von Apps manuell, aber auch automatisch durch den Update-Checker für jede eingehende APK-Datei geprüft.

Wenn ein solcher von einer App verwendet wird, muss dies transparent gemacht werden. Diese Überarbeitung beinhaltet also genau das: die Gründe dafür sichtbar zu machen (in einem separaten Block auf der App Details Seite der Website des Repos mit der Bezeichnung „Anwendungskonfiguration & Spezielle Zugriffsmethoden“, zusammen mit den oben erwähnten „Flags“).

Zertifikate und Signierung

Zertifikate kommen zum Einsatz, um Apps zu signieren. Sie werden üblicherweise von den Entwicklern selbst erstellt und ihn ihren privaten Keystores gespeichert – zumindest sollte das für die über das IzzyOnDroid Repository bereitgestellten APK-Dateien gelten. Ausnahmen davon finden sich etwa in Google’s PlayStore, wo Google das Signieren lieber selbst übernehmen möchte – sowie bei F-Droid‘s eigenem Repository, für das F-Droid die entsprechenden Zertifikate in den Fällen selbst generiert, in denen keine reproducible builds etabliert werden konnten.

App Signing ist ein Security Feature. Damit soll sichergestellt werden, dass die APK nicht manipuliert werden kann (so dass niemand z. B. bösartige Elemente einfügen kann) und dass sich unabhängig überprüfen lässt, ob die APK wirklich von dem entsprechenden Entwickler bereitgestellt wurde. Updates für eine installierte App werden nur akzeptiert, wenn die Signatur der entsprechenden APK-Datei mit der der bereits installierten App übereinstimmt. Was nur der Fall ist, wenn beide mit demselben Zertifikat signiert wurden. Die Zertifikate einer APK-Datei lassen sich zum Beispiel mit einem Tool namens apksigner überprüfen:

$ apksigner verify --verbose --print-certs org.fdroid.fdroid.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Number of signers: 1
Signer #1 certificate DN: CN=Ciaran Gultnieks, OU=Unknown, O=Unknown, L=Wetherby, ST=Unknown, C=UK
Signer #1 certificate SHA-256 digest: 43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab
Signer #1 certificate SHA-1 digest: 05f2e65928088981b317fc9a6dbfe04b0fa13b4e
Signer #1 certificate MD5 digest: 17c55c628056e193e95644e989792786
Signer #1 key algorithm: RSA
Signer #1 key size (bits): 2048
Signer #1 public key SHA-256 digest: e3d2cc87a245da2e84d4fb71e527c164e084d48bccf76ffad46ad17f1bfde388
Signer #1 public key SHA-1 digest: 26ef7882633282a9b04688178ee7f372fbec7c3d
Signer #1 public key MD5 digest: 9225fccafb33b605a86cfc09d7f38ec6

Wenn eine App zum IzzyOnDroid Repository hinzugefügt wird, wird das zum Signieren verwendete Zertifikat gepinnt: AllowedSigningKeys wird auf den Wert von Signer #1 certificate SHA-256 digest gesetzt. Updates für diese App werden dann nur akzeptiert, wenn die Zertifikate übereinstimmen. Damit soll verhindert werden dass eine APK, die möglicherweise manipuliert wurde, überhaupt in das Repository gelangt. Während eine solche APK für diejenigen, die die Vorgängerversion auf ihrem Gerät haben, nicht installiert (oder auch nur als Update angeboten) werden würde, schützt das Verhindern der Aufnahme in das Repository diejenigen, die die App zum ersten Mal installieren würden.

Aber das ist nicht das einzige, was auf dieser Ebene geprüft wird. Schauen wir uns an, was sonst noch geschieht:

Debug-Zertifikate & schwache Zertifikate

Diese werden lediglich bei der Aufnahme neuer Apps geprüft – Apps, die mit Debug-Zertifikaten signiert wurden, werden nicht mehr ins Repository aufgenommen. Da Zertifikate, wie beschrieben, bei der Aufnahme ins Repository per AllowedSigningKeys gepinnt werden, können solche APKs auch nicht mit Updates hinein gelangen: APKs mit einer abweichenden Signatur (das Verwenden eines anderen Zertifikats führt definitiv zu einer solchen) würden somit automatisch abgewiesen und nicht einmal in den Index gelangen können. Es wurde ein Scan über alle APKs durchgeführt, die sich derzeit im Repo befinden, um diejenigen zu finden, die ein Debug-Zertifikat verwenden (siehe scan existing APKs for use of debug keys) und zeigte, dass es zunächst 112 solcher APKs gab, 40 von ihnen sogar mit abgelaufenen Debug-Schlüsseln (das bedeutet nicht 112 bzw. 40 Apps, da es bis zu 3 APKs pro App im Repo geben kann). Mit den letzteren 40 wurde begonnen: 23 Apps, die offensichtlich nicht mehr gepflegt werden (Repositories gelöscht/archiviert, Autor seit Jahren nicht mehr gesehen usw.), wurden entfernt, für die übrigen habe ich die Autoren kontaktiert. Einige davon wurden innerhalb einer Woche korrigiert, andere wurden überhaupt nicht beantwortet. Letztere wurden ebenfalls entfernt, wenn innerhalb eines Monats keine Antwort einging (oder wenn die Autoren erklärten, sich nicht darum kümmern zu wollen).

Die restlichen 72 wurden in einem separaten Durchlauf behandelt. Die meisten davon sind bereits geklärt: In der Regel haben die Entwickler zu einem richtigen Release-Schlüssel gewechselt, und die Debug-Versionen wurden hier entfernt. Die letzten mit einem Debug-Schlüssel signierten APKs sollten Ende März 2024 verschwunden sein.

Diejenigen, die sich fragen warum dies ein Problem sein sollte, finden Antworten unter anderem hier:

Außerdem weist ein richtiges Release-Zertifikat in seiner DN darauf hin, wer das Zertifikat erstellt hat – während bei Debug-Schlüsseln immer steht, dass es "Android Debug" war:

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

Für diejenigen, die sich für die technischen Details interessieren, sind dies die Befehle, mit denen sie aufgespürt wurden:

Tipp für Entwickler: Da die Verwendung eines anderen Signierschlüssels bedeutet dass alle, die die App bereits verwenden, die alte Version deinstallieren müssen, bevor sie die neue installieren können, sollte „Schlüsselrotation“ in Betracht gezogen werden. Die Schlüsselrotation kann mit apksigner durchgeführt werden, wenn man sowohl Zugang zum ursprünglichen als auch zum neuen privaten Schlüssel hat. Ich habe noch nicht getestet, ob fdroidserver dies unterstützt; wer möchte kann sich aber gerne an mich wenden, damit ich einen Test durchführen kann. Da die Schlüsselrotation erst mit Android 9 eingeführt wurde, ist dies nur möglich, wenn die minSdkVer der App Android 9 oder höher entspricht.

BLOBs in APK Signing Blöcken

In den so genannten „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:

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

Es könnte auch andere Blocktypen geben, denn Entwickler könnten einfach ihre eigenen Blocktypen erstellen (oder vorhandene missbrauchen) und alles darin unterbringen, was sie möchten, einschließlich Code. Weshalb auch „unbekannte Blöcke“ eine Warnung auslösen – einschließlich der an mich gesendeten Mail. Wie schon bei den Prüfungen auf heikle Berechtigungen und sensiblen Intent-Filtern erfolgt diese Prüfung sowohl manuell bei Aufnahme neuer Apps, als auch automatisch bei jedem Update. Wer selbst APKs prüfen möchte, findet das passende Skript hier. In selbigem finden sich auch alle derzeit bekannten Blöcke aufgeführt, einschließlich Links zu Details über sie.

Wie beim DEPENDENCY_INFO_BLOCK ausgeführt, empfehle ich die Verwendung von apksigner für das Signieren, um einige dieser BLOBs von vornherein zu vermeiden. Gemäß der offiziellen Dokumentation lassen sich Android Studio und auch IntelliJ IDEA vom Einfügen dieses Blocks auch abhalten, wenn man folgendes Snippet in die build.gradle.kts einbindet:

android {
    dependenciesInfo {
        // Disable including dependency metadata when building APKs
        includeInApk = false
        // Disable including dependency metadata when building Android App Bundles
        includeInBundle = false
    }
}

Danke an Naveen für den Hinweis, und an soupslurpr für den Hinweis, auch AABs so zu behandeln! Mittlerweile hat sich der Ansatz, den DEPENDENCY_INFO_BLOCK über die skizzierte Modifikation der build.gradle auszuschließen, als erfolgreich erwiesen und wurde im Quellcode mehrerer Apps aus dem IzzyOnDroid-Repository angewendet.

Derzeit werden SigningBlock-BLOBs nur in der APK-Checker-Datenbank des Repositorys erfasst und auf der Website sichtbar gemacht. Wie dies in Zukunft gehandhabt werden soll, wird in einem separaten Thema verfolgt: Dealing with BLOBs found in APK signing blocks.

Noch ein Wort dazu: Wie das Beispiel des Payload von Meituan zeigt, ist dies nicht nur eine „kosmetische Angelegenheit“. Man kann eine APK nehmen, die ordnungsgemäß mit dem Schlüssel des Entwicklers signiert ist, etwas zum Signierblock hinzufügen – und die Verifizierung mit apksigner gelingt trotzdem vollständig, als ob nichts falsch wäre. Die modifizierte App lässt sich sogar auf einem Android-Gerät ordnungsgemäß installieren – das ist also durchaus ernst zu nehmen. Details dazu finden sich u. a. in diesem POC. Ein kurzes Zitat aus dem POC, frei übersetzt:

Ob der Payload vorhanden ist oder nicht, hat keinen Einfluss auf die Gültigkeit der Signatur. So erhalten wir zwei APKs – mit einer identischen gültigen v1+v2+v3-Signatur – aber eine sagt "Hier gibt es nichts zu sehen...", wenn man sie ausführt, während die andere z.B. sagt "Dies ist der Payload".

In einem Test wurde das EICAR sample auf diese Weise in eine APK-Datei eingeschleust und zu VirusTotal hochgeladen. Nur 2 der 64 Scanner dort erkannten es – was bedeutet, dass eine derartige Manipulation in vielen Fällen unerkannt bliebe. Doch selbst wenn deutlich mehr Malware-Scanner es entdecken würden wäre dies ein schlechtes Zeichen, solange die Signaturprüfung es nicht bemerkt: ein böswilliger Akteur könnte die APK eines seriösen Autors nehmen, einem Signierungsblock Malware hinzufügen und die daraus resultierende APK verbreiten, wodurch der Ruf des ursprünglichen Autors geschädigt würde – der dafür verantwortlich gehalten wird, da die Signatur „beweist“ das er es war.

In einem weiteren Test wurde ein ELF binary auf diese Weise in einen Signing Block eingebracht. VirusTotal schien das überhaupt nicht zu sehen. Pithus hat in diesen Fällen zumindest auf die „unbekannten“ Blöcke hingewiesen.

Warum ist dies nun ein Sicherheitsproblem? Android Apps haben Zugriff auf ihre eigenen APK-Datei, und können somit auf diese Weise Payload hier verstecken (und einige tun dies bereits, wie das Beispiel des MEITUAN_APK_CHANNEL zeigt). Da die meisten Scanner die Signierblöcke vollständig ignorieren, stellt dies ein Risiko dar, das behoben werden sollte.

Danke an Fay für die Bemühungen, die sie in diese Sache gesteckt hat!

Reaktionen von kontaktierten Entwicklern

Bislang wurden alle meine Berichte, sofern sie beantwortet wurden, gut aufgenommen und Anregungen entsprechend umgesetzt. Entweder sind die „potentiellen Übeltäter“ geklärt worden (mit Links zum Quellcode und entsprechenden Erklärungen) – oder meine Berichte führten zu Verbesserungen der App selbst, da selbige „Übeltäter“ entfernt wurden (teilweise mit Codeumstellungen unter Verwendung weniger „anstößiger“ Implementierungen), oder indem begründete Fälle transparenter gemacht und den Nutzern der App erklärt wurde, wenn die entsprechende Funktion ausgelöst wurde (z. B. indem bei android:usesCleartextTraffic bei Eingabe einer unsicheren URL gefragt wird, ob dies wirklich beabsichtigt war oder nur ein Tippfehler (das s in https vergessen?) vorliegt – manchmal auch beides, wie im beschriebenen Beispiel.

Fazit

Security ist kein „Set-and-Forget“, sondern ein fortlaufender Prozess. Dies ist nun die dritte „große Runde“ von Prüfungen, die im IzzyOnDroid Repository implementiert wurden – und wird definitiv nicht die letzte sein. Wie gezeigt, ist die Transparenz ein wichtiger Aspekt dieses Repositorys, um Euch zu zeigen „was drin ist“ selbst wenn es kein Sicherheitsproblem ist – damit Ihr, sollte etwas verdächtig aussehen, hoffentlich zumindest eine Erklärung dafür findet, warum es da ist.

„Dinge sicher(er) zu machen“ ist auch ein Lernprozess. Ich bin dankbar für alle Hilfe, die ich von Entwicklern erhalten habe, die mir (der kein Android-Entwickler ist) die Hintergründe und Einsatzzwecke erklärt haben. Und ich bin froh dass ich einigen Entwicklern mit dem, was ich auf diesem Weg gelernt habe, helfen konnte. Diese Zusammenarbeit empfinde ich als sehr wichtig, da es uns allen hilft, uns zu verbessern – und unsere Androiden zu sichereren Orten zu machen. Lasst uns das beibehalten!

appsinternaprivacysecurity


  1. Apkverifier enthält einen kurzen Kommentar im Quellcode, u. a. „The data is compressed, encrypted by a Google Play signing key...“ ↩︎

2024-03-25