Hallo allerseits, heute möchte ich Ihnen einige Optionen für die Übertragung von Daten zwischen zwei Android-Anwendungen erläutern und diese unter Sicherheitsgesichtspunkten betrachten. Ich habe mich aus zwei Gründen entschlossen, diesen Artikel zu schreiben. Erstens stieß ich oft auf ein Unverständnis der Entwickler der Mechanismen für die Arbeit mit den Komponenten einer Android-Anwendung. Das zweite - Ich habe aufgehört zu verstehen, worauf die Wahl dieses oder jenes Mechanismus bei der Implementierung von Funktionen basiert, und wollte vermitteln, wie es auf das Minimum aussehen sollte.
Herausforderung
Wir haben 2 Anwendungen, die auf dieselbe API zugreifen. Clients können über das Zugriffstoken (sessionId) auf die API zugreifen. Sie müssen einen nahtlosen Übergang von einer Anwendung zur anderen implementieren. Um dies zu tun, müssen Sie zwischen ihnen fummeln, z. B. sessionId.
Option 1: QUERY DEEPLINK
Die naheliegendste Option ist die Übertragung des Tokens an Query DeepLink. Es wird ungefähr so aussehen:
slave://main?sessionId=686A885A4FB644053C584B9BE2A70C7D
In diesem Fall kann der Empfänger die Sitzungs-ID extrahieren und verwenden, ohne die Autorisierung des Benutzers anzufordern. Aus Entwicklerseite sieht es so aus, als wäre die Aufgabe abgeschlossen, aber lassen Sie uns etwas tiefer gehen.
Deeplink-Entführung
Da jede Anwendung das Tinkoff: // Schema registrieren kann, kann das Betriebssystem die falsche Anwendung öffnen. Dies ist möglich, weil es keine Registrierung gibt und die Verwendung von Systemen eingeschränkt ist. Eine böswillige Anwendung kann das Schema tinkoff: // registrieren, die Anforderung an die Tinkoff-Anwendung abfangen und sich selbst starten. In diesem Fall gerät die sessionId in die falschen Hände und Ihr Konto wird gefährdet. Darüber hinaus können Sie mit DeepLink Hijacking Phishing durchführen, indem Sie beispielsweise Felder zur Eingabe eines Benutzernamens und eines Kennworts anzeigen.
Konzeptionell sieht der Prozess folgendermaßen aus:

Für dieses Problem gibt es zwei Lösungen. Erstens können Entwickler mit der AppLinks-Technologie das Schema nicht mehr anpassen. Stattdessen wird http / https verwendet. In diesem Fall nimmt das
Betriebssystem den Link
Slave.com/profile und kontaktiert den Host von Slave.com zur Überprüfung. Die zweite - Intent URL - anstelle des Aufrufs von Slave: //, Intent: // wird aufgerufen, wobei die eindeutige Kennung der zu startenden Anwendung übergeben wird. Es sieht so aus:
intent://main/#Intent;scheme=slave;package=com.example.slave.client.android;end"
In diesem Fall kann der Start der Anwendung nicht abgefangen werden, da ein bestimmtes Paket angegeben ist. Das Problem bleibt jedoch, dass der Benutzer die Anwendung von einer Quelle eines Drittanbieters mit derselben Paket-ID wie Ihr Slave installieren kann. In diesem Fall wird die schädliche Anwendung Ihr Token installieren und empfangen, wenn Sie keine legitime Slave-Anwendung hatten.
Sitzungsfixierung
Dies ist ein Angriff, bei dem ein Angreifer den Client zwingt, eine Sitzung mit der Zielsoftware unter Verwendung der vom Angreifer bereitgestellten Sitzungs-ID einzurichten. Sobald sich der Benutzer authentifiziert, kann der Angreifer diese bereits privilegierte Kennung für seine eigenen Zwecke verwenden. Der Angriff nutzt die Tatsache aus, dass die Zielsoftware nach der Eskalation von Berechtigungen dieselbe Sitzungs-ID verwendet.

Wie es in unserem Fall aussieht:
- Der Angreifer erhält eine anonyme Sitzung von der Anwendung
- wirft wunderschön einen Brief an das Opfer im Namen der Bank, in dem er eingeladen wird, auf sein persönliches Konto zu gehen
- Wenn wir auf den Link klicken, gelangen wir mit einem Angreifersitzungs-Slave zu DeepLink: // main? sessionId = 686A885A4FB644053C584B9BE2A70C7D
- Die mobile Anwendung nimmt an einer Sitzung teil, versteht, dass sie nicht über genügend Rechte verfügt, und fordert den Benutzer zur Authentifizierung auf
- Wenn der Benutzer es übergibt, hat die Sitzung erhöhte Rechte
- Benutzer in der Anwendung, ein Angreifer mit einer privilegierten Sitzung, Gewinn
Es wäre richtig, dies in der API zu beheben und nach der Eskalation von Berechtigungen eine weitere Sitzungs-ID auszugeben, aber wir schreiben eine mobile Anwendung. Und unser Weg ist es, die Übertragung des Tokens vom Master zum Slave zu verweigern. Außerdem erhalten wir so einen umfassenden Schutz. Wenn die API beschädigt wird und sich die Token nicht ändern, wenn die Berechtigungen erhöht werden, ist ein Angriff immer noch unmöglich.
Leckage von Drittanbietern
Ein weiteres Minus dieser Option. Viele Leute nutzen Dienste von Drittanbietern für DeepLink, weil sie bequem Links, Analysen und andere coole Dinge generieren können. In diesem Fall geben Sie Ihren Token einfach an ein Drittunternehmen weiter.
Option 2: INHALTSANBIETER
Wie machen wir das? Wir definieren den Master-Inhaltsanbieter und lassen den Slave für das Token zu diesem Inhaltsanbieter gehen.

