SourMint: Malicious code, ad fraud, and data leak in iOS
UPDATE: In addition to the findings we originally disclosed, we’ve identified additional concerns in both the iOS and Android versions of the SDK. Read more about the updated findings and the reactions from Apple, Google, and the community here.
The Snyk research team has uncovered malicious behavior in a popular Advertising SDK used by over 1,200 apps in the AppStore which represent over 300 Million downloads per month, based on industry expert estimates.
The malicious code was uncovered in the iOS versions of the SDK from the Chinese mobile ad platform provider, Mintegral dating back to July 2019. The malicious code can spy on user activity by logging URL-based requests made through the app. This activity is logged to a third-party server and could potentially include personally identifiable information (PII) and other sensitive information. Furthermore, the SDK fraudulently reports user clicks on ads, stealing potential revenue from competing ad networks and, in some cases, the developer/publisher of the application.
SourMint malicious code high-level description
The Mintegral SDK presents itself as a tool to help app developers and advertisers build monetized ad-based marketing. However, through our research and in collaboration with experts from the mobile advertising industry, the Snyk team has discovered that some malicious code within the SDK works to steal potential revenue from other ad networks the application may be using, and spy on any URL-based request made from within the application.
Developers can sign up as publishers and download the SDK from the Mintegral site. Once loaded, the SDK injects code into standard iOS functions within the application that execute when the application opens a URL, including app store links, from within the app. This gives the SDK access to a significant amount of data and even potentially private user information. The SDK also specifically examines these open URL events to determine if a competitor’s ad network SDK was the source of the activity.
It’s interesting to note the Mintegral SDK also contains a number of anti-debug protections that appear to be designed to keep researchers from discovering the true behavior behind the application. In the code, there is a particular routine that attempts to determine if the phone was rooted and if any type of debugger or proxy tools are in use. If it finds evidence that it is being watched, the SDK modifies its behavior in an apparent attempt to mask its malicious behaviors. This may also help the SDK pass through Apple’s app review process without being detected.
The primary goal of the malicious code that Snyk uncovered in this SDK appears to be hijacking user clicks on ads within the app. In mobile applications, advertisements are often presented by ad networks that the developer integrates into their code.
Advertisers pay the ad networks to display their ads and are charged on the performance of the ad (i.e., the ability to get users to click on the ad to visit the advertiser’s site or install their application). The app developers receive a portion of the profits the ad network makes from the advertisers.
It is common for app publishers to include SDKs from multiple ad networks in their applications through the use of ad mediators. These mediators optimize revenue for the ad publisher by including multiple ad networks and then selecting which ad network to use for each ad request, based on ad network performance metrics.
However, the Mintegral SDK is able to intercept all of the ad clicks (and other URL clicks as well) within the application. It uses this information to forge click notifications to the attribution provider. The forged notifications make it appear that the ad click came through their network even though it may have been a competing ad network that served the ad.
Mintegral is able to steal ad revenue from competing ad networks in two primary ways. First, Mintegral steals advertiser revenue that should have gone to the other ad networks. This happens simply by claiming attribution for clicks that did not occur on a Mintegral presented ad. This seems to be the main goal of this malicious functionality.
A secondary impact, however, would be that the developer or mediator SDK may notice that Mintegral is performing better than the other ad networks, causing bias toward selecting Mintegral over competing ad networks.
There is also potential for the application developer or publisher to lose revenue even when Mintegral isn’t being used to serve ads. In our investigation, we discovered that once the Mintegral SDK is integrated into an application, it intercepts the clicks even if Mintegral isn’t enabled to serve ads. In this case, ad revenue that should have come back to the developer or publisher via a competing ad network will never be paid to the developer.
Privacy exposures from data leak
While ad fraud appears to be the primary goal of the malicious code, it may not be its most severe implication. In our research, Snyk further learned that the Mintegral SDK captures details of every URL-based request that is made from within the compromised application.
The information on these requests as well as other device and application data is then sent to a remote logging server. The SDK accesses a great deal of information including:
- the URL that was requested, which could potentially include identifiers or other sensitive information
- headers of the request that was made which could include authentication tokens and other sensitive information
- where in the application’s code the request originated which could help identify user patterns
- the device’s Identifier for Advertisers (IDFA) which is a unique random number used to identify the device and the unique hardware identifier of the device, the IMEI.
The requests captured by the SDK include web URLs, custom URL scheme (protocol handler) requests, and in-app calls to the app store.
Beyond ad click attribution, it is unclear if and how this data is being used once it is uploaded to the logging server. At a minimum, the data captured would enable a deep analysis of the user journey within the application. More concerning is that, depending on the nature of the compromised application, the URL and other data being collected could potentially expose private information. Ultimately, it could be possible for Mintegral to monetize such data by selling it to other parties for purposes of data analytics.
This functionality of logging large amounts of user sensitive data is particularly notable given the growing concerns over the way mobile applications, in general, are collecting data. Most recently, the TikTok application has been the subject of increased scrutiny for their data collection practices.
The attempts by Mintegral to conceal the nature of the data being captured, both through anti-tampering controls and a custom proprietary encoding technique, are reminiscent of similar functionality reported by researchers that analyzed the Tik Tok app.
In the case of SourMint, the scope of data being collected is greater than would be necessary for legitimate click attribution. The app also uses questionable coding methods to achieve this level of data access.
Technical exploit details and remediation
Just how does this malicious code attack work? Well, let’s take a look at the details we uncovered in our research.
Developers are able to download the SDK from Mintegral’s site and incorporate it into their application. When the SDK is initialized, it makes a number of requests to the Mintegral server. One of these requests receives a JSON response that contains a number of parameters that are directly used by the malicious code within the application. These include:
- a flag to turn on or off the anti-tampering/debugging detection
- a flag to enable the hooks that are used to capture and log URL clicks
- a URL (encoded) to which user click activity will be logged
The retrieved settings JSON also contains a numeric value indicating the delay before the next setting update. This indicates that settings within the SDK can be updated remotely.
As noted previously, the SDK performs some basic anti-tampering detection steps. It looks for the following conditions:
- the application is running in a simulator
- there is a debugger attached to the application process
- the phone is rooted (by checking for various files including the Cydia app)
- proxying is enabled
If the SDK detects that any of the conditions above are met, it sets a flag that is used throughout other functions of the SDK and modifies the behavior of the SDK. The modified behavior appears to disable the malicious activity of rewriting URLs and logging user data. Therefore it would seem this is an attempt to avoid detection of the malicious activity of the SDK.
At runtime, the SDK uses method swizzling to inject malicious code into the implementations of numerous methods and handlers. These hooks allow it to intercept any URL-based request made from within the app, even those that occurred outside of the Mintegral SDK. This is the crucial step that allows the SDK to gather the necessary information about user clicks to successfully create a click notification to the attribution provider. The methods that the SDK swizzles with its own code include:
UIAplication OpenURL:options: completionHandler(after performing a check to confirm the app is running on iOS 10.x or higher)
When one of the methods above is called, the code injected by the SDK does a number of things. First, the SDK checks if the anti-tampering flag is set and if so, all subsequent Mintegral code is skipped. It then checks to see whether the request originated from a marketing ad served by Mintegral or if it came from a Mintegral competitor. If the request originated from a Mintegral ad, the normal method handler is invoked without further action.
If the request originated from within a non-Mintegral method, the code gathers information about the event including the URL, the request headers, the class where the click happened, the method in which the click occurred, and additional backtrace data. This data about the request along with other phone data is sent in an encoded format to the Mintegral logging server specified in the settings file. The data logged includes:
- OS Version
- IP Address
- charging state
- Mintegral SDK Version
- network type
- package name
- request headers
- method name
- class Name
- backtrace data
Once the data is logged to Mintegral, the execution of the rest of the method continues as normal. Based on reporting provided by an attribution provider, we’re able to confirm that on the back end, Mintegral is creating click notifications for the touchpoints that occurred through other ad networks.
In order to discover this information, the Snyk Security Research Team added the SDK to a test application. To avoid the anti-tampering detection, application communications were intercepted at the wireless access point using a Man-in-the-Middle proxy (
mitm.it). Snyk used Hopper disassembler to investigate the code within the SDK and map out the functionality. We were able to identify this malicious functionality in versions of the SDK going back to 5.5.1 (current version as of this writing is 6.4.0).
Ultimately, through our own internal research as well as collaborating with key organizations and experts in the industry, we were able to confirm the full end-to-end hijacking of user ad click events.
For an even more detailed technical description of the code we discovered and the methods used, visit our research write-up.