Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
TheLastBundleMismatch — Writeup und Exploit für CVE-2023-45777, Umgehung der Intent-Validierung innerhalb des AccountManagerService auf Android 13 trotz der „Lazy Bundle“-Abschwächung | Kitploit
Tools/GitHubGitHub/michalbednarski/thelastbundlemismatch
Android-SicherheitSchwachstellenanalyseExploitationBinäranalysePapers & Forschung
GitHubmichalbednarski/thelastbundlemismatch

TheLastBundleMismatch

Writeup und Exploit für CVE-2023-45777, Umgehung der Intent-Validierung innerhalb des AccountManagerService auf Android 13 trotz der „Lazy Bundle“-Abschwächung

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen
1011468vor 2 JahrenVon Kitploit geprüft

Mysteriöser Patch

Beginnen wir diesmal mit dem Patch, der als Fix für CVE-2023-45777 im Android Security Bulletin erschien:```diff diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 7a19d034c2c8..5238595fe2a2 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -4923,7 +4923,7 @@ public class AccountManagerService p.setDataPosition(0); Bundle simulateBundle = p.readBundle(); p.recycle();

  •        Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
    
  •        Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class);
           if (intent != null && intent.getClass() != Intent.class) {
               return false;
           }
    
Wenige Leute waren neugierig genug, um mich zu fragen; zuvor habe ich ihnen mit einigen Hinweisen geantwortet, und jetzt veröffentliche ich den vollständigen Writeup zu diesem Problem

Aber zuerst etwas Kontext darüber, was in diesem Patch vor sich geht

Dies ist eine Änderung in der [`checkKeyIntent()`-Methode](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/services/core/java/com/android/server/accounts/AccountManagerService.java;l=4938-4954;drc=47de64a38aa1799cb41f41b2ea0c539ee61de64d). Diese Methode führt mehrere Prüfungen durch, um sicherzustellen, dass die von der Anwendung bereitgestellte `Intent` für das System sicher zu starten ist (unter Verwendung der Privilegien des Systems)

Zuerst verwendet diese Methode `checkKeyIntentParceledCorrectly()`, die ein `Bundle`, das wir prüfen, serialisiert und wieder deserialisiert und prüft, ob die `Intent`, die vorher aus dem `Bundle` entnommen wurde, mit der `Intent` aus dem `Bundle` nach einem solchen Zyklus übereinstimmt. Da der Start der `Intent` in anderen System-App-Prozessen erfolgt als in dem, der die Validierung durchführt, war es zuvor [möglich, `Bundle`s zu konstruieren, die während der Validierung innerhalb von `AccountManagerService` sicher erschienen, aber eine andere `Intent` enthielten, nachdem sie an den nächsten Prozess gesendet wurden](https://github.com/michalbednarski/IntentsLab/issues/2#issuecomment-344365482). Dies simuliert das Senden des `Bundle`s an den nächsten Prozess, um solche Situationen zu erkennen.

Nach `checkKeyIntentParceledCorrectly()` haben wir einen `bundle.getParcelable()`-Aufruf, den dieser Patch von der veralteten Version, die beliebige Objekte konstruieren konnte, auf eine Version umstellt, die validiert, dass das Objekt, das deserialisiert werden soll, vom Typ ist, der im zweiten Parameter angegeben wurde

Diese Version mit Typparameter wurde in Android 13 als Teil der umfassenderen `Parcel`/`Bundle`-Härtung eingeführt. Insbesondere vor Android 13 behielt ein `Bundle`, wenn es zwischen Prozessen gesendet wurde, eine rohe Kopie der gesamten serialisierten Daten, bis auf ein Element zugegriffen wurde, woraufhin jeder Wert deserialisiert wurde. Jetzt, wenn auf einen Wert zum ersten Mal zugegriffen wird, nachdem das `Bundle` empfangen wurde, werden nur die `String`-Schlüssel und die Werte primitiver Typen deserialisiert, während nicht-primitive Werte als `LazyValue`s belassen werden, deren Länge als Teil der serialisierten Daten gespeichert ist, um sicherzustellen, dass selbst bei einer Nichtübereinstimmung der Serialisierungs-/Deserialisierungslogik solche Nichtübereinstimmungen keine anderen Einträge beeinträchtigen

Bevor wir eintauchen, werfen wir einen Blick auf `LazyValue`: In seinem Quellcode [haben wir einen schönen Kommentar, der seine Datenstruktur erklärt](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/Parcel.java;l=4392-4399;drc=03c34f57c05feecfb090de3917787f049cb5f804)```
                     |   4B   |   4B   |
mSource = Parcel{... |  type  | length | object | ...}
                     a        b        c        d
length = d - c
mPosition = a
mLength = d - a

mPosition und mLength beschreiben den Speicherort der gesamten LazyValue-Daten im ursprünglichen Parcel, einschließlich type und length. „length“ (ohne „m“ am Anfang) bezieht sich auf den Längenwert, wie er in den Parcel geschrieben wurde, und schließt den Header (type und length) aus.

Wenn ein Bundle, das eine LazyValue enthält, an einen anderen Prozess weitergeleitet wird, wird die gesamte LazyValue einschließlich der Felder type und length unverändert von Bundle.mParcelledData in den Ziel-Parcel kopiert.

Wenn auf das durch LazyValue dargestellte Bundle-Element zugegriffen wird, wird Parcel auf mPosition zurückgespult und readValue() aufgerufen. Wenn ein Typargument an bundle.getParcelable() übergeben wird, wird es an readValue() weitergegeben, das sowohl sicherstellt, dass der Typ, der entpackt werden soll, der erwartete ist, als auch nach dem Entpacken verifiziert, dass der entpackte Werttyp der erwartete ist. Nach dem Entpacken wird LazyValue ersetzt, sodass der Wert beim nächsten Schreiben des Bundle in den Parcel erneut über writeValue() serialisiert wird.

Die Verwendung des typisierten Parameters Bundle.get*()/Parcel.read*() ist hauptsächlich für Methoden wie Parcel.readParcelableList() relevant, die eine ArrayList zurückgeben. Aufgrund der Java-Typ-Erasure wird der Teil <SomeParcelableType> selbst bei etwas wie List<SomeParcelableType> field = parcel.readParcelableList(); zur Laufzeit nicht erzwungen, und eine solche List könnte beliebige im System verfügbare Parcelable-Klassen enthalten. Daher könnten alle im System verfügbaren createFromParcel/writeToParcel als Teil der Serialisierung/Deserialisierung des Typs verwendet werden, der eine solche List enthält.

Möglicherweise möchten Sie sich auch die Präsentation des Android Security and Privacy Teams zur Einführung dieser Mechanismen ansehen (Folien, Video).

Hier scheint die Verwendung der typisierten Version jedoch redundant zu sein, da wir den Typ des zurückgegebenen Objekts auch explizit prüfen. Was ist also los und welche Schwachstelle wird hier behoben?

Nebenwirkungen

Werfen Sie noch einmal einen Blick auf den Patch von Anfang an

Tool herunterladen