Recherchebericht zu schädlicher SDK-Software SourMint
Kirill Efimov
24. August 2020
0 Min. LesezeitÜberblick
Das Mintegral SDK ist ein beliebtes Werbe-SDK für mobile Apps und sowohl für iOS als auch Android verfügbar. Es wird von Tausenden mobilen Apps mit über einer Milliarde Downloads pro Monat genutzt. App-Entwickler verwenden das SDK, um ihre Apps mit Anzeigen von Drittanbietern zu monetarisieren.
Das Snyk-Security-Research-Team hat zwei bedeutende Sicherheitslücken im Mintegral SDK offengelegt. Die erste Offenlegung wurde im August 2020 veröffentlicht und deckte umfangreiche Datenerfassung sowie Click-Hijacking in der iOS-Version des SDK auf. Die zweite Offenlegung beschrieb eine in der iOS-Version des SDK entdeckte Hintertür, die Remote Code Execution ermöglicht, sowie neue Erkenntnisse zur Android-Version des SDK.
Dieser Artikel stellt die technischen Details unserer Untersuchungen und Erkenntnisse vor, die über die Inhalte der Blogbeiträge hinausgehen.
Dieser Bericht ist in drei Abschnitte unterteilt:
Umfangreiche Datenerfassung, einschließlich des Abfangens und Protokollierens sämtlicher HTTP-Anfragen im iOS-SDK – ursprünglich am 24. August 2020 veröffentlicht – beschreibt die URL- und Request-Tracking-Funktionen der iOS-Version des Mintegral SDK.
Eine Hintertür in der iOS-Version des SDK ermöglicht Remote Code Execution – dieser Abschnitt beschreibt die Remote-Code-Execution-Funktionen in MintegralAdSDK, veröffentlicht am 15. Oktober 2020.
URL-Tracking von Downloads unter Android – beschreibt verschiedene Erkenntnisse zur Android-Version des Mintegral SDK.
Umfangreiche 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 zu Datenlecks führen. Vereinfacht gesagt, spioniert das SDK aus, auf welche Links Nutzer klicken und welche Netzwerkaktivitäten in den betroffenen Apps stattfinden. Die Überwachung erfolgt selbst dann, wenn der Entwickler oder die Ad-Mediation-Plattform das SDK nicht aktiviert hat. Außerdem versucht das SDK, 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 zur Laufzeit die Implementierungen der Methoden UIApplication openURL und SKStoreProductViewController loadProductWithParameters zu ersetzen. Außerdem registriert es eine eigene Klasse NSURLProtocol.
Diese Hooks spionieren App-Nutzer aus, indem sie sämtliche Informationen zu HTTP-Anfragen, geöffneten URLs und App-Store-Links übermitteln, auf die Nutzer innerhalb der App klicken.
HTTP-Request-Header und URLs können selbst sensible Daten enthalten. Zusammen mit der IDFA (Identifier for Advertisers) ermöglichen diese Daten Mintegral jedoch, Betrug bei der Werbezuordnung zu begehen.
Betrug bei der Werbezuordnung
Um ihre Apps zu monetarisieren, installieren Entwickler häufig Werbeplattformen. Werbeplattformen erhalten von Werbetreibenden Einnahmen für jede Installation, die erfolgt, nachdem ein Nutzer auf deren Anzeige geklickt hat. Entwickler nutzen nicht selten mehrere Werbeplattformen in ihren Apps. Um festzustellen, welcher Werbeplattform die Installation zugeordnet werden soll, wird daher jeder Klick bei einem Attributionsanbieter registriert – einer Mobile Measurement Platform (MMP).
Die folgende Abbildung zeigt, wie die schädliche Funktion in Mintegral arbeitet. In diesem Beispiel hat der Nutzer auf eine Anzeige von „Another Platform“ geklickt. Da Mintegral jedoch alle von der App geöffneten URLs abfangen kann, kann es zusätzliche Anfragen an einen Attributionsanbieter senden und so vortäuschen, dass der Klick auf eine eigene Anzeige erfolgte. Der Ablauf sieht folgendermaßen aus:
Der Nutzer klickt auf einen Link in einer In-App-Anzeige eines Werbenetzwerks, das nicht zu Mintegral gehört, um eine neue App aus dem App Store zu installieren.
Das SDK des Werbenetzwerks sendet die Klickinformationen an seine Backend-Plattform.
Nachdem Mintegral das Klickereignis über Code abgefangen hat, der mithilfe von Method Swizzling in iOS-Ereignishandler eingeschleust wurde, protokolliert es die Klickdaten auf seinem Server.
Das Werbenetzwerk registriert eine Klickbenachrichtigung beim Attributionsanbieter.
Auch Mintegral registriert eine Klickbenachrichtigung beim Attributionsanbieter.
Wenn der Attributionsanbieter versucht, das Installationsereignis den registrierten Klickbenachrichtigungen zuzuordnen, findet er zwei passende Benachrichtigungen. Bei einem Last-Touch-Attributionsmodell wird der Klick Mintegral zugeordnet und die Klickbenachrichtigung 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 erzeugen. Bei der Untersuchung konnte der Anbieter nachweisen, dass solche Benachrichtigungen erstellt wurden und dazu führten, dass Anzeigenklicks fälschlicherweise Mintegral zugeordnet wurden.
Demo-App
Um den Angriff zu demonstrieren, haben wir eine Demo-App eingerichtet. Sie zeigt den schädlichen openURL-Hook in Aktion. Mit einem Debugging-Proxy fangen wir den gesamten Netzwerkverkehr ab.
Zur Initialisierung der App verwenden wir den folgenden Codeausschnitt aus der Mintegral-Dokumentation:
Nach der Initialisierung des SDK öffnen wir example.com in der App, indem wir auf eine Schaltfläche klicken:
Nach dem Start der App sehen wir sofort einige Anfragen des Mintegral SDK in unserem Proxy:
GET https://setting.rayjump.com/sdk/customidGET https://setting.rayjump.com/settingPOST https://analytics.rayjump.com

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 abgegriffenen Informationen gesendet werden (*). |
cspn | Aktiviert oder deaktiviert Hooks für StoreKit-Methoden. |
cud | Aktiviert oder deaktiviert den Hook für NSURLProtocol. |
cudl | Array von URLs, die über NSURLProtocol verfolgt werden (**). |
* In unserem Fall war es LdxThdi1WBK/WgfPhbxQYkeXHBPwHZKsYFh= und nach dem Dekodieren https://n.systemlog.me/log.
** In unserem Fall war es kBzuJd5/H+i/D+SMY7V/DFKwR0M0D+SMhBPthdSsHZPUYFT0+N==und nach dem Dekodieren ["itunes.apple.com","apps.apple.com"].
Payload dekodieren
Nach dem Klick auf die Schaltfläche, die example.com öffnet, sehen wir zwei weitere Anfragen. Die erste ist wie erwartet eine GET-Anfrage an http://example.com. Die zweite ist eine POST-Anfrage an https://n.systemlog.me/log.