Auf diese Weise wird das Risiko beseitigt, dass das Token im Fall von DeepLink-Hijacking an die falsche Anwendung übertragen wird, und der Angriff auf die Sitzungsfixierung wird unmöglich. Wir haben jedoch andere Probleme: In der aktuellen Version kann im Allgemeinen jede Anwendung jederzeit ein Token anfordern, auch wenn wir den Start nicht initiiert haben.
Schutzstufe
In den meisten Fällen müssen Sie überprüfen, ob der Slave mit demselben Schlüssel wie der Master signiert ist, dh, er gehört demselben Autor. In diesem Fall verfügt der Paketmanager über eine checkSignatures-Methode, mit der Anwendungssignaturen überprüft werden. Um diese Funktion nutzen zu können, müssen Sie im Anwendungsanbieter im Anwendungsmanifest eine Berechtigung mit protectedLevel = "Signatur" hinzufügen:
<permission android:name="com.example.contentprovider.access" android:protectionLevel="signature"/> <application> <provider ... android:readPermission="com.example.contentprovider.access"> </application>
Das Schema wird sich kaum von der vorherigen Abbildung ändern. Es wird nur eine Garantie angezeigt, dass nur Anwendungen mit einer Signatur desselben Autors Zugriff auf das Token erhalten.
Erlaubnis Race Bedingung
Es gibt eine sehr unangenehme Eigenschaft, dass Berechtigungsnamen nicht eindeutig sind, die von einer böswilligen Anwendung verwendet werden können und die Berechtigung mit unserem Namen und Schutzlevel = "normal" vor uns registrieren. In diesem Fall ist bei der Installation unserer Anwendung bereits eine Berechtigung auf dem Betriebssystem vorhanden, die nicht überschrieben wird. Folglich bleibt unser Inhaltsanbieter ungeschützt und hat von jeder Anwendung aus autorisierten Zugriff.
Unterschiedliche Signaturen
Leider werden Anwendungen nicht immer mit einem Schlüssel signiert, zum Beispiel werden einige Anwendungen gekauft oder "so historisch", aber ein nahtloser Übergang ist immer noch erforderlich. In diesem Fall nehmen wir die Unterschriftenüberprüfung selbst in die Hand.
Wie kann dies umgesetzt werden:
Der Inhaltsanbieter verfügt über eine getCallingPackage () -Methode, mit der wir die packageId der Anwendung abrufen können, die Daten beantragt hat, und mit packageId die Liste der Signaturen abrufen und diese mit den integrierten überprüfen können.
String pkg = this.getCallingPackage(); PackageInfo pkgInfo = pkgmgr.getPackageInfo(pkg, GET_SIGNATURES); Signatures[] signatures = pkgInfo.signatures; for (Signature sig: signatures) { if (sig.equals(TRUSTED_SIGNATURE)) {

Es scheint, dass wir alles perfekt gemacht haben, aber nein.
Gefälschte ID-Sicherheitslücke
Das Problem ist, dass beim Erstellen einer Vertrauenskette durch Android der Überprüfungsprozess nur den Betreff vergleicht und die Signatur im Unterzeichnerfeld des Zertifikats nicht überprüft. Infolgedessen kann ein Angreifer eine Vertrauenskette ohne tatsächliche Signatur aufbauen.
Aufgrund dieses Fehlers wird eine falsche Zertifikatkette generiert, die möglicherweise legitime Zertifikate enthält, die in das APK eingebettet sind, aber nicht zum Signieren der Anwendung verwendet werden. Am Ende werde ich einen Link zum Commit hinterlassen, der diese Sicherheitsanfälligkeit behebt. Das Problem wurde in Android 4.4 behoben, sodass wir die API-Stufe nur auf 19 erhöhen können.
Schlussfolgerungen
Heute haben wir untersucht, wie Features während der Entwicklung analysiert werden sollten.
Wir haben auch die Optionen für die Übertragung des Geheimnisses zwischen zwei Anwendungen untersucht. Dabei haben wir die Probleme jeder Option analysiert und Möglichkeiten gefunden, sie zu vermeiden.
Alle sicheren Anwendungen!
Referenzen