SourMintの悪意あるSDKに関する調査レポート
Kirill Efimov
2020年10月16日
0 分で読めます概要
Mintegral SDKは、iOSとAndroidの両プラットフォームで利用できる、人気のモバイルアプリ広告SDKです。毎月10億回以上ダウンロードされる数千のモバイルアプリで利用されています。アプリ開発者は、このSDKを使ってサードパーティ広告を配信し、アプリを収益化します。
Snykのセキュリティリサーチチームは、Mintegral SDKに関する重大な開示を2件行いました。最初の開示は2020年8月に公開され、SDKのiOS版で過剰なデータ収集とクリックハイジャックが行われていることを明らかにしました。2件目の開示では、SDKのiOS版にリモートコード実行を可能にするバックドアが見つかったほか、SDKのAndroid版についても新たな発見がありました。
この記事では、ブログ記事で取り上げた内容を超えて、調査と発見事項の技術的な詳細を紹介します。
このレポートは、次の3つのセクションで構成されています。
過剰なデータ収集(iOS SDKにおけるすべてのHTTPリクエストの傍受と記録を含む)—2020年8月24日に公開された内容で、Mintegral SDKのiOS版におけるURLとリクエストの追跡機能について説明します。
SDKのiOS版におけるバックドアがリモートコード実行を可能にする—2020年10月15日に公開されたMintegralAdSDKのリモートコード実行機能について説明します。
AndroidでのダウンロードURL追跡—Mintegral SDKのAndroid版に関するさまざまな発見事項を説明します。
iOSでの過剰なデータ収集[2020年8月]
概要
この調査のパートでは、2020年8月時点でオープンソース版を入手できなかったため、Mintegral iOS SDKのバイナリ版を調査しました。調査対象は、GitHubからダウンロードできるSDKバージョン6.3.5.0(x86アーキテクチャ)です。
Mintegral iOS SDKのバージョン5.5.1以降には、情報漏えいにつながる悪意ある機能が含まれていることを確認しました。簡単に言えば、このSDKはユーザーによるリンクのクリックや、影響を受けるアプリ内のネットワークアクティビティを監視します。この監視は、開発者や広告メディエーションプラットフォームがSDKを有効にしていなくても行われます。また、プロキシ、シミュレーター、脱獄済みデバイスを検出し、悪意ある動作を隠そうとします。
メソッドスウィズリング
Mintegral SDKは、メソッドスウィズリングと呼ばれる手法を使って、実行時にUIApplication openURLメソッドとSKStoreProductViewController loadProductWithParametersメソッドの実装を置き換え、さらに独自のNSURLProtocolクラスを登録します。
これらのフックは、アプリ内でユーザーが行ったHTTPリクエストや開いたURL、クリックしたApp Storeリンクに関する情報をすべて送信し、アプリのユーザーを監視するために使われます。
HTTPリクエストのヘッダーやURL自体に機密データが含まれている可能性がありますが、IDFA(広告主識別子)と組み合わせることで、Mintegralは広告アトリビューション詐欺を実行できます。
広告アトリビューション詐欺
アプリを収益化するため、開発者は広告プラットフォームを導入することがよくあります。広告プラットフォームは、ユーザーが広告をクリックした後にアプリがインストールされるたび、広告主から収益を受け取ります。開発者がアプリで複数の広告プラットフォームを使うことも珍しくありません。そのため、インストールのアトリビューションをどの広告プラットフォームに付与すべきか判断するために、クリックはそれぞれ、アトリビューションプロバイダーであるモバイル計測プラットフォーム(MMP)に登録されます。
下の図は、Mintegralの悪意ある機能の仕組みを示しています。この例では、ユーザーは「Another Platform」の広告をクリックしました。しかし、Mintegralはアプリが開くすべてのURLを傍受できるため、アトリビューションプロバイダーに追加のリクエストを送り、あたかも自社の広告がクリックされたかのように見せかけることができます。処理の全体像は次のとおりです。
ユーザーが、Mintegral以外の広告ネットワークが配信したアプリ内広告のリンクをクリックし、App Storeから新しいアプリをインストールします。
広告ネットワークのSDKが、クリック情報をバックエンドプラットフォームに送信します。
メソッドスウィズリングを介してiOSのイベントハンドラーに注入されたコードでクリックイベントを傍受したMintegralは、クリックデータをサーバーに記録します。
広告ネットワークが、アトリビューションプロバイダーにクリック通知を登録します。
Mintegralも、アトリビューションプロバイダーにクリック通知を登録します。
アトリビューションプロバイダーがインストールイベントと登録済みのクリック通知を照合すると、一致する通知が2件見つかります。ラストタッチアトリビューションモデルでは、Mintegralのクリック通知にアトリビューションが付与され、もう一方の広告ネットワークのクリック通知は却下されます。

Snykは大手アトリビューションプロバイダーと連携し、Mintegralがクリックデータを使って偽のクリック通知を生成していることを確認しました。プロバイダーの調査により、偽のクリック通知が生成され、広告クリックのアトリビューションが誤ってMintegralに付与されていることが明らかになりました。
デモアプリ
攻撃を実証するため、デモアプリを用意しました。このアプリでは、悪意あるopenURLフックの動作を確認できます。デバッグ用プロキシを使って、すべてのネットワークトラフィックを傍受します。
アプリの初期化には、Mintegralのドキュメントにある次のコードスニペットを使います。
SDKを初期化した後、ボタンをクリックしてアプリからexample.comを開きます。
アプリを起動するとすぐに、プロキシ上でMintegral SDKからのリクエストがいくつか確認できます。

設定
https://setting.rayjump.com/setting_からのレスポンスは、さまざまなオプションを含むJSONオブジェクトです。次の表では、調査上特に注目すべきフィールドを説明します。
JSONフィールド | 説明 |
|---|---|
csw | アンチデバッグ機能の有効・無効を切り替えます。 |
cou |
|
cdai | 漏えいした情報の送信先URL(*)。 |
cspn | StoreKitメソッドのフックの有効・無効を切り替えます。 |
cud | NSURLProtocolのフックの有効・無効を切り替えます。 |
cudl | NSURLProtocolで追跡するURLの配列(**)。 |
* 今回の場合はLdxThdi1WBK/WgfPhbxQYkeXHBPwHZKsYFh=で、デコードするとhttps://n.systemlog.me/logになります。
** 今回の場合はkBzuJd5/H+i/D+SMY7V/DFKwR0M0D+SMhBPthdSsHZPUYFT0+N==で、デコードすると["itunes.apple.com","apps.apple.com"]になります。
ペイロードのデコード
example.comを開くボタンをクリックすると、さらに2つのリクエストが確認できます。1つ目は予想どおりhttp://example.comへのGETリクエストです。2つ目はhttps://n.systemlog.me/logへのPOSTリクエストです。

リクエストの本文はBase64でエンコードされているように見えますが、実際にはBase64文字列ではありません。Mintegral SDKは独自のエンコード・デコードロジックを実装しており、+[MTGBase base64DecodeString:]と+[MTGBase base64CleverDecodeString:]に記述されています。MTGBaseはSDKの公開ヘッダーに公開されておらず、開発者がアクセスすることを想定していない点に注意してください。
次のコードスニペットを使ってペイロードをデコードします。

ペイロードには、IDFA、IDFV、OSバージョン、ユーザーエージェントなど、多くのデータが含まれています。また、「clever」というフィールドもあり、こちらもエンコードされています。base64DecodeStringを使ってデコードできます。
ご覧のとおり、URL、スタックトレースのほか、コントローラー名やメソッド名などの追加情報も含まれています。
さらに詳しく調べる
前述のとおり、Mintegral SDKはクローズドソースです。ここでは、x86アーキテクチャ向けのバージョン6.3.5.0を調査します。
バイナリは、複数の別のバイナリを含むMach-O実行ファイルです。調査対象のコードは_CXX_CXX_OperationPKTask.oにあります。
クラスを確認すると、+[_CXX_CXX_OperationPKTask load]が見つかります。このメソッドは、クラスが実行時に追加されると自動的に実行されます。つまり、SDKをCocoaPods経由でインストールすると、開発者が実際にSDKを使うかどうかにかかわらず、悪意あるロジックが初期化されます。
loadメソッドはいくつかの呼び出しを行い、最終的に___cxxwebk_init_vwに到達します。このメソッドはアンチデバッグ保護フラグが有効かどうかを確認し、フラグがfalseの場合、またはデバッグが無効の場合にフックを初期化します。

フックの初期化は、前述の設定リクエストに依存します。次の表は、レスポンス内のJSONフィールドとMTGSettingクラスの対応関係を示しています。
JSONフィールド | MTGSettingプロパティ | 説明 |
|---|---|---|
csw | cSrtW | アンチデバッグ機能の有効・無効を切り替えます。 |
cou | cOpenURL |
|
cspn | cPackageName | StoreKitメソッドのフックの有効・無効を切り替えます。 |
アンチデバッグロジック

__cxx_cxx_op_isInSuperViewFrame関数は、次の場合にtrueを返します。
デバイスのプラットフォームが「シミュレーター」である。
デバッガーがアタッチされている(
____mvpmvvm_isDebuggerAttached_block_invokeで実装)。デバイス上に次のファイルのいずれかが存在する(脱獄の兆候)。
/Applications/Cydia.app
/Library/MobileSubstrate/MobileSubstrate.dylib
/bin/bash
/usr/sbin/sshd
/etc/apt
/usr/bin/ssh
プロキシが有効になっている(
CFNetworkCopySystemProxySettingsを使用)。
openURLのメソッドスウィズリング
次のスクリーンショットのロジックは___cxxwebkmcouitninapoメソッドに実装されており、該当するフラグが有効な場合に___cxxwebk_init_vwから呼び出されます。

「blog-sour-mint-openurl-method-swirl」—上のスクリーンショットは、メソッドスウィズリングの実装を示しています。次の呼び出しを実行します。
「openURL:」メソッドのセレクターを取得する
NSSelectorFromString。UIApplicationのクラス記述子を取得するNSClassFromString。メソッド記述子を取得する
class_getInstanceMethod。メソッドの実際の実装を取得する
method_getImplementation。次に、
_____cxxwebkmcouitninapo_block_invoke_2を呼び出した後、元のopenURLを呼び出すコードブロックを定義します。method_setImplementationを使い、元のopenURLを前の手順で作成したコードブロックに置き換えます。
openURL:options:completionHandler:メソッドでもほぼ同じ処理が行われますが、その前にシステムバージョンを確認します(このハンドラーが導入されたのはiOS 10です)。
ここまでで、フックがどのように適用されるかを確認しました。次に、フック自体の実装(_____cxxwebkmcouitninapo_block_invoke_2)を見ていきます。
openURLフックの実装
実際の実装は___cxxwebkmcoulszメソッドにあります。ここでは、もう1つのアンチデバッグチェックが呼び出された後、__mc_notifyInHouseフラグが確認され、このフラグが1の場合は何も行いません。
これは、ユーザーがMintegralが配信した広告でクリックしたマーケティングURLをすべて無視するためです。下のスクリーンショットにある+[MTGBase mtgOpenURL:options:completionHandler:]で、該当するロジックを確認できます。

次のコードから、バックトレースデータもシリアライズし、https://n.systemlog.me/logに送信するペイロードに含めて漏えいさせていることが分かります。
+[_CXX_CXX_OperationPKTask _cxx_cm_log_warnings:to:ins:]の呼び出しにブレークポイントを設定できます。次のスクリーンショットで、呼び出し引数を確認できます。

開かれたURL(http://example.com?foo=bar&x=y)。
クリックが発生したクラス(
ViewController)。クリックが発生した箇所から呼び出されるメソッド(
openURLWithOptions:)。バックトレース情報。
もう1つ興味深い関数は_nsh_id_by_ccです。競合他社のSDKを特定する役割を担っているようです。関連するロジックを次のスクリーンショットに示します。

+[_CXX_CXX_OperationPKTask _cxx_cm_log_warnings:to:ins:]に戻ると、ペイロードを+[MTGBase base64EncodeString:]でエンコードした後、新しいコードブロックを作成し、_dispatch_asyncを使って実行しています。
さらに呼び出しが続き、ペイロードに追加の変換が加えられた後、-[_MC_ApiManager AFRequestWithUrl:paras:success:failure:]にたどり着きます。このメソッドは、MTGSettingのcollectDomainUrl(デフォルトではhttps://n.systemlog.me/log)にPOSTリクエストを送信します。
非公開URLが漏えいする様子を示す動画。

SKStoreProductViewControllerのフック
SKStoreProductViewControllerは、ユーザーがApp Storeからメディアを購入できるページを表示するビューコントローラーです。
loadProductWithParameters:completionBlock:メソッドは、新しい商品画面を読み込んで表示します。
フックの実装に関する技術的な詳細には踏み込まず、デモアプリケーションに次のコードスニペットを追加しました。
その結果、https://n.systemlog.me/logへのPOSTリクエストが確認され、「clever」フィールドには次のペイロードが含まれていました。
ご覧のとおり、リクエストに商品IDが含まれています。これで証明できました。
NSURLProtocolのフック
NSURLProtocolクラスを使うと、開発者はAppleのURL読み込みシステムの動作を再定義できます。Mintegral SDKは、悪意のあるNSURLProtocolの実装を登録します。この実装はリモートから設定でき、アプリケーションが送信するあらゆるリクエストを傍受し、URLやHTTPヘッダー(Authorizationヘッダーを含む)を追跡できます。
アプリケーション開発者にとって、APIトークン、Cookie、Basic認証ヘッダーがMintegralによって収集される可能性があるということです。
SDKが悪意のあるコードのこの部分を有効化する仕組みを理解するには、___cxxwebk_init_vwをもう一度確認する必要があります。

上のスクリーンショットが示すように、フックを有効にするにはcudフラグを有効にし、cudl配列を空でない状態にする必要があります。
次のスクリーンショットは、上記のメソッドから呼び出される___cxxwebkterisiuuxx関数の一部を示しています。

___cxxwebkterisiuuxx関数内のコードは、次の処理を実行します。
NSURLProtocolを継承するクラスを作成します(objc_registerClassPair、objc_allocateClassPair)。実質的にインターセプターとなる
canInitWithRequest:の実装を追加します(class_addMethod)。+[NSURLProtocol registerClass:]を呼び出して、URL読み込みシステムにクラスを登録します。
調査では、悪意のあるコードが収集するデータを確認するため、次のコードスニペットを追加しました。
その結果、https://n.systemlog.me/logへのPOSTリクエストが確認され、「clever」フィールドには次のペイロードが含まれていました。
リクエストにはURLとAuthorizationヘッダーが含まれています。リクエスト本文は含まれていませんが、ヘッダーにも機密データが含まれることは少なくありません。個人を特定できる情報が含まれる可能性さえあります。たとえば、APIでJWTトークンを使っている場合、メールアドレスやユーザー名がトークン内に格納されていることがあります。
まとめ
調査を通じて、Mintegralの開発者がSDKの悪意ある挙動を隠すために使っている、興味深い手法を数多く確認しました。特定の地域における特定のアプリケーションでのみフックを有効にしていたため、悪意のあるコードは1年以上にわたって発見されずに存在し続けていたと考えられます。
時系列を見ると、悪意のあるSDKの初版(5.5.1)は2019年7月17日に公開されました。その後のすべてのバージョンにも、同じ悪意のある機能が含まれていたことがわかりました。
このSDKの悪意ある活動は、多くの人気アプリケーションに影響を及ぼしました。今回の調査が状況を明らかにすることで、今後、広告ネットワークに対する監視が強化され、プライバシー保護が向上することを期待しています。
iOSにおけるリモートコード実行(RCE)[2020年10月]
要約
SDK内のさまざまな箇所でJavaScriptとの通信に使われているMTGBaseBridgeWebViewクラスがバックドアとして機能し、ネイティブアプリケーションのコードから任意の関数を呼び出せることを発見しました。

上の図は、リモートコード実行の動作を簡略化して示したものです。
差分分析
最初の一般公開による開示の後、MintegralはSDKのオープンソース版をリリースしたと発表しました。
そこで、新しいオープンソース版と、以前CocoaPods経由で配布されていたバイナリ版を比較しました。旧バージョンのソースコードはありませんでしたが、クラス名を比較することはできました。そのため、バイナリから.oファイルを抽出し、シンボルをオープンソース版の.hファイルと比較しました。
予想どおり、以前発見された悪意のある_CXX_CXX_OperationPKTaskコンポーネントは削除されていましたが、差分から別のものが見つかりました。次のクラスが目に留まりました。
MTGCommandDispatcher
MTGComponentCommands
MTGRemoteCommand
MTGRemoteCommandParameterModel
MTGRemoteCommandParser
MTGInvocationBoxing
これらのファイルの用途を理解するため、バイナリを詳しく調べることにしました。
影響を受けるバージョン
MintegralAdSDKの6.5.0.0以前の全バージョン(6.5.0.0を含む)。2020年9月10日に公開されたバージョン6.6.0.0には、本稿で説明するバックドア機能は含まれていません。
ブリッジの実装
まずMTGRemoteCommandParserクラスの使用箇所を調べたところ、使用箇所は1つだけでした。MTGBaseBridgeWebViewクラスの-(void)handleNativeObject:parameters:です。
実装を見ると、-(void)handleNativeObject:parameters:はMTGRemoteCommandParserを使ってparameters引数を解析し、MTGCommandDispatcherクラスの-(void)dispatchCommand:feedback:メソッドを呼び出しています。
一見すると-(void)handleNativeObject:parameters:は使われていないように見えますが、実際はそうではありません。JavaScriptコードから呼び出す方法を見てみましょう。
MTGBaseBridgeWebViewは、WKNavigationDelegateプロトコルの-(void)webView:decidePolicyForNavigationAction:decisionHandler:メソッドを実装しています。このメソッドは、Webビュー内でナビゲーションが発生するたびに呼び出されます。つまり、JavaScriptからlocation.href=somethingを呼び出すだけで、このメソッドを実行できます。SDKのオープンソース版では、ナビゲーションリクエストのURLを解析する正規表現が見つかりました。mv://(.+?):(.+?)/(.+?)\\?([\\s\\S]*)。

上のスクリーンショットにある-(void)callFunctionWithName:fucId:param:は、selfに対してfucNameセレクターを使って呼び出しを行っています。
したがって、MTGBaseBridgeWebViewの-(void)handleNativeObject:parameters:を呼び出すには、次のJavaScriptコードを実行します。location.href = 'mv://1:fucId/handleNativeObject?<parameters>'。
なお、執筆時点でSDKの最新バージョンとオープンソース版では、ここまで説明した内容はすべて当てはまります。ただし、最新リリースでは-(void)handleNativeObject:parameters:が削除されている点のみ例外です。
リモートメソッド呼び出し
MTGInvocationBoxingやその他のクラスの実装全体を説明することはしません。代わりに、リモートメソッドを実行する悪意のあるJavaScriptコードをどのように作成できるかを紹介します。
次の概念実証では、「シンプルノート」アプリケーションを攻撃します。このアプリケーションには、+(void)save:と+(NSString*)loadという2つのメソッドを持つNoteRepositoryクラスがあります。
Mintegralのサーバーを独自のサーバー実装に置き換えて、悪意のあるJavaScriptコードを挿入します。このアプリケーションとサーバーのソースコード全体はこちらにあります。
このアプリケーションで使用する悪意のあるJavaScriptコードは次のとおりです。
値 | デコード結果 |
|---|---|
hbxtJ7QU+TPXJ75ZH+SXhFQTYbzP | static_NoteRepository |
Y7KtHv== | load |
このコードはNoteRepositoryクラスの+(NSString*)loadメソッドを呼び出し、その結果をdemo-evil-server.com/logエンドポイントに送信します。
前のセクションで説明したものと同じ難読化手法を使っています。ただし、この概念実証には、エンコードとデコードを行うJavaScriptコードがすでに含まれています(banner.htmlを参照)。
完全なリモートコード実行(RCE)の実現
上の例では、このSDKを使うと任意のクラスの静的メソッドを呼び出せることを確認しました。このセクションでは、この機能を利用して任意のネイティブコードを実行する方法を示します。
実演では、「PWNED!」というメッセージを表示するUIAlertControllerを作成する方法を紹介します。
まず、次のObjective-Cコードを参考に見てみましょう。
呼び出しの間、UIAlertControllerのインスタンスを作成して保持する方法、共有アプリケーションインスタンスを取得する方法、そしてそのインスタンスを使ってpresentViewController:animated:completion:を呼び出す方法を解明する必要があります。
ステップ1:UIAlertControllerクラスへの参照を保存する
MTGRemoteCommandParserは、次の2種類のオブジェクト参照をサポートしています。
static:名前を指定してクラスオブジェクトへの参照を取得します。singleton:次の複数の処理を実行します。名前を指定してクラスを取得します(この例では
MTGSetting)。そのクラスの
sharedInstanceメソッドを実行します。Objective-Cでは[MTGSetting sharedInstance]に相当します。valueForKey:を使って、ドットで区切られたプロパティを取得します。この場合は[[MTGSetting sharedInstance] valueForKey:@"jsonTitles"]となります。
jsonTitlesは単なるNSMutableDictionaryのインスタンスです。エクスプロイトでは、参照を一時的に保存する場所として使います。MTGRemoteCommandParserがサポートするパラメーターの型は次のとおりです。
0:数値。1:参照。2:文字列。4:nil。
参照型(1)を使うと、メソッドの引数としてオブジェクトへの参照を渡せます。重要なのは、uniqueIdentifierがトップレベルのuniqueIdentifierとまったく同じ方法で解析されるため、singleton型にも対応している点です。
ステップ2:UIAlertControllerクラスの新しいインスタンスを割り当てる
この場合、すべての処理はsingleton_MTGSetting.jsonTitles.a.alloc.initで行われます。すでに説明したように、singleton_MTGSetting.jsonTitles.aを使うとUIAlertControllerクラスへの参照を取得できます。しかし、なぜ[[UIAlertController valueForKey:@"alloc"] valueForKey:@"init"]が機能するのかを解明する必要があります。valueForKey:のドキュメントには、次のように記載されています。
valueForKey:が返す値を検索するために使用する検索パターンについては、Accessor Search Patternsの「Key-Value Coding Programming Guide」で説明されています。
調査の結果、valueForKey:は引数を取らないメソッドであれば、名前を指定して任意のメソッドを呼び出せることがわかりました。
これでUIAlertControllerクラスの新しいインスタンスを作成し、jsonTitles辞書のプロパティbから参照できるようになります。
ステップ3:「PWNED!」メッセージを設定する
この手順は簡単です。UIAlertControllerのインスタンスでsetMessage:を呼び出し、メッセージにPWNED!を設定します。
ステップ4:UIApplicationクラスへの参照を保存する
この手順はステップ1と似ています。UIApplicationクラスへの参照をjsonTitles.xに保存します。
ステップ5:アラートを表示する
この手順は複雑に見えますが、これまでの手順で紹介したさまざまな手法を組み合わせるだけです。Objective-Cのコードでは次のようになります。
これで、リモートコード実行によってアラートを表示できることを実証しました。ペイロード全体はこちらで確認できます。各手順を1つずつ実行するため、アクションの配列を作成し、それぞれのアクションの完了後に次のアクションを実行するよう、window.WindVane.onSuccessコールバック内で実行しました。
悪意のある広告を通じてエクスプロイトを配信し、クリップボードの内容が漏えいする様子を示す動画。

JavaScriptエクスプロイトのソースコード
これまでに、Mintegral SDKがJavaScriptコードを介してネイティブのリモートコード実行を可能にすることを確認しました。ただし、そのJavaScriptコードはすべてMintegralが所有し、管理しています。しかし興味深いことに、広告主自身が作成したインタラクティブ広告を使っても、同じことを実現できます。広告はJavaScriptベースのウェブページです。
理論上、広告主はJavaScriptエクスプロイトを含む悪意のある広告を配信することで、特定のユーザーグループや特定のデバイス群を正確に狙うことができます。
結論
MintegralがSDKにネイティブメソッドをリモートで呼び出す機能を組み込んだ理由は推測するしかありませんが、MTGCommandDispatcherやMTGRemoteCommandといったクラス名から、意図的なものだったと考えられます。また、公開時点ではそのことを把握していませんでしたが、公開直後にMintegralはこのコードを削除しました。
Androidにおけるダウンロード追跡[2020年10月]
概要
この調査記事の前の2つのセクションでは、SnykのセキュリティチームがMintegral SDKの悪意ある挙動を発見し、iOSデバイスで広告詐欺、データ漏えい、リモートコード実行(RCE)につながる可能性があることを説明しました。このセクションでは、SDKのAndroid版についてさらに調査した結果を紹介します。主な発見は次のとおりです。
GoogleからのURIダウンロードを追跡。ブラウザーやアプリ経由のダウンロードに加え、通常のファイル、メールの添付ファイル、Google Docsのリンクも対象。
通常のものかどうかを問わず、すべてのAPKダウンロードを追跡。
このデータはMintegralのサーバーに送信されます。
確認された挙動
Google Docsのリンクをダウンロードすると、アプリからhttps://n.systemlog.meへの次のリクエストが送信されることを確認しました。

これは、iOS SDKがMintegralのサーバーにデータを報告するために使用していたものと同じエンドポイントです。ペイロードはエンコードされていますが、SDKバイナリに含まれるデコード処理を使うと、次の内容を取得できます。
さらに、cleverとdviという2つのエンコードされたパラメーターがあります。これらもデコードすると、興味深いことがわかりました。
Google DriveアプリからダウンロードしたGoogleスプレッドシートのURLはulフィールドに、ダウンロードしたファイル名はkwフィールドに格納され、dviにはデバイスに関するデータが格納されています。
考えられる用途
iOSの場合、クライアントのデバイスからMintegralのサーバーへ不正な重複クリックが送信され、さらにアトリビューションプロバイダー(MMP)へ送られていました。今回のケースでは、ダウンロードまたはインストールされたAPKがサーバーに報告され、サーバー側のクリック生成に利用される可能性があります。次の図にデータの流れを示します。

Alphabモジュール
前述の挙動はAlphabモジュールに含まれています。Mintegralはこのモジュールを「最適化パッケージ」と説明していました。

記事の公開後、このモジュールはMintegralのサイトから削除され、配布されるSDKにも含まれなくなったようです。SDKを逆コンパイルし、この挙動を引き起こすコードを特定しました。
AlphaCommonConstクラス
このクラスには、ハードコードされた定数定義が多数含まれています。一部の文字列は、iOS版で確認されたものと同様に、AlphabBase64Utilクラスにある独自のBase64ベースのエンコード方式で難読化されています。
デコードすると、次の文字列が得られます。
これらは、次に説明する初期化処理で使用されます。
Alphabレシーバー
AlphabReceiverクラスのinit()メソッドでは、BroadcastReceiverが、先ほどの難読化された文字列の一部を使って初期化されています。
これらをデコード済みの文字列に置き換えると、コードは次のようになります。
Java Reflection APIを使って新しいブロードキャストレシーバーを作成し、次の2種類のインテントを監視していることがわかります。
android.intent.action.PACKAGE_ADDED- デバイスへのパッケージのインストール時に発生する、システム全体に送信されるインテント。alphab_net_debug_action- ネットワークデバッグを検出するように見えるカスタムインテント。
インテントを受信すると、AlphabReceiverクラスはParseAndLoad()メソッドを構築します。
このフィールドは後で条件判定に使用されます。
if節にある他の2つのメソッドを逆コンパイルすると、現在のネットワーク接続がWi-FiプロキシまたはVPNクライアントを経由しているかどうかを確認していることがわかります。これは、アプリのデバッグや通信の傍受を防ぐためのものです。このインテントにより、SDKの開発者はこのデバッグ対策を回避できます。
Alphabオブザーバー
同様に、このContentObserverの初期化ブロックも、リフレクションと難読化された文字列の中に隠されています。
整理すると、次のようになります。
つまり、このコンテンツオブザーバーはcontent://downloads URIを監視するよう登録され、デバイスにファイルがダウンロードされるたびに起動します。
Androidのダウンロードマネージャーに対して、公開ダウンロードを照会します。
文字列をデコードすると、次のようになります。
ダウンロードURLが次のいずれかの条件を満たすと、https://n.systemlog.met/stlogへのレポートが生成されます。
apkで終わる - 手動ダウンロードが対象。com.android.vendingに属するパッケージを参照する、またはURLにgoogle.comが含まれる - 条件に一致するGoogleアプリやブラウザーのURLがすべて対象。
以下は、https://n.systemlog.met/stlogサーバーにリクエストを送信するコードスニペットです。
つまり、次のとおりです。
そしてここでは、例で取得したリクエストに含まれていたパラメーターを確認できます。
p- ダウンロード対象のパッケージ名、つまりアプリv- アプリのバージョンul- ダウンロードしたファイルのURLkw- ダウンロードしたファイル名fl- ファイルサイズ
デモアプリ

この挙動を実証するため、次のことができるデモアプリを作成しました。
1. リフレクションを使ってネットワークデバッグフラグを有効にし、デバッグ対策を回避する
2. google.comを含むURLからファイルをダウンロードする
3. apkで終わるURLからファイルをダウンロードする
HTTPプロキシで送信リクエストをキャプチャしました。ダウンロードボタンのいずれかをクリックすると、サーバーのエンドポイントへのリクエストが確認できます。

追跡の挙動を示す動画をご覧ください。

タイムライン
日付 | 調査イベント |
|---|---|
8月5日 | Snykの調査チームが、MintegralのiOS SDKによる過剰なデータ収集とクリックの乗っ取りを特定 |
8月17日 | Snykが調査結果をAppleに責任ある形で開示 |
8月24日 | SnykがSour Mintに関するiOSの調査結果を公開 |
8月25日 | MintegralがSDKに関する指摘を否定する声明を発表 |
9月3日 | IronSourceが、メディエーションプラットフォームからMintegralを削除すると発表 |
9月3日 | MintegralがiOS SDKのバージョン6.5.0.0をリリースし、悪意のある隠しコンポーネント_CXX_CXX_OperationPKTaskを削除 |
9月4日 | MoPub(Twitter)のメディエーションプラットフォームが、Mintegralの認定を取り消すと発表 |
9月4日 | MintegralがSDKをオープンソース化する計画を発表 |
9月4日 | Snykの調査チームが、SDKのAndroid版に隠されたダウンロード追跡機能を特定 |
9月9日 | SnykがAndroid SDKの調査結果をGoogleに責任ある形で開示 |
9月10日 | MintegralがiOS SDKのバージョン6.6.0.0をリリースし、バックドアコンポーネントMTGRemoteCommandParserを削除 |
9月22日 | SnykがiOS SDKのソースコード版6.6.0.0を入手し、差分解析を実施 |
9月23日 | Snykが、MintegralがAndroid SDKからGoogleのダウンロード追跡モジュールを削除したことを確認 |
9月30日 | 差分解析により、SnykがRCEを可能にするiOS SDKのバックドアを特定 |
10月2日 | Snykが新たなiOSの調査結果をAppleに責任ある形で開示 |
10月3日 | Appleが影響を受けたパブリッシャーに通知し、RCEを可能にするコードの削除を要請 |
10月15日 | SnykがiOSとAndroidの最新の調査結果を公開 |



