SourMint: Bericht zur Untersuchung des schädlichen SDKs
Kirill Efimov
16. Oktober 2020
0 Min. LesezeitÜbermäßige Datenerfassung unter iOS [August 2020]
Remote Code Execution (RCE) unter iOS [Oktober 2020]
Download-Tracking unter Android [Oktober 2020]
Überblick
Das Mintegral SDK ist ein beliebtes Werbe-SDK für mobile Apps, das für iOS und Android verfügbar ist. Tausende mobile Apps mit insgesamt über einer Milliarde Downloads pro Monat verwenden es. App-Entwickler nutzen das SDK, um ihre Apps mit Anzeigen von Drittanbietern zu monetarisieren.
Das Snyk-Sicherheitsforschungsteam hat zwei bedeutende Erkenntnisse zum Mintegral SDK veröffentlicht. Die erste Erkenntnis wurde im August 2020 veröffentlicht. Dabei wurden übermäßige Datenerfassung und Click-Hijacking in der iOS-Version des SDK entdeckt. Die zweite Erkenntnis betraf eine in der iOS-Version des SDK gefundene Hintertür, die Remote Code Execution ermöglicht, sowie neue Erkenntnisse zur Android-Version des SDK.
Dieser Artikel soll die technischen Details unserer Untersuchungen und Erkenntnisse vermitteln, die über die Blogbeiträge hinausgehen.
Dieser Bericht ist in drei Abschnitte unterteilt:
Übermäßige Datenerfassung: Dieser Abschnitt beschreibt die URL- und Request-Tracking-Funktionen der iOS-Version des Mintegral SDK, einschließlich des Abfangens und Protokollierens sämtlicher HTTP-Requests im iOS-SDK. Er wurde ursprünglich am 24. August 2020 veröffentlicht.
Eine Hintertür in der iOS-Version des SDK ermöglicht Remote Code Execution: Dieser Abschnitt beschreibt die Remote-Code-Execution-Funktionen von MintegralAdSDK, veröffentlicht am 15. Oktober 2020.
URL-Tracking von Downloads unter Android: Dieser Abschnitt beschreibt verschiedene Erkenntnisse zur Android-Version des Mintegral SDK.
Übermäßige Datenerfassung unter iOS [August 2020]
Überblick
Dieser Teil der Untersuchung wurde anhand der Binärversion des Mintegral iOS SDK durchgeführt, da uns die Open-Source-Version im August 2020 noch nicht zur Verfügung stand. Untersucht wurde Version 6.3.5.0 des SDK (für x86-Architektur), die auf GitHub zum Download bereitsteht.
Wir haben festgestellt, dass die Mintegral-iOS-SDK-Versionen 5.5.1 und höher schädliche Funktionen enthalten, die zum Abfluss von Informationen führen. Vereinfacht gesagt, spioniert das SDK Klicks auf Links sowie Netzwerkaktivitäten innerhalb der betroffenen Apps aus. Die Spionage findet auch dann statt, wenn das SDK vom Entwickler oder der Anzeigenvermittlungsplattform nicht aktiviert wurde. Das SDK versucht, sein schädliches Verhalten zu verbergen, indem es Proxys, Simulatoren und Geräte mit Jailbreak erkennt.
Method Swizzling
Das Mintegral SDK verwendet eine Technik namens Method Swizzling, um die Implementierungen der Methoden UIApplication openURL und SKStoreProductViewController loadProductWithParameters zur Laufzeit zu ersetzen. Außerdem registriert es eine benutzerdefinierte Klasse NSURLProtocol.
Diese Hooks spionieren App-Nutzer aus, indem sie sämtliche Informationen zu HTTP-Requests, geöffneten URLs und App-Store-Links, auf die Nutzer innerhalb der App klicken, übermitteln.
HTTP-Request-Header und URLs können sensible Daten enthalten. Zusammen mit der IDFA (Identifier for Advertisers) ermöglichen diese Daten Mintegral jedoch, Werbe-Attributionsbetrug zu begehen.
Werbe-Attributionsbetrug
Um ihre Anwendungen zu monetarisieren, installieren Entwickler häufig Werbeplattformen. Werbeplattformen erhalten von Werbetreibenden Einnahmen für jede Installation, die nach einem Klick des Nutzers auf ihre Anzeige erfolgt. Nicht selten verwenden Entwickler mehrere Werbeplattformen in ihren Apps. Um festzustellen, welcher Werbeplattform die Installation zugeordnet werden soll, wird jeder Klick bei einem Attributionsanbieter registriert, einer Mobile Measurement Platform (MMP).
Die folgende Abbildung zeigt, wie die schädliche Funktion von Mintegral arbeitet. In diesem Beispiel klickt der Nutzer auf eine Anzeige von „Another Platform“. Da Mintegral jedoch alle von der App geöffneten URLs abfangen kann, kann es zusätzliche Requests an einen Attributionsanbieter senden und vorgeben, der Klick sei auf eine eigene Anzeige erfolgt. Der gesamte Ablauf sieht so aus:
Der Nutzer klickt auf einen Link in einer In-App-Anzeige eines nicht zu Mintegral gehörenden Werbenetzwerks, um eine neue App aus dem App Store zu installieren.
Das SDK des Werbenetzwerks sendet die Klickinformationen an dessen Backend-Plattform.
Nachdem Mintegral das Klickereignis mithilfe von in iOS-Ereignishandler eingeschleustem Code über Method Swizzling abgefangen hat, protokolliert es die Klickdaten auf seinem Server.
Das Werbenetzwerk registriert beim Attributionsanbieter eine Klickbenachrichtigung.
Mintegral registriert beim Attributionsanbieter ebenfalls eine Klickbenachrichtigung.
Wenn der Attributionsanbieter versucht, das Installationsereignis den registrierten Klickbenachrichtigungen zuzuordnen, findet er zwei passende Benachrichtigungen. Bei einem Last-Touch-Attributionsmodell wird die Klickbenachrichtigung von Mintegral zugeordnet und die Benachrichtigung des anderen Werbenetzwerks abgelehnt.

Snyk hat mit einem großen Attributionsanbieter zusammengearbeitet, um zu bestätigen, dass Mintegral die Klickdaten verwendet, um gefälschte Klickbenachrichtigungen zu generieren. Im Rahmen seiner Untersuchung konnte der Anbieter nachweisen, dass solche gefälschten Benachrichtigungen erzeugt wurden und dazu führten, dass Anzeigenklicks fälschlich Mintegral zugeschrieben wurden.
Demo-App
Um den Angriff zu demonstrieren, haben wir eine Demo-App eingerichtet. Sie zeigt den schädlichen openURL-Hook in Aktion. Mithilfe eines Debugging-Proxys fangen wir den gesamten Netzwerkverkehr ab.
Zur Initialisierung der App verwenden wir den folgenden Codeausschnitt aus der Mintegral-Dokumentation:
Nachdem das SDK initialisiert ist, öffnen wir example.com in der App, indem wir auf eine Schaltfläche klicken:
Nach dem Start der App sehen wir in unserem Proxy sofort einige Requests vom Mintegral SDK:

Einstellungen
Die Antwort von _https://setting.rayjump.com/setting ist ein JSON-Objekt mit vielen verschiedenen Optionen. Die folgende Tabelle beschreibt die für unsere Untersuchung interessantesten Felder.
JSON-Feld | Beschreibung |
|---|---|
csw | Aktiviert oder deaktiviert die Anti-Debugging-Funktion. |
cou | Aktiviert oder deaktiviert den |
cdai | URL, an die die abgeflossenen Informationen gesendet werden (*). |
cspn | Aktiviert oder deaktiviert den Hook für StoreKit-Methoden. |
cud | Aktiviert oder deaktiviert den Hook für NSURLProtocol. |
cudl | Array mit URLs, die über NSURLProtocol nachverfolgt werden (**). |
* In unserem Fall lautete der Wert LdxThdi1WBK/WgfPhbxQYkeXHBPwHZKsYFh=. Nach dem Dekodieren ergibt sich https://n.systemlog.me/log.
** In unserem Fall lautete der Wert kBzuJd5/H+i/D+SMY7V/DFKwR0M0D+SMhBPthdSsHZPUYFT0+N==. Nach dem Dekodieren ergibt sich ["itunes.apple.com","apps.apple.com"].
Dekodierung der Nutzdaten
Nachdem wir auf die Schaltfläche geklickt haben, über die example.com geöffnet wird, sehen wir zwei weitere Requests. Beim ersten handelt es sich erwartungsgemäß um einen GET-Request an http://example.com. Der zweite ist ein POST-Request an https://n.systemlog.me/log.

Der Request-Body sieht base64-kodiert aus. Tatsächlich handelt es sich jedoch nicht um eine base64-kodierte Zeichenfolge. Das Mintegral SDK implementiert eine eigene Kodierungs- und Dekodierungslogik, die sich in +[MTGBase base64DecodeString:] und +[MTGBase base64CleverDecodeString:] findet. Beachten Sie, dass MTGBase nicht in den öffentlichen Headern des SDK offengelegt ist und für Entwickler nicht zugänglich sein soll.
Mit dem folgenden Codeausschnitt dekodieren wir die Nutzdaten:

Die Nutzdaten enthalten zahlreiche Informationen, darunter IDFA, IDFV, Betriebssystemversion und User-Agent. Außerdem gibt es ein Feld namens „clever“, das ebenfalls kodiert ist. Wir können es mit base64DecodeString dekodieren:
Wie Sie sehen, enthält es die URL, den Stack-Trace und einige zusätzliche Informationen, etwa den Controller- und Methodennamen.
Ein genauerer Blick
Wie bereits erwähnt, ist das Mintegral SDK Closed Source. Wir untersuchen Version 6.3.5.0 für die x86-Architektur.
Bei der Binärdatei handelt es sich um eine Mach-O-Datei, die mehrere weitere Binärdateien enthält. Der für uns relevante Code befindet sich in _CXX_CXX_OperationPKTask.o.
Bei der Untersuchung der Klasse sehen wir +[_CXX_CXX_OperationPKTask load], das automatisch ausgeführt wird, sobald die Klasse zur Laufzeit hinzugefügt wird. Wird das SDK also über CocoaPods installiert, wird die schädliche Logik unabhängig davon initialisiert, ob Entwickler das SDK tatsächlich verwenden.
Die Methode load führt eine Reihe von Aufrufen aus, die zu ___cxxwebk_init_vw führen. Diese Methode prüft, ob das Anti-Debugging-Schutzflag aktiviert ist, und initialisiert die Hooks, wenn das Flag auf „false“ gesetzt oder das Debugging deaktiviert ist.

Die Initialisierung der Hooks hängt von der oben erwähnten Einstellungsabfrage ab. Die folgende Tabelle zeigt die Beziehungen zwischen den JSON-Antwortfeldern und der Klasse MTGSetting:
JSON-Feld | Eigenschaft von MTGSetting | Beschreibung |
|---|---|---|
csw | cSrtW | Aktiviert oder deaktiviert die Anti-Debugging-Funktion. |
cou | cOpenURL | Aktiviert oder deaktiviert den |
cspn | cPackageName | Aktiviert oder deaktiviert den Hook für StoreKit-Methoden. |
Anti-Debugging-Logik

Die Funktion __cxx_cxx_op_isInSuperViewFrame gibt in den folgenden Fällen true zurück:
Die Geräteplattform ist ein „Simulator“.
Ein Debugger ist angehängt (implementiert in
____mvpmvvm_isDebuggerAttached_block_invoke).Eine der folgenden Dateien befindet sich auf dem Gerät (Hinweis auf einen Jailbreak):
/Applications/Cydia.app
/Library/MobileSubstrate/MobileSubstrate.dylib
/bin/bash
/usr/sbin/sshd
/etc/apt
/usr/bin/ssh
Ein Proxy ist aktiviert (ermittelt mithilfe von
CFNetworkCopySystemProxySettings).
Method Swizzling für openURL
Die Logik im folgenden Screenshot ist in der Methode ___cxxwebkmcouitninapo implementiert. Sie wird von ___cxxwebk_init_vw aufgerufen, wenn das entsprechende Flag aktiviert ist.

„blog-sour-mint-openurl-method-swirl“ – Der obige Screenshot zeigt die Method-Swizzling-Implementierung. Sie führt die folgenden Aufrufe aus:
NSSelectorFromString, um einen Selector für die Methode „openURL:“ abzurufen.NSClassFromString, um einen Klassen-Deskriptor fürUIApplicationabzurufen.class_getInstanceMethod, um den Methoden-Deskriptor abzurufen.method_getImplementation, um die tatsächliche Implementierung der Methode abzurufen.Anschließend definieren sie einen Codeblock, der
_____cxxwebkmcouitninapo_block_invoke_2und danach das ursprünglicheopenURLaufruft.method_setImplementation, um die ursprüngliche openURL-Implementierung durch den Codeblock aus dem vorherigen Schritt zu ersetzen.
Bei der Methode openURL:options:completionHandler: geschieht fast dasselbe. Zuvor wird jedoch die Systemversion geprüft (der Handler wurde erstmals mit iOS 10 eingeführt).
Nun haben wir gesehen, wie der Hook angewendet wird. Als Nächstes sehen wir uns die Implementierung des Hooks selbst an (_____cxxwebkmcouitninapo_block_invoke_2).
Implementierung des openURL-Hooks
Die Implementierung befindet sich in der Methode ___cxxwebkmcoulsz. Dort sehen wir eine weitere Anti-Debugging-Prüfung. Anschließend wird das Flag __mc_notifyInHouse geprüft. Ist es auf 1 gesetzt, wird nichts unternommen.
Damit werden alle Marketing-URLs ignoriert, auf die Nutzer in einer von Mintegral ausgelieferten Anzeige klicken. Der entsprechende Code ist im folgenden Screenshot in +[MTGBase mtgOpenURL:options:completionHandler:] zu sehen:

Der nächste Codeabschnitt zeigt, dass auch die Backtrace-Daten serialisiert und in den Nutzdaten an https://n.systemlog.me/log übertragen werden.
Wir können am Aufruf +[_CXX_CXX_OperationPKTask _cxx_cm_log_warnings:to:ins:] einen Breakpoint setzen. Die Aufrufargumente sehen Sie im nächsten Screenshot:

Die geöffnete URL (http://example.com?foo=bar&x=y).
Die Klasse, in der der Klick stattfand (
ViewController).Die Methode, in der der Klick erfolgt ist (
openURLWithOptions:).Backtrace-Informationen.
Eine weitere interessante Funktion ist _nsh_id_by_cc. Sie scheint dafür zuständig zu sein, konkurrierende SDKs zu identifizieren. Die relevante Logik ist im nächsten Screenshot zu sehen:

Zurück zu +[_CXX_CXX_OperationPKTask _cxx_cm_log_warnings:to:ins:]: Nachdem die Payload mit +[MTGBase base64EncodeString:] codiert wurde, erstellt die Methode einen neuen Codeblock und verwendet _dispatch_async, um ihn aufzurufen.
Darauf folgt eine Reihe von Aufrufen mit weiteren Payload-Transformationen. Am Ende steht -[_MC_ApiManager AFRequestWithUrl:paras:success:failure:], das eine POST-Anfrage an collectDomainUrl aus MTGSetting sendet. Standardmäßig lautet die URL https://n.systemlog.me/log.
Ein Video, das zeigt, wie eine private URL offengelegt werden kann.

SKStoreProductViewController-Hook
SKStoreProductViewController ist ein View-Controller, der eine Seite bereitstellt, auf der Nutzer Medien im App Store kaufen können.
Die Methode loadProductWithParameters:completionBlock: lädt einen neuen Produktbildschirm zur Anzeige.
Statt die technischen Details der Hook-Implementierung zu erläutern, haben wir den folgenden Codeausschnitt zur Demo-Anwendung hinzugefügt:
Als Ergebnis sehen wir eine POST-Anfrage an https://n.systemlog.me/log mit der folgenden Payload im Feld „clever“:
Wie zu sehen ist, befindet sich die Produkt-ID in der Anfrage. Damit ist es bewiesen.
NSURLProtocol-Hook
Die Klasse NSURLProtocol ermöglicht Entwicklern, die Funktionsweise von Apples URL-Ladesystem neu zu definieren. Das Mintegral SDK registriert eine schädliche Implementierung von NSURLProtocol, die sich aus der Ferne so konfigurieren lässt, dass sie alle ausgehenden Anfragen einer Anwendung abfängt und URLs sowie HTTP-Header wie den Authorization-Header protokolliert.
Für Anwendungsentwickler bedeutet das, dass Mintegral möglicherweise API-Tokens, Cookies und Header für die einfache Authentifizierung erfassen kann.
Um zu verstehen, wie das SDK diesen Teil des schädlichen Codes aktiviert, müssen wir uns ___cxxwebk_init_vw noch einmal ansehen.

Der obige Screenshot zeigt, dass das cud-Flag aktiviert und das cudl-Array nicht leer sein muss, damit der Hook aktiviert wird.
Der folgende Screenshot zeigt einen Teil der Funktion ___cxxwebkterisiuuxx, die von der oben gezeigten Methode aufgerufen wird.

Der Code in der Funktion ___cxxwebkterisiuuxx führt folgende Aktionen aus:
Erstellt eine von
NSURLProtocolabgeleitete Klasse (objc_registerClassPair,objc_allocateClassPair).Fügt eine Implementierung für
canInitWithRequest:hinzu, die als Interceptor fungiert (class_addMethod).Ruft
+[NSURLProtocol registerClass:]auf, um die Klasse beim URL-Ladesystem zu registrieren.
Im Rahmen unserer Untersuchung haben wir den folgenden Codeausschnitt hinzugefügt, um zu überprüfen, welche Daten der schädliche Code erfasst:
Als Ergebnis sehen wir eine POST-Anfrage an https://n.systemlog.me/log mit der folgenden Payload im Feld „clever“:
In der Anfrage sind die URL und der Authorization-Header zu sehen. Der Anfragekörper ist zwar nicht enthalten, doch Header enthalten häufig vertrauliche Daten. Dazu können sogar personenbezogene Daten gehören. Wenn eine API beispielsweise JWT-Tokens verwendet, können E-Mail-Adressen oder Benutzernamen im Token gespeichert sein.
Fazit
Während unserer Untersuchung haben wir zahlreiche interessante Techniken beobachtet, mit denen Mintegral-Entwickler das schädliche Verhalten ihres SDKs verschleiern. Wie zu sehen ist, aktivieren sie Hooks nur in bestimmten Anwendungen und Regionen. Dadurch blieb der schädliche Code über ein Jahr lang unentdeckt.
Zum zeitlichen Verlauf: Die erste Version (5.5.1) des schädlichen SDK wurde am 17. Juli 2019 veröffentlicht. Wir stellten fest, dass alle nachfolgenden Versionen dieselbe schädliche Funktionalität enthielten.
Viele beliebte Anwendungen waren von den schädlichen Aktivitäten dieses SDK betroffen. Wir hoffen, dass diese Untersuchung Licht auf die Situation wirft und künftig zu einer genaueren Prüfung von Werbenetzwerken sowie zu besseren Datenschutzkontrollen führt.
Remote Code Execution (RCE) unter iOS [Oktober 2020]
Kurzfassung
Wir haben die Klasse MTGBaseBridgeWebView entdeckt, die im gesamten SDK zur Kommunikation mit JavaScript verwendet wird. Sie fungiert als Hintertür und ermöglicht den Aufruf beliebiger Funktionen im nativen Anwendungscode.

Die Abbildung oben zeigt ein vereinfachtes Schema der Remote Code Execution in Aktion.
Diff-Analyse
Nach unserer ersten öffentlichen Offenlegung kündigte Mintegral die Veröffentlichung einer Open-Source-Version des SDK an.
Wir verglichen daraufhin die neue Open-Source-Version mit der zuvor als CocoaPod vertriebenen Binärversion. Obwohl uns der Quellcode der älteren Version nicht vorlag, konnten wir die Klassennamen vergleichen. Dazu extrahierten wir die .o-Dateien aus den Binärdateien und verglichen die Symbole mit den .h-Dateien der Open-Source-Version.
Wie erwartet wurde die zuvor entdeckte schädliche Komponente _CXX_CXX_OperationPKTask tatsächlich entfernt. Beim Vergleich stießen wir jedoch auf etwas anderes. Die folgenden Klassen fielen uns auf:
MTGCommandDispatcher
MTGComponentCommands
MTGRemoteCommand
MTGRemoteCommandParameterModel
MTGRemoteCommandParser
MTGInvocationBoxing
Wir beschlossen, die Binärdateien genauer zu untersuchen, um herauszufinden, wofür diese Dateien verwendet wurden.
Betroffene Versionen
Alle Versionen von MintegralAdSDK bis einschließlich 6.5.0.0. Die am 10. September 2020 veröffentlichte Version 6.6.0.0 enthält nicht die in diesem Beitrag beschriebene Hintertür-Funktionalität.
Die Bridge-Implementierung
Wir begannen damit, zu untersuchen, wo die Klasse MTGRemoteCommandParser verwendet wird, und fanden nur eine Stelle: -(void)handleNativeObject:parameters: in der Klasse MTGBaseBridgeWebView.
Anhand der Implementierung sehen wir, dass -(void)handleNativeObject:parameters: MTGRemoteCommandParser verwendet, um das Argument parameters zu analysieren, und die Methode -(void)dispatchCommand:feedback: in der Klasse MTGCommandDispatcher aufruft.
Auf den ersten Blick scheint -(void)handleNativeObject:parameters: nicht verwendet zu werden. Das ist jedoch nicht der Fall. Sehen wir uns an, wie der Aufruf aus JavaScript-Code erfolgen kann.
MTGBaseBridgeWebView implementiert die Methode -(void)webView:decidePolicyForNavigationAction:decisionHandler: des Protokolls WKNavigationDelegate. Diese Methode wird bei jeder Navigation in der Web-View aufgerufen. Das bedeutet, dass wir sie direkt aus JavaScript auslösen können, indem wir einfach location.href=something aufrufen. In der Open-Source-Version des SDK fanden wir einen regulären Ausdruck, der Navigationsanfrage-URLs analysiert: mv://(.+?):(.+?)/(.+?)\\?([\\s\\S]*).

-(void)callFunctionWithName:fucId:param: führt im obigen Screenshot einfach einen Aufruf von self mit dem Selector fucName aus.
Um also -(void)handleNativeObject:parameters: von MTGBaseBridgeWebView aufzurufen, benötigen wir die folgende JavaScript-Codezeile: location.href = 'mv://1:fucId/handleNativeObject?<parameters>'.
Beachten Sie, dass alles oben Beschriebene zum Zeitpunkt der Erstellung dieses Beitrags auch für die neueste SDK-Version sowie für die Open-Source-Version des SDK gilt. Die einzige Ausnahme: -(void)handleNativeObject:parameters: wurde aus den neuesten Releases entfernt.
Aufruf entfernter Methoden
Wir beschreiben nicht die vollständige Implementierung von MTGInvocationBoxing und den anderen Klassen. Stattdessen zeigen wir, wie sich schädlicher JavaScript-Code erstellen lässt, um die entfernte Methode aufzurufen.
Der folgende Proof of Concept greift eine Anwendung für „einfache Notizen“ an, die eine Klasse NoteRepository mit den beiden Methoden +(void)save: und +(NSString*)load enthält.
Wir schleusen den schädlichen JavaScript-Code ein, indem wir den Mintegral-Server durch unsere eigene Serverimplementierung ersetzen. Den vollständigen Quellcode dieser Anwendung und des Servers finden Sie hier.
Der schädliche JavaScript-Code für diese Anwendung lautet:
Wert | Dekodiert |
|---|---|
hbxtJ7QU+TPXJ75ZH+SXhFQTYbzP | static_NoteRepository |
Y7KtHv== | load |
Dieser Code ruft die Methode +(NSString*)load der Klasse NoteRepository auf und sendet das Ergebnis an unseren Endpunkt demo-evil-server.com/log.
Der Code verwendet dieselben Verschleierungstechniken wie im vorherigen Abschnitt beschrieben. Der Proof of Concept enthält jedoch bereits JavaScript-Code zum Codieren und Dekodieren (siehe banner.html).
Vollständige Remote Code Execution (RCE) erlangen
Im obigen Beispiel haben wir gesehen, wie sich das SDK verwenden lässt, um beliebige statische Methoden beliebiger Klassen aufzurufen. In diesem Abschnitt zeigen wir, wie sich damit beliebiger nativer Code ausführen lässt.
Zur Veranschaulichung zeigen wir, wie sich ein UIAlertController mit der Meldung „PWNED!“ erstellen lässt.
Sehen wir uns als Referenz den folgenden Objective-C-Code an:
Wir müssen herausfinden, wie wir eine Instanz von UIAlertController erstellen und zwischen Aufrufen beibehalten, eine gemeinsame Anwendungsinstanz abrufen und presentViewController:animated:completion: mit dieser Instanz aufrufen können.
Schritt 1: Referenz auf die Klasse UIAlertController speichern
Der MTGRemoteCommandParser unterstützt zwei Arten von Objektreferenzen:
static– ruft anhand des Namens eine Referenz auf ein Klassenobjekt ab.singleton– führt mehrere Schritte aus:Ruft eine Klasse anhand ihres Namens ab (in unserem Beispiel
MTGSetting).Führt die Methode
sharedInstancefür die Klasse aus. In Objective-C:[MTGSetting sharedInstance].Verwendet
valueForKey:, um durch Punkte getrennte Eigenschaften abzurufen. In unserem Fall ist das[[MTGSetting sharedInstance] valueForKey:@"jsonTitles"].
Beachten Sie, dass jsonTitles lediglich eine Instanz von NSMutableDictionary ist. Im Exploit dient sie als temporärer Speicher für unsere Referenzen. Der MTGRemoteCommandParser unterstützt die folgenden Parametertypen:
0– Zahl.1– Referenz.2– Zeichenfolge.4–nil.
Mit dem Referenztyp (1) können wir eine Objektreferenz als Argument einer Methode übergeben. Wichtig ist, dass uniqueIdentifier genau wie ein uniqueIdentifier der obersten Ebene analysiert wird – daher wird auch der Typ singleton unterstützt.
Schritt 2: Neue Instanz der Klasse UIAlertController erstellen
In diesem Fall steckt die ganze Magie in singleton_MTGSetting.jsonTitles.a.alloc.init. Wie wir bereits wissen, liefert singleton_MTGSetting.jsonTitles.a eine Referenz auf die Klasse UIAlertController. Wir müssen jedoch noch herausfinden, warum [[UIAlertController valueForKey:@"alloc"] valueForKey:@"init"] funktioniert. In der Dokumentation zu valueForKey: erfahren wir:
Das Suchmuster, mit dem valueForKey: den zurückzugebenden Wert findet, wird unter Accessor Search Patterns im Key-Value Coding Programming Guide beschrieben.
Wir haben herausgefunden, dass valueForKey: eine beliebige Methode anhand ihres Namens aufrufen kann, wenn sie keine Argumente erwartet.
Damit können wir nun eine neue Instanz der Klasse UIAlertController erstellen, auf die über die Eigenschaft b des Wörterbuchs jsonTitles verwiesen wird.
Schritt 3: Meldung „PWNED!“ festlegen
Dieser Schritt ist ziemlich offensichtlich: Wir rufen setMessage: für die Instanz von UIAlertController auf, um die Meldung PWNED! festzulegen.
Schritt 4: Referenz auf die Klasse UIApplication speichern
Dieser Schritt ähnelt Schritt 1. Wir müssen die Klassenreferenz von UIApplication in jsonTitles.x speichern.
Schritt 5: Meldung anzeigen
Dieser Schritt wirkt kompliziert, nutzt aber lediglich verschiedene Techniken aus den vorherigen Schritten. In Objective-C sieht der Code so aus:
Damit haben wir gezeigt, wie sich mithilfe von Remote Code Execution eine Meldung anzeigen lässt. Die vollständige Payload finden Sie hier. Um die Schritte nacheinander aufzurufen, haben wir ein Aktions-Array erstellt und jede Aktion im Callback window.WindVane.onSuccess ausgeführt (jeweils nach Abschluss der vorherigen Aktion).
Ein Video zeigt, wie sich Inhalte der Zwischenablage durch die Auslieferung des Exploits über eine bösartige Anzeige auslesen lassen.

Quelle des JavaScript-Exploits
Wir haben bereits gesehen, wie das Mintegral-SDK über JavaScript-Code die native Remote-Codeausführung ermöglicht. Dieser JavaScript-Code liegt jedoch vollständig in der Hand von Mintegral. Interessanterweise lässt sich dasselbe aber auch mit interaktiven Anzeigen erreichen, die von den Werbetreibenden selbst erstellt wurden. Bei den Anzeigen handelt es sich um JavaScript-basierte Webseiten.
Theoretisch kann ein Werbetreibender eine bestimmte Nutzergruppe oder eine bestimmte Gruppe von Geräten gezielt ansprechen, indem er eine bösartige Anzeige mit dem JavaScript-Exploit ausliefert.
Fazit
Wir können nur spekulieren, warum Mintegral die Möglichkeit integriert hat, native Methoden remote im SDK aufzurufen. Die Namen der Klassen, etwa MTGCommandDispatcher und MTGRemoteCommand, lassen uns jedoch vermuten, dass dies beabsichtigt war. Außerdem entfernte Mintegral den Code unmittelbar nach unserer Veröffentlichung, obwohl wir ihn zu diesem Zeitpunkt noch nicht kannten.
Download-Tracking unter Android [Oktober 2020]
Überblick
In den beiden vorangegangenen Abschnitten dieses Forschungsartikels haben wir beschrieben, wie das Snyk-Sicherheitsteam schädliches Verhalten im Mintegral-SDK entdeckt hat, das sich auf iOS-Geräten ausnutzen lässt und zu Anzeigenbetrug, Datenlecks und Remote Code Execution (RCE) führen kann. Wir wollten die Android-Version des SDK genauer untersuchen. Darum geht es in diesem Abschnitt. Hier die wichtigsten Ergebnisse:
Tracking von Download-URIs von Google, das sowohl Browser- als auch App-Downloads betrifft – darunter reguläre Dateidownloads, E-Mail-Anhänge und Google-Docs-Links.
Tracking aller APK-Downloads, unabhängig davon, ob sie organisch zustande kamen.
Diese Daten werden an die Server von Mintegral zurückgesendet.
Beobachtetes Verhalten
Beim Herunterladen eines Google-Docs-Links stellten wir fest, dass die App folgende Anfragen an https://n.systemlog.me sendet:

Dabei handelt es sich um denselben Endpunkt, der im iOS-SDK zum Senden von Daten an den Mintegral-Server verwendet wurde. Die Payload ist codiert. Mit der Decodierlogik aus der SDK-Binärdatei erhalten wir jedoch Folgendes:
Es gibt zwei weitere codierte Parameter: clever und dvi. Nachdem wir auch diese decodiert hatten, fiel uns etwas Interessantes auf:
Wie zu sehen ist, wird die URL der Google-Tabelle, die wir über die Google-Drive-App heruntergeladen haben, im Feld ul an das Backend gesendet. Der Name der heruntergeladenen Datei steht im Feld kw, während dvi einige Gerätedaten enthält.
Mögliche Verwendungszwecke
Im iOS-Szenario wurden betrügerische doppelte Klicks vom Gerät des Clients an die Mintegral-Server und anschließend an den Attribution-Anbieter (MMP) gesendet. In diesem Fall werden heruntergeladene oder installierte APKs an die Server gemeldet und könnten dazu verwendet werden, serverseitige Klicks zu erzeugen. Das folgende Diagramm veranschaulicht den Datenfluss:

Alphab-Modul
Das oben beschriebene Verhalten befindet sich im Alphab-Modul, das Mintegral als „Optimierungspaket“ bezeichnete:

Nach unserer Veröffentlichung wurde das Modul von der Mintegral-Website entfernt und scheint nicht mehr zum bereitgestellten SDK zu gehören. Wir haben das SDK dekompiliert und den für dieses Verhalten verantwortlichen Code gefunden.
Klasse AlphaCommonConst
Diese Klasse enthält zahlreiche fest codierte Konstantendefinitionen. Einige Zeichenfolgen sind mit einem eigenen, auf Base64 basierenden Codierungsverfahren verschleiert, das sich in der Klasse AlphabBase64Util befindet – ähnlich wie bei der iOS-Version.
Nach dem Decodieren erhalten wir folgende Zeichenfolgen:
Diese werden in den Initialisierungsschritten verwendet, die wir als Nächstes besprechen.
Alphab-Receiver
In der init()-Methode der Klasse AlphabReceiver wird der BroadcastReceiver mit einigen der zuvor verschleierten Zeichenfolgen initialisiert:
Wenn wir diese durch die decodierten Zeichenfolgen ersetzen, sieht der Code so aus:
Mithilfe der Java Reflection API wird ein neuer Broadcast-Receiver erstellt, der auf zwei Arten von Intents wartet:
android.intent.action.PACKAGE_ADDED– ein systemweiter Intent, der ausgelöst wird, wenn ein Paket auf dem Gerät installiert wird.alphab_net_debug_action– ein benutzerdefinierter Intent, der offenbar die Netzwerk-Debugging-Funktion erkennt.
Beim Empfang des Intents erstellt die Klasse AlphabReceiver eine ParseAndLoad()-Methode:
Dieses Feld wird später in einer Bedingung verwendet:
Die Dekompilierung der beiden anderen Methoden in dieser if-Anweisung zeigt, dass geprüft wird, ob die aktuelle Netzwerkverbindung über einen WLAN-Proxy oder einen VPN-Client läuft. Damit soll verhindert werden, dass die App debuggt und ihr Datenverkehr mitgeschnitten wird. Dieser Intent ermöglicht es den Entwicklern des SDK, diese Anti-Debugging-Funktion zu umgehen.
Alphab-Observer
Ähnlich dazu ist auch der Initialisierungsblock dieses ContentObserver in Reflection-Code und verschleierten Zeichenfolgen verborgen:
Nach der Bereinigung erhalten wir Folgendes:
Das bedeutet, dass der Content-Observer registriert wird, um auf die URI content://downloads zu achten. Er wird immer dann ausgelöst, wenn eine Datei auf das Gerät heruntergeladen wird.
Er fragt den Android-Download-Manager nach öffentlichen Downloads ab:
Wenn wir die Zeichenfolge decodieren, erhalten wir Folgendes:
Erfüllt die Download-URL eine der folgenden Bedingungen, wird ein Bericht an https://n.systemlog.met/stlog gesendet:
Endet mit
apk– bei manuellen Downloads.Verweist auf ein Paket von
com.android.vendingoder die URL enthält google.com – dadurch werden Google-Apps oder sogar Browser-URLs erfasst, die der Bedingung entsprechen.
Der folgende Codeausschnitt sendet die Anfrage an den Server https://n.systemlog.met/stlog.
Das entspricht:
„Hier sehen wir die Parameter, die wir auch in der mitgeschnittenen Anfrage aus unserem Beispiel gefunden haben:
p– Paketname des Downloads, also die Appv– App-Versionul– URL der heruntergeladenen Dateikw– Dateiname des Downloadsfl– Dateigröße
Demo-App

Um das Verhalten zu veranschaulichen, haben wir eine Demo-App erstellt, mit der wir Folgendes tun konnten:
1. Das Net-Debug-Flag mithilfe von Reflection aktivieren, um die Anti-Debugging-Logik zu umgehen
2. Eine Datei von einer URL herunterladen, die google.com enthält
3. Eine Datei von einer URL herunterladen, die mit apk endet
„Wir haben die ausgehenden Anfragen mit einem HTTP-Proxy mitgeschnitten. Nachdem wir auf eine der Download-Schaltflächen geklickt hatten, sahen wir eine Anfrage an den Endpunkt des Servers:

Dieses Video veranschaulicht das Tracking-Verhalten:

Zeitachse
Datum | Forschungsereignis |
|---|---|
5. Aug. | Das Snyk-Forschungsteam stellt fest, dass das Mintegral-iOS-SDK übermäßig viele Daten erfasst und Klicks kapert |
17. Aug. | Snyk meldet die Ergebnisse verantwortungsvoll an Apple |
24. Aug. | Snyk veröffentlicht die Ergebnisse zu Sour Mint für iOS |
25. Aug. | Mintegral veröffentlicht eine Stellungnahme und weist die Vorwürfe zum SDK zurück |
3. Sept. | IronSource kündigt an, Mintegral aus seiner Mediation-Plattform zu entfernen |
3. Sept. | Mintegral veröffentlicht Version 6.5.0.0 des iOS-SDK und entfernt die schädliche, verborgene Komponente _CXX_CXX_OperationPKTask |
4. Sept. | Die MoPub-(Twitter)-Mediation-Plattform kündigt an, Mintegral die Zertifizierung für ihre Plattform zu entziehen |
4. Sept. | Mintegral kündigt an, das SDK als Open Source freizugeben |
4. Sept. | Das Snyk-Forschungsteam entdeckt eine verborgene Funktion zum Tracking von Downloads in der Android-Version des SDK |
9. Sept. | Snyk meldet die Ergebnisse zum Android-SDK verantwortungsvoll an Google |
10. Sept. | Mintegral veröffentlicht Version 6.6.0.0 des iOS-SDK und entfernt die Backdoor-Komponente MTGRemoteCommandParser |
22. Sept. | Snyk erhält den Quellcode der iOS-SDK-Version 6.6.0.0 und führt eine Diff-Analyse durch |
23. Sept. | Snyk stellt fest, dass Mintegral das Google-Download-Tracking-Modul aus seinem Android-SDK entfernt hat |
30. Sept. | Durch eine Diff-Analyse entdeckt Snyk eine Backdoor in der iOS-Version des SDK, die RCE ermöglicht |
2. Okt. | Snyk meldet die neuen Ergebnisse zu iOS verantwortungsvoll an Apple |
3. Okt. | Apple benachrichtigt betroffene Publisher und fordert sie auf, den Code zu entfernen, der RCE ermöglicht |
15. Okt. | Snyk veröffentlicht die neuesten Ergebnisse zu iOS und Android |