Der Request-Body sieht aus, als wäre er Base64-kodiert. Tatsächlich handelt es sich jedoch nicht um eine Base64-kodierte Zeichenfolge. Das Mintegral SDK implementiert eine eigene Kodierungs- und Dekodierungslogik, die in +[MTGBase base64DecodeString:] und +[MTGBase base64CleverDecodeString:] zu finden ist. Beachten Sie, dass MTGBase nicht in den öffentlichen Headern des SDK offengelegt ist und Entwicklern nicht zur Verfügung stehen soll.
Zum Dekodieren des Payloads verwenden wir den folgenden Codeausschnitt:

Der Payload enthält viele Daten, darunter IDFA, IDFV, die Betriebssystemversion, den User-Agent und mehr. Er enthält jedoch auch ein Feld namens „clever“, das wiederum 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 den Methodennamen.
Ein genauerer Blick
Wie bereits erwähnt, ist das Mintegral SDK proprietär. Wir untersuchen Version 6.3.5.0 für die x86-Architektur.
Bei der Binärdatei handelt es sich um eine Mach-O-Executable, 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. Das bedeutet: Wird das SDK über CocoaPods installiert, wird die schädliche Logik initialisiert – unabhängig davon, ob Entwickler das SDK tatsächlich verwenden.
Die Methode load führt eine Reihe von Aufrufen aus, die uns zu ___cxxwebk_init_vw führen. Diese Methode prüft, ob das Anti-Debugging-Schutz-Flag aktiviert ist, und initialisiert Hooks, wenn das Flag auf „false“ gesetzt ist oder das Debugging deaktiviert ist.

Die Initialisierung der Hooks hängt von der oben erwähnten Einstellungsanfrage ab. Die folgende Tabelle zeigt die Beziehungen zwischen den JSON-Antwortfeldern und der Klasse MTGSetting:
JSON-Feld | MTGSetting-Eigenschaft | Beschreibung |
|---|---|---|
csw | cSrtW | Aktiviert oder deaktiviert die Anti-Debugging-Funktion. |
cou | cOpenURL | Aktiviert oder deaktiviert den |
cspn | cPackageName | Aktiviert oder deaktiviert Hooks 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 ist auf dem Gerät vorhanden (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 (über
CFNetworkCopySystemProxySettings).
openURL-Methoden-Swizzling
Die Logik im folgenden Screenshot ist in der Methode ___cxxwebkmcouitninapo implementiert. Sie wird von ___cxxwebk_init_vw aufgerufen, wenn das entsprechende Flag aktiviert ist.

Der obige Screenshot zeigt die Implementierung des Method Swizzling. Dabei werden folgende Aufrufe ausgeführt:
NSSelectorFromStringermittelt einen Selector für die Methode „openURL:“.NSClassFromStringermittelt einen Klassen-Deskriptor fürUIApplication.class_getInstanceMethodermittelt den Methoden-Deskriptor.method_getImplementationermittelt die tatsächliche Implementierung der Methode.Anschließend wird ein Codeblock definiert, der
_____cxxwebkmcouitninapo_block_invoke_2und danach das ursprünglicheopenURLaufruft.method_setImplementationersetzt das ursprüngliche openURL durch den Codeblock aus dem vorherigen Schritt.
Bei der Methode openURL:options:completionHandler: läuft es fast genauso ab. Zuvor wird jedoch die Systemversion geprüft (der Handler wurde erstmals in iOS 10 eingeführt).
Nun haben wir gesehen, wie der Hook angewendet wird. Als Nächstes untersuchen wir die Implementierung des Hooks selbst (_____cxxwebkmcouitninapo_block_invoke_2).
Implementierung des openURL-Hooks
Die Implementierung befindet sich in der Methode ___cxxwebkmcoulsz. Dort sehen wir einen weiteren Anti-Debugging-Aufruf. Anschließend wird das Flag __mc_notifyInHouse geprüft. Ist es auf 1 gesetzt, geschieht nichts.
Damit werden alle Marketing-URLs ignoriert, auf die ein Nutzer in einer von Mintegral ausgelieferten Anzeige klickt. Die entsprechende Logik ist im Screenshot unten in +[MTGBase mtgOpenURL:options:completionHandler:] zu sehen:

Der nächste Codeausschnitt zeigt, dass auch die Backtrace-Daten serialisiert und im Payload 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 erfolgte (
ViewController).Die Methode, aus der heraus der Klick erfolgte (
openURLWithOptions:).Backtrace-Informationen.
Eine weitere interessante Funktion ist _nsh_id_by_cc. Sie scheint für die Erkennung konkurrierender SDKs zuständig zu sein. Die entsprechende 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, wird ein neuer Codeblock erstellt und mit _dispatch_async aufgerufen.
Es folgt eine Reihe von Aufrufen mit zusätzlichen Payload-Transformationen, die schließlich bei -[_MC_ApiManager AFRequestWithUrl:paras:success:failure:] enden. Diese Methode sendet eine POST-Anfrage an collectDomainUrl aus MTGSetting, das standardmäßig auf https://n.systemlog.me/log gesetzt ist.
Ein Video zeigt, wie eine private URL offengelegt werden kann.

Hook für SKStoreProductViewController
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.
Anstatt auf technische Details zur Implementierung des Hooks einzugehen, haben wir den folgenden Codeausschnitt zur Demo-Anwendung hinzugefügt:
Das Ergebnis ist eine POST-Anfrage an https://n.systemlog.me/log mit der folgenden Payload im Feld „clever“:
Wie wir sehen, ist die Produkt-ID in der Anfrage enthalten. Damit ist es bewiesen.
Hook für NSURLProtocol
Die Klasse NSURLProtocol ermöglicht es Entwicklerinnen und Entwicklern, das Verhalten von Apples URL-Ladesystem neu zu definieren. Das Mintegral SDK registriert eine schädliche Implementierung von NSURLProtocol, die aus der Ferne so konfiguriert werden kann, dass sie beliebige ausgehende Anfragen einer Anwendung abfängt und URLs sowie HTTP-Header einschließlich des Authorization-Headers erfasst.
Für Anwendungsentwickler bedeutet das, dass Mintegral möglicherweise API-Token, 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 Flag cud aktiviert und das Array cudl nicht leer sein muss, um den Hook zu aktivieren.
Der folgende Screenshot zeigt einen Teil der Funktion ___cxxwebkterisiuuxx, die von der obigen Methode aufgerufen wird.

Der Code in der Funktion ___cxxwebkterisiuuxx führt die folgenden Aktionen aus:
Erstellt eine von
NSURLProtocolabgeleitete Klasse (objc_registerClassPair,objc_allocateClassPair).Fügt eine Implementierung für
canInitWithRequest:hinzu, die effektiv als Interceptor fungiert (class_addMethod).Ruft
+[NSURLProtocol registerClass:]auf, um die Klasse beim URL-Ladesystem zu registrieren.
Im Rahmen unserer Recherche haben wir den folgenden Codeausschnitt hinzugefügt, um zu überprüfen, welche Daten der schädliche Code erfasst:
Das Ergebnis ist eine POST-Anfrage an https://n.systemlog.me/log mit der folgenden Payload im Feld „clever“:
In der Anfrage sehen wir die URL und den Authorization-Header. Der Anfrage-Body ist zwar nicht enthalten, aber Header enthalten häufig sensible Daten. Diese Daten können sogar personenbezogene Informationen umfassen. Wenn eine API beispielsweise JWT-Token verwendet, können E-Mail-Adresse oder Benutzername im Token gespeichert sein.
Fazit
Während unserer Recherche haben wir viele interessante Techniken beobachtet, mit denen Mintegral-Entwickler das schädliche Verhalten ihres SDKs verschleiern. Wie wir sehen, aktivieren sie Hooks nur für bestimmte Anwendungen in bestimmten Regionen. Dadurch blieb der schädliche Code mehr als ein Jahr lang unentdeckt.
Zur zeitlichen Einordnung: Die erste Version (5.5.1) des schädlichen SDKs 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 SDKs betroffen. Wir hoffen, dass diese Recherche die Situation ins Bewusstsein rückt und künftig für mehr Kontrolle und Datenschutz bei Werbenetzwerken sorgt.
Remote Code Execution (RCE) unter iOS [Oktober 2020]
Kurzfassung
Wir haben die Klasse MTGBaseBridgeWebView entdeckt, die im gesamten SDK für die Kommunikation mit JavaScript verwendet wird. Sie fungiert als Hintertür und ermöglicht den Aufruf beliebiger Funktionen aus dem nativen Anwendungscode.

Das Bild 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 SDKs an.
Wir verglichen die neue Open-Source-Version mit der vorherigen Binärversion, die als CocoaPod verteilt wurde. Zwar hatten wir keinen Zugriff auf den Quellcode der älteren Version, konnten aber 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 fiel jedoch etwas anderes auf. Die folgenden Klassen erregten unsere Aufmerksamkeit:
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. Version 6.6.0.0, veröffentlicht am 10. September 2020, enthält nicht die in diesem Artikel beschriebene Hintertürfunktion.
Die Bridge-Implementierung
Wir untersuchten zunächst, wo die Klasse MTGRemoteCommandParser verwendet wird, und fanden nur eine Stelle: -(void)handleNativeObject:parameters: in der Klasse MTGBaseBridgeWebView.
Die Implementierung zeigt, dass -(void)handleNativeObject:parameters: MTGRemoteCommandParser verwendet, um das Argument parameters zu parsen, 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 sich die Methode aus JavaScript-Code aufrufen lässt.
MTGBaseBridgeWebView implementiert die Methode -(void)webView:decidePolicyForNavigationAction:decisionHandler: des Protokolls WKNavigationDelegate. Diese Methode wird bei jeder Navigation in der Webansicht aufgerufen. Das bedeutet, dass wir sie aus JavaScript heraus auslösen können, indem wir einfach location.href=something aufrufen. In der Open-Source-Version des SDKs fanden wir einen regulären Ausdruck, der URLs von Navigationsanfragen parst: 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-Zeile: location.href = 'mv://1:fucId/handleNativeObject?<parameters>'.
Bitte beachten Sie, dass alles, was wir oben beschrieben haben, zum Zeitpunkt der Erstellung dieses Artikels auch in der neuesten SDK-Version sowie in der Open-Source-Version des SDKs weiterhin gilt. Die einzige Ausnahme: -(void)handleNativeObject:parameters: wurde aus den neuesten Versionen entfernt.
Aufruf entfernter Methoden
Wir beschreiben nicht die vollständige Implementierung von MTGInvocationBoxing und 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 „einfache Notiz“-Anwendung 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.
Dabei kommen dieselben Verschleierungstechniken zum Einsatz, die im vorherigen Abschnitt beschrieben wurden. 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 mit dem SDK jede statische Methode einer beliebigen Klasse aufrufen lässt. 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.
Betrachten wir den folgenden Objective-C-Code als Referenz:
Wir müssen herausfinden, wie eine Instanz von UIAlertController erstellt und zwischen den Aufrufen beibehalten werden kann, wie sich eine gemeinsame Anwendungsinstanz abrufen lässt und wie presentViewController:animated:completion: mit dieser Instanz aufgerufen wird.
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 anhand des Namens eine Klasse ab (in unserem Beispiel
MTGSetting).Führt die Methode
sharedInstancefür die Klasse aus.[MTGSetting sharedInstance]in Objective-C.
Verwendet
valueForKey:, um Eigenschaften abzurufen, deren Namen durch Punkte getrennt sind. In unserem Fall lautet der Aufruf[[MTGSetting sharedInstance] valueForKey:@"jsonTitles"].
Beachten Sie, dass jsonTitles lediglich eine Instanz von NSMutableDictionary ist. Im Exploit wird sie als temporärer Speicher für unsere Referenzen verwendet. Der MTGRemoteCommandParser unterstützt die folgenden Parametertypen:
0– Zahl.1– Referenz.2– Zeichenfolge.4–nil.
Mit dem Referenztyp (1) können wir eine Referenz auf ein Objekt als Methodenargument übergeben. Wichtig ist, dass uniqueIdentifier genau wie ein uniqueIdentifier der obersten Ebene geparst wird – daher wird auch der Typ singleton unterstützt.
Schritt 2: Neue Instanz der Klasse UIAlertController erzeugen
In diesem Fall läuft die gesamte Magie in singleton_MTGSetting.jsonTitles.a.alloc.init ab. Wie wir bereits wissen, liefert uns singleton_MTGSetting.jsonTitles.a eine Referenz auf die Klasse UIAlertController. Wir müssen jedoch herausfinden, warum [[UIAlertController valueForKey:@"alloc"] valueForKey:@"init"] funktioniert. In der Dokumentation zu valueForKey: steht:
Das Suchmuster, das valueForKey: verwendet, um den zurückzugebenden Wert zu finden, wird unter Suchmuster für Zugriffsmethoden im Programmierreferenz zu Key-Value-Coding beschrieben.
Wir haben herausgefunden, dass valueForKey: jede Methode anhand ihres Namens aufrufen kann, sofern sie keine Argumente hat.
Wir können nun also eine neue Instanz der Klasse UIAlertController erstellen, auf die über die Eigenschaft b des jsonTitles-Dictionaries verwiesen wird.
Schritt 3: Meldung „PWNED!“ festlegen
Dieser Schritt ist naheliegend: Wir rufen für die Instanz von UIAlertController setMessage: 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: Warnmeldung anzeigen
Dieser Schritt wirkt kompliziert, nutzt aber lediglich verschiedene Techniken aus den vorherigen Schritten. In Objective-C sähe der Code so aus:
Damit haben wir gezeigt, wie sich per Remote Code Execution eine Warnmeldung anzeigen lässt. Die vollständige Payload finden Sie hier . Um die einzelnen Schritte nacheinander aufzurufen, haben wir ein Array mit Aktionen erstellt und jede Aktion im Callback window.WindVane.onSuccess ausgeführt – jeweils nachdem die vorherige Aktion abgeschlossen war.
Ein Video zeigt, wie sich Inhalte der Zwischenablage durch die Auslieferung des Exploits über eine schädliche Anzeige auslesen lassen.

Quellcode des JavaScript-Exploits
Wir haben bereits gesehen, wie das Mintegral SDK die native Remote-Code-Ausführung über JavaScript-Code ermöglicht. Dieser JavaScript-Code liegt jedoch vollständig in der Kontrolle von Mintegral. Interessanterweise lässt sich dasselbe aber auch mit interaktiven Anzeigen erreichen, die von den Werbetreibenden selbst erstellt werden. Bei den Anzeigen handelt es sich um JavaScript-basierte Webseiten.
Theoretisch kann ein Werbetreibender eine bestimmte Nutzergruppe oder bestimmte Geräte gezielt ansprechen, indem er eine schädliche Anzeige mit dem JavaScript-Exploit ausliefert.
Fazit
Wir können nur darüber spekulieren, warum Mintegral die Möglichkeit eingebaut hat, native Methoden remote über das SDK aufzurufen. Die Namen der Klassen, etwa MTGCommandDispatcher und MTGRemoteCommand, lassen jedoch darauf schließen, dass dies beabsichtigt war. Außerdem entfernte Mintegral den Code unmittelbar nach unserer Veröffentlichung, obwohl wir zu diesem Zeitpunkt noch nichts davon wussten.
Download-Tracking unter Android [Oktober 2020]
Überblick
In den beiden vorherigen Abschnitten dieses Forschungsartikels haben wir beschrieben, wie das Snyk-Security-Research-Team schädliches Verhalten im Mintegral SDK entdeckt hat, das sich auf iOS-Geräten ausnutzen lässt und zu Anzeigenbetrug, Datenlecks und Remote-Code-Ausführung (RCE) führen kann. Wir wollten weitere Untersuchungen zur Android-Version des SDK durchführen. Darum geht es in diesem Abschnitt.
Zusammengefasst sind dies unsere wichtigsten Erkenntnisse:
Tracking von Download-URIs durch Google, das Browser- und 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 übermittelt.
Beobachtetes Verhalten
Beim Herunterladen eines Google Docs-Links bemerkten wir, dass die App folgende Anfragen an https://n.systemlog.me sendete:

Es handelt sich um denselben Endpunkt, der im iOS SDK verwendet wurde, um Daten an den Mintegral-Server zu übermitteln. Die Nutzdaten sind kodiert. Mithilfe der Dekodierungslogik im SDK-Binary können wir jedoch Folgendes auslesen:
Es gibt zwei weitere kodierte Parameter: clever und dvi. Nachdem wir auch diese dekodiert hatten, fiel uns etwas Interessantes auf:
Wie zu sehen ist, wird die URL des Google Sheets, das wir aus der Google Drive-App heruntergeladen haben, in der Datei ul und der Name der heruntergeladenen Datei im Feld kw an das Backend übermittelt. dvi enthält einige Gerätedaten.
Mögliche Verwendungszwecke
Im iOS-Szenario wurden betrügerische, doppelte Klicks vom Gerät des Clients an die Server von Mintegral und anschließend an den Attributionsanbieter (MMP) gesendet. In diesem Fall werden heruntergeladene oder installierte APKs an die Server gemeldet und könnten dazu verwendet werden, serverseitige Klicks zu generieren. Das folgende Diagramm zeigt den Datenfluss:

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

Nach unserer Veröffentlichung wurde das Modul von der Mintegral-Website entfernt und scheint nicht mehr Bestandteil des ausgelieferten SDK zu sein. Wir haben das SDK dekompiliert und den für dieses Verhalten verantwortlichen Code gefunden.
Klasse AlphaCommonConst
Diese Klasse enthält zahlreiche hartcodierte Konstantendefinitionen. Einige Strings sind mit einem eigenen, auf Base64 basierenden Kodierungsverfahren verschleiert, das sich in der Klasse AlphabBase64Util befindet – ähnlich wie bei der iOS-Version.
Nach dem Dekodieren erhalten wir folgende Strings:
Diese werden in den Initialisierungsschritten verwendet, die wir als Nächstes besprechen.
Alphab-Receiver
In der Methode init() der Klasse AlphabReceiver wird der BroadcastReceiver mit einigen der zuvor verschleierten Strings initialisiert:
Ersetzt man diese durch die dekodierten Strings, 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 Netzwerk-Debugging erkennt.
Beim Empfang des Intents erstellt die Klasse AlphabReceiver eine Methode namens ParseAndLoad():
Dieses Feld wird später in einer Bedingung verwendet:
Die Dekompilierung der beiden anderen Methoden in dieser if-Klausel zeigt, dass sie prüfen, 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 SDK-Entwicklern, diese Anti-Debugging-Funktion zu umgehen.
Alphab-Observer
Ähnlich wie beim Receiver ist auch der Initialisierungsblock dieses ContentObserver in Reflection und verschleierten Strings verborgen:
Nach der Bereinigung erhalten wir Folgendes:
Das bedeutet, dass der Content-Observer registriert wird, um auf die URI content://downloads zu warten. Er wird ausgelöst, sobald eine Datei auf das Gerät heruntergeladen wird.
Er fragt den Android-Download-Manager nach öffentlichen Downloads ab:
Nach dem Dekodieren des Strings 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 – damit werden Google-Apps sowie Browser-URLs erfasst, die der Bedingung entsprechen.
Unten sehen Sie den Codeausschnitt, der die Anfrage an den Server unter https://n.systemlog.met/stlog sendet.
Das entspricht:
Hier sehen wir die Parameter, die auch in der aufgezeichneten Anfrage unseres Beispiels vorkamen:
p– Paketname der herunterladenden Appv– App-Versionul– URL der heruntergeladenen Dateikw– Dateiname der heruntergeladenen Dateifl– Dateigröße
Demo-App

Um dieses Verhalten zu demonstrieren, haben wir eine Demo-App erstellt, mit der wir Folgendes tun konnten:
1. Das Net-Debug-Flag per 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 mithilfe eines HTTP-Proxys aufgezeichnet. Nachdem wir auf eine der Download-Schaltflächen geklickt hatten, konnten wir sehen, wie eine Anfrage an den Endpunkt des Servers gesendet wurde:

Dieses Video zeigt das Tracking-Verhalten:

Zeitleiste
Datum | |
|---|---|
5. August | Das Snyk-Security-Research-Team entdeckt übermäßige Datenerfassung und Klick-Hijacking im Mintegral iOS SDK |
17. August | Snyk meldet die Erkenntnisse verantwortungsvoll an Apple |
24. August | Snyk veröffentlicht die Erkenntnisse zu Sour Mint unter iOS |
25. August | Mintegral veröffentlicht eine Stellungnahme, in der die Vorwürfe gegen das SDK zurückgewiesen werden |
3. September | IronSource kündigt an, Mintegral aus seiner Mediation-Plattform zu entfernen |
3. September | Mintegral veröffentlicht Version 6.5.0.0 des iOS SDK und entfernt die schädliche, versteckte Komponente _CXX_CXX_OperationPKTask |
4. September | Die MoPub-(Twitter-)Mediation-Plattform kündigt an, Mintegral auf ihrer Plattform die Zertifizierung zu entziehen |
4. September | Mintegral kündigt an, sein SDK als Open Source bereitzustellen |
4. September | Das Snyk-Security-Research-Team entdeckt eine versteckte Download-Tracking-Funktion in der Android-Version des SDK |
9. September | Snyk meldet die Erkenntnisse zum Android SDK verantwortungsvoll an Google |
10. September | Mintegral veröffentlicht Version 6.6.0.0 des iOS SDK und entfernt die Backdoor-Komponente MTGRemoteCommandParser |
22. September | Snyk erhält den Quellcode der Version 6.6.0.0 des iOS SDK und führt eine Diff-Analyse durch |
23. September | Snyk entdeckt, dass Mintegral das Google-Download-Tracking-Modul aus seinem Android SDK entfernt hat |
30. September | Durch eine Diff-Analyse entdeckt Snyk eine Backdoor in der iOS-Version des SDK, die RCE ermöglicht |
2. Oktober | Snyk meldet neue Erkenntnisse zu iOS verantwortungsvoll an Apple |
3. Oktober | Apple benachrichtigt betroffene Publisher und fordert sie auf, den RCE ermöglichenden Code zu entfernen |
15. Oktober | Snyk veröffentlicht die neuesten Erkenntnisse zu iOS und Android |



