Quantcast
Channel: Kristen Dennesen – Security Bloggers Network
Viewing all articles
Browse latest Browse all 138

Rollout or Not: the Benefits and Risks of iOS Remote Hot Patching

$
0
0
Previously On iOS Remote Hot Patching

Apple’s detailed app review process has resulted in greater security for iOS apps made available through the App Store. However, this review process can be lengthy, which negatively impacts developers who need to quickly patch a buggy or insecure app. As a result, we have seen the development of various third-party solutions that allow developers to remotely hot patch an iOS app on a non-jailbroken device without going through Apple’s review process. While iOS remote hot patching is a very recent concept and is still in its inception, we have seen fierce demand and an emerging market for such products. However, they are not without their own security risks.

In our January blog, we discussed JSPatch, an open source hot patching solution. While JSPatch allows developers to provide better support to users by quickly fixing problematic apps, it potentially allows malicious actors to engage in attacks that evade current iOS security controls.

In this episode, we take you on a tour of Rollout.io, a commercial (though currently with limited free access) solution that attempts to address the remote patching problem with an eye towards security.

Episode 2: Rollout.io

According to their website, Rollout is an Israel-based, venture capital-backed technology startup founded in 2014. The core product is a commercialized solution to the iOS patching problem that essentially allows developers to update their app’s behavior, following an app’s initial approval and release, without going through Apple’s App Store review process.

Co-founder Erez Rusovsky stated that Rollout “created an SDK that allows you to remotely hot-patch native production applications”.  Rollout’s mission statement further states that:

Rollout.io’s mission is to bridge the gap between developers and their live apps. When a live app needs updating, app developers usually wait days and even weeks to get the new version out to their users. Rollout solves this problem by giving developers code-level access to their live apps.

Rollout is aware of the concerns within the community that patching apps outside of the App Store could be a violation of Apple’s review guidelines and practices. Rollout notes both on their FAQ site and in a longer blog post that their process is in compliance.

Technical Wonderland

JSPatch, which we discussed in our previous blog, provides a relatively simple patching framework consisting of three Objective-C files to be imported to an iOS app to activate the remote hot patching capability. As a commercial offering, Rollout offers a software development kit (SDK) and infrastructure that supports patching for scale and efficiency. Rollout provides a simple overview of their process, but also gives us an insider look into the tech stack and the “under the hood” mechanics of their Rollout SDK through their technical blogs. For our analysis, we focus only on the dissection of the Rollout SDK.

In a nutshell, Rollout SDK is built on the following three technologies:

●    dSYM file
●    Method Swizzling
●    JavaScriptCore framework

iOS Debug Symbol File

According to Rollout, the following steps are taken for an app to hook up with Rollout:
The developer chooses to use Rollout SDK and imports the SDK into their app.
The Rollout SDK parses the app code and generates the dSYM file (debug symbol file), which is uploaded to Rollout’s back end.
The dSYM file is rendered in the developer portal and available to the app developer for use in reviewing and patching an app.

The end result is rendered by Rollout’s developer portal and presented to the developers, allowing them to select and patch a function. Through the Rollout portal, the developer has easy access to all the defined classes (e.g. ViewController) and selectors (e.g., imagePickerController:didFinishPickingMediaWithInfo:) of the analyzed app, as shown in Figure 1.


 
Figure 1: Rollout developer portal allowing the developer easy access to all defined classes and methods in the app

The most common way to patch a bug in an existing function is to replace the faulty implementation of the function with a new, fixed one. But there are situations where a fix is needed in multiple places across the application. In this case, the best practice is to create a new function that encapsulates the shared routine. In Rollout, one can easily achieve this through the interface shown in Figure 2.



Figure 2: Rollout developer portal allowing the developer to add a new method into a class

Rollout also allows developers to resolve problematic situations such as when a method was renamed but still called from some code in the UI, which requires the developer to link the disconnect by a new wrapper method. In this case, selecting a function to be fixed (such as [ViewController imagePickerController:didFinishPickingMediaWithInfo:] shown in Figure 2) will display the JavaScript patch editing interface shown in Figure 3.

 
Figure 3: Rollout develop portal providing a JavaScript editing interface for patch development

Method Swizzling

Method swizzling is known to iOS developers as “black magic.” In short, method swizzling is an Objective-C runtime technique that allows one implementation of a method to replace an existing implementation of another method (of a class or instance) at runtime.

The term “implementation” refers to the actual function pointer to the code (implementation) of the method. The Objective-C runtime maintains a struct called "objc_method" for each method of a class. This struct has the method name, the argument, the return types of the method, and the "implementation" of the method, which is represented by a pointer IMP pointing to a C function. Therefore, swizzling basically involves exchanging the value of the "implementation" field between the objc_method data of two different methods. Figure 4 and Figure 5 depict a visualization of the process:
 
Figure 4: The original selector and its implementation mapping in class FortitudeViewController before swizzling
   
Figure 5: The selector and implementation mapping in class FortitudeViewController after method swizzling

In Figure 4, which shows the state before swizzling, each selector in Class FortitudeViewController contains a corresponding pointer IMP that points to its real implementation, which is a C function behind the scene. For instance, selector1 is an objc_method struct that contains pointer IMP1.

The “magic” lies in the availability of three essential C functions in the Objective-C runtime:

●    method_exchangeImplementations
●    class_replaceMethod
●    method_setImplementation

The most common and intuitive way to perform a method swizzling is similar to what is shown in Figure 6.
 

Figure 6: Example code showing method swizzling

This code will turn the internal runtime relation of the relevant methods into the conceptual structure shown in Figure 5. This effectively allows one to replace an existing implementation of a function with a new one, thus leading to a new and uncharted behavior of an app at runtime.

There have been many discussions about the pitfalls and dangers of utilizing this “black magic.” A primary focus is to avoid the unintended side effects of using the C function method_exchangeImplementations (shown above) by instead using class_replaceMethod and method_setImplementation. Further details are beyond the scope of this blog post.

Apple does not seem to have provided any official documentation for the concept of method swizzling, despite documenting the associated runtime APIs. However, it is a general consensus within the developer community that method swizzling is permitted. It should be noted that to date, Apple does not appear to have rejected an app during its review process due to the use of method swizzling.

JavaScriptCore.framework

The JavaScriptCore framework was introduced into iOS at version 7. It allows one to evaluate JavaScript programs from within a C-based program. It also lets users insert custom objects to the JavaScript environment. On iOS, it is similar to an Objective-C wrapper of WebKit’s JavaScript engine, thus extending the capability and power of scripting beyond a web client to the whole app.

The following four classes form the cornerstone of the framework:  

●    JSVirtualMachine represents the virtual JavaScript runtime environment that allows JavaScript to run and to be executed. To initiate a virtual machine instance in Objective-C, one does the following:
JSVirtualMachine *vm = [[JSVirtualMachine alloc] init];

●    JSContext talks to the above runtime, provides access to global objects that reside in the context, and performs the execution of JavaScript code. For example, in Objective-C, one can initiate a JSContext instance and declare a variable in the manner shown here:
JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm];
context[@”name”] = @”Jean-Luc”;
context[@”organization”] = @”Enterprise”;

●    JSValue is the class that represents arbitrary data in JavaScript. For instance, we have:
JSValue *name = context[@”name”];
JSValue *organization = context[@“organization”];
NSLog(@”Captain Name: %@ \nOrganization: %@”, name, organization);

●    JSExport is a protocol that allows one to expose parts of Objective-C classes and methods to JavaScript. The wrapper created through this protocol functions as a passthrough between the Objective-C runtime and the JavaScript runtime. This one object thus facilitates the sharing between the two execution contexts allowing code in one environment to change the states of the other.

Rollout Patch Capability

Rollout exposes to developers only a limited set of JavaScript APIs that can be permitted in the Objective-C runtime environment. Its API documentation shows the following essentials:

●    R: the Rollout namespace object that allows integration with the Rollout SDK, the containing function, and the application’s runtime. Within which, it offers the functionality of the Foundation C function NSClassFromString, as shown in Figure 7.

Figure 7: Portion of Rollout 'R' namespace


●    ObjcBox: encapsulates Objective-C NSObject instances. It allows a transformation from an Objective-C instance to a JavaScript value. There are two important functions, as shown in Figure 8:
 
Figure 8: Portion of Rollout ObjcBox namespace

The APIs provided by Rollout and the legitimate use cases they describe for their hot patching infrastructure are simple, limited, and benign. However, as with many well-intentioned solutions, the possibilities of misuse or abuse remain when malicious individuals think outside the box.

The Usual Suspects

In our blog on JSPatch, we outlined several attack capabilities that could be carried out against that technology, such as loading arbitrary public or private frameworks into an app. The types of capabilities we described for JSPatch also work against Rollout, though we do not provide specific examples here. Instead, we highlight a few additional scenarios specific to Rollout to avoid duplication.

Example 1: Load arbitrary private frameworks and utilize unauthorized private APIs

●    Targeted private framework: /System/Library/PrivateFrameworks/CoreRecents.framework
●    Targeted private API: [[CRRecentContactLibrary defaultInstance] maxDateEventsPerRecentContact]

Figure 9 and Figure 10 show sample exploitation code and the associated console output loading the private framework CoreRecents.framework.
 
Figure 9: Sample exploitation code for loading a private framework

Console Output:


Figure 10: Sample console output showing successful load of the framework

Both this example and the following ones make use of Apple iOS private APIs. The pros and cons of the use of these private APIs by third party apps has been at the center of much debate. In general, common sense suggests that the use of Apple’s private APIs by third party apps is risky due to security risks as well as stability concerns (for example, unexpected behavior if Apple changes the internals of the private APIs). Despite Apple’s efforts to prohibit the practice of utilizing non-public APIs, it has proven difficult to identify their use when developers use obfuscation and other even more clever and sophisticated maneuvers.

That said, when an app developer with malicious intent makes use of these private APIs, the use of the APIs will leave traces within the app code itself. This means the malicious code within the app is subject to potential discovery by Apple or a third party. However, with Rollout’s dynamic hot patching process, the intent – that is, the malicious code – can be separated from the app binary itself in the form of a hot patch. Rollout, as a remote hot patching solution, is not the only means one can resort to separating private API calls from the app binary, but it lowers the bar for malware developers to achieve so.

Example 2: Load arbitrary public frameworks and utilize unauthorized private APIs

●    Targeted public framework: /System/Library/Frameworks/AVFoundation.framework
●    Targeted private API: [AVCaptureDevice devices]

Figure 11 and Figure 12 show sample code used to successfully access the iPhone’s cameras and microphone.    

Figure 11: Example exploit code loading public framework to access the private AVCaptureDevice API

Console outputs three devices: Back Camera; Front Camera; iPhone Microphone.


Figure 12: Console output showing access to the iPhone cameras and microphone

Example 3: Test device for the presence of a targeted app

The ability for one app to check for the presence of another app raises both privacy and security concerns (for example, checking for the presence of an app in order to exploit it). The primary method for obtaining a list of installed apps is through the private API [LSApplicationWorkspace allInstalledApplications]. As we have seen, use of these private APIs is prohibited by Apple’s Developer Program License Agreement.

Some app developers have sought other means to determine installed apps without using Apple’s private APIs. For example, iHasApp used the public API [UIApplication canOpenURL:] to identify installed apps based on their supported URL schemes. Unfortunately, the extensive usage of the API and associated detection method in a large volume of apps resulted in iHasApp and its derived framework being shut down by Apple, and the API being flagged during the app store vetting process.

However, Rollout eliminates this constraint because the API can be called via a hot patch outside of the app itself.

Figure 13 and Figure 14 show sample code using canOpenURL: to detect installed apps.
Figure 13: Sample exploit code calling canOpenUrl
 
Figure 14: Console output showing app detection

Example 4: Make phone calls to premium numbers without consent

By utilizing the public API [UIApplication openURL:], one can launch the native mobile phone app and make a phone call to an arbitrary premium number. This activity would be immediately visible to the user when the phone app interface was unexpectedly displayed. However, use of the exploit could be fine-tuned by applying environmental checks (for example, only initiate calls when the user is asleep) and maintaining a status of long running background process through background modes.  

Figure 15 and Figure 16 show sample code for dialing a premium number and the successful connection.    

Figure 15: Sample exploit code used to dial a premium phone number

 
Figure 16: Console output showing successful call

Example 5: Take screenshot without informing the user

Figure 17, Figure 18, and Figure 19 show that through the patch, one can take screenshots of the current foreground screen by utilizing non-public API [UIImage createSnapshotWithRect:] without the user’s knowledge. The screenshots are saved in the sandbox of the application, which can be further exflitrated outside of the device.


Figure 17: Sample exploit code showing the use of private API [UIImage createSnapshotWithRect:] to capture the screen



 
Figure 18: Console output showing that the captured screenshot has been saved to the sandbox
 
Figure 19: App sandbox content showing the captured images

All of the above tests were performed on a device that runs iOS 8.4. Apple has released a number of iOS versions through the years to fix and close security holes reported by both industry practitioners and academic researchers. Most of the private or public APIs that could have been abused are protected through various access controls  (e.g., entitlements to the Address Book) in newer versions of iOS. However, the reality is that there are a significant number of users who are not keeping their devices’ OS version up-to-date. The ramifications are that “old” attacks through private APIs, which are ineffective against iOS 8.4 or iOS 9, would still be effective against some devices.

Threat Scenario

In our earlier blog on JSPatch, we highlighted three general attack scenarios using an iOS remote hot-patching vector. Of these, two are still present on Rollout in a similar fashion:

1.    Precondition: 1) Embedded 3rd party ad SDK is malicious.
a.    Consequences: ad SDK has the right to write to the database, which allows it to change the behavior of the app.
2.    Precondition: 1) App developer is malicious.
a.    Consequences: app developers can perform stealthy persistent but temporary actions against the user including by utilizing Private APIs.

It has been pointed out that an app developer with malicious intent will strive to find a way to distribute their malicious app regardless of the particular framework used. That is, no existing distribution method can fully guard against malicious intent. While we agree with this statement, we also believe it is important to understand how different distribution methods may help or hinder a malicious developer in deploying their malicious code. A developer wishing to distribute a malicious app through the App Store would need to slip the malicious code past the review process. The third-party hot patching frameworks developed to date do not include any review process, so it helps to understand how malicious patches could be distributed and where (or whether) they could be detected.

A risk of hot patching frameworks is that because patches can be deployed ‘on the fly’, a developer could distribute a legitimate app, temporarily deploy a patch to carry out specific malicious activity, and then deploy another patch to revert the app back to its normal, non-malicious behavior. Because this activity can occur automatically in the background, users are highly unlikely to notice the change, and replacement of the malicious patch with a “clean” one could leave little evidence that anything suspicious had occurred.

To put the threat scenario in perspective, we provide a visualization of such an attack to reinforce the concept and facilitate understanding.  

Fictional Malicious Plotting

Synopsis
Our fictional app FortitudeSeries was a new release of an iOS app that allows one to add filters to selected photos from the device photo gallery and save the edited photos back to the gallery. In order to offer the user a better experience with quality performance and stable software, we decided to use the Rollout.io service to maintain the ability to remotely hot-patch bugs and security issues should they be discovered in the future.

After testing several patches, we identified several actions we could take outside of what the app was originally designed for. We first tried saving an original copy of all the filtered photos in the sandbox, and it was a quick success. We then became curious about the photos the user does not select for filtering, so we issued a new patch to capture a screenshot of the user’s photo gallery. This too was simple to achieve.


Production
Our fictional attack is demonstrated through three stages to show the following scenarios:

●    Stage 1: Rollout patching is disabled in the backend. FortitudeSeries only exhibits its legitimate behavior. A user selects a photo from the photo gallery by pressing the button “Select A Photo”. Once the photo is selected, the console outputs “Filtering the selected image” and the photo gallery view is dismissed. The app’s Documents directory does not hold any data, therefore, it remains empty. Figure 20 shows the source code of the main view controller of FortitudeSeries.
 

Figure 20: Objective-C code for the core implementation of fictional app FortitudeSeries

●    Stage 2: Rollout patch is enabled with the code shown in Figure 21. The user restarts the app and performs the same sequence of actions. The app’s Documents directory keeps a record of the selected photos and labels them with the timestamp of the photo that was selected.
  

Figure 21: Rollout patch code for saving a copy of the user selected photo in the sandbox

●    Stage 3: Rollout patch is enabled with different code, as shown in Figure 22. The user restarts the app and performs the same sequence of actions described above. The app takes a screenshot of the photo gallery and saves a copy to the sandbox Documents directory using the same naming scheme presented above.
 

Figure 22: Rollout patch code for capturing a screenshot of the photo gallery in stealth

Once the data is in the sandbox of the app, the app may deal with it however it wants. A conceivable approach is to exfiltrate it to a developer-controlled server. It should not be surprising that this can be done via a Rollout patch script that executes at runtime without Apple’s knowledge.  

The operation of the demo is therefore done in the following three stages:

●    Stage 1: Develop FortitudeSeries in Objective C and Rollout; deploy it to a user device to allow the user filter selected photos; check the Rollout patch; perform the expected actions on the installed app; check the console log; check the sandbox Documents directory;
●    Stage 2: Enable Rollout patch with script for scenario I; restart the app; perform the expected actions on the installed app; check the console log; check the sandbox Documents directory;
●    Stage 3: Comment out the patch script for scenario I and enable script for scenario II; restart the app; perform the expected actions on the installed app; check the console log; check the sandbox Documents directory.

Primed with the above depiction, it should be easy to understand the recorded demo below even without a narrative.

Rollout Security Defense

The chances of a successful man-in-the-middle (MITM) attack through the use of poor encryption (or no encryption) of the patch script content can be reduced significantly through secure implementation of the app and any supporting hot patching framework.

To prevent patches from being tampered with, Rollout invested in the following security measures:

●    The app retrieves the patch data from Rollout.io server through HTTPS. This significantly lowers the chances of being a target of MITM attacks.
●    The patch data is signed by a Rollout.io private key and therefore can only be decrypted by a key that’s known to the iOS app.

Security Weakness

The above protection ensures that data is secure in transmission. However, once the patch data lands on the device, it is decrypted accordingly and stored in the sandbox in plaintext. Figure 23 shows the directory #APP_SANDBOX/Library/Caches/#APP_ID containing a specific database Cache.db that contains data resulting from the hot patch network communications.
 

Figure 23: File structure view of the directory encompasses the database of patch data

All patches that have been pushed to production and received by the client app are stored as a record in the table cfurl_cach_receiver_data as shown in Figure 24.
 

Figure 24: DB table cfurl_cach_receiver_data containing all records of production patches

Each patch is stored in the receiver_data column in JSON format. The JavaScript code is mapped to the key “configuration” in based64 format. For example, the highlighted data blob in Figure 24 contains the based64 encoded content shown in Table 1:


Table 1: base64 content from patch database

Its corresponding ASCII format is the data is shown in Figure 25.

Figure 25: Decoded base64 content

Given Rollout’s existing security measures such as HTTPS and asymmetric encryption, as well as iOS’s sandbox, this weakness is a minor issue. Since there are other attack vectors that can be more easily exploited (for example those described in our threat scenario I and II), a third party library may be less motivated to tamper the patch to their advantage. Should circumstances change and one chooses to do, this weakness is really to be leveraged.

Field Survey

Rollout’s web site states that its product is “trusted by thousands of mobile app developers”. As Rollout provides a solution for a problem that is unique to iOS developers, we can speculate that all its customers are iOS app developers at this point. Though a few have been highlighted on their main page, the exact number of App Store-approved apps that use Rollout SDK is unknown. We performed a scan using FireEye’s infrastructure in late 2015 and found 130 apps that have been or still are in the App Store using Rollout as a remote hot patching solution. This number has since grown to 245 as of Jan. 19, 2016.  

As opposed to apps that adopted JSPatch as the remote hot patching solution, which are predominantly Chinese apps for Chinese speaking users, apps that use Rollout are mostly marketed towards English speaking users. Many offer localization for a variety of languages. There are no distinct features among these apps; they span a variety of categories including education, social networking, magazines and newspapers, lifestyle, photo and video, games and more. Most of the apps have very low user adoption in the App Store at this point. The most popular app seems to have accumulated a download record of 62,869 times, while the vast majority have no popularity rating on file.  

At the time of this writing, we have not confirmed any malicious activity related to any app that uses the Rollout SDK. We are simply reporting on potential vulnerabilities and avenues for misconduct that could potentially be exploited when using this tool. 

Epilogue

Conclusions

iOS remote hot-patching through a non-Objective-C language to effectively evade the Apple review process – a process that has so far largely led to a safe and clean app ecosystem – is now a reality. Our analysis has placed JSPatch and Rollout under the spotlight as examples of two hot patching frameworks with very different characteristics:

  • JSPatch is developed by a Chinese developer; Rollout.io is provided by an Israel-based company.
  • JSPatch is open sourced; Rollout.io is a commercial product.
  • JSPatch is adopted mostly by Chinese app developers; Rollout.io is marketed to English speaking or international developers.
  • JSPatch and Rollout.io offer different syntax and capabilities for JavaScript code.
  • The infrastructures are far from the same.

Despite differences in their implementation, both are similar in that they potentially allow a developer to turn an innocuous looking app into something malicious – all while circumventing Apple’s App Store vetting process. What’s more, the underlying “biology” is the same for the two solutions: the combination of JavaScriptCore framework and method swizzling.

When conducting our research, we contacted Rollout regarding the issues described in this post. We gratefully acknowledge Rollout’s responsiveness and assistance in addressing them. As a result, Rollout has indicated that they will prevent developers from accessing iOS private APIs and private frameworks in their future releases of the product so that all patch code is subject to the same types of checks as those in the Apple review process. With Rollout’s upcoming release, the attack examples shown here would be thwarted.

Additional Food for Thought

The current limitations of the App Store review process and the desire from developers for a faster solution means that hot patching, as a process, is unlikely to go away any time soon. We hope that by describing these underlying risks, patch framework developers will institute additional security controls to ensure that they are providing developers with convenience and productivity in iOS app development all while maintaining a clean and safe ecosystem.

In this ecosystem, iOS users are the least able to protect themselves and, consequently, the most vulnerable. When it comes to user security, it is difficult to decide which single stakeholder should assume the responsibility of maintaining and sustaining a safe and clean iOS mobile environment. While Apple has come a long way in keeping its mobile users safe from malware, the task has become increasingly difficult. It is not outrageous to expect third party library or framework providers to offer extra security to ensure their services are not being abused.

While we do not have a definite solution for this complicated issue, we believe a system that functions as follows could potentially increase iOS user security: 1) App developers providing to Apple a list of the third party libraries and frameworks that they use, 2) The underlying technologies of third party libraries and frameworks being provided to Apple, and 3) Third party library or framework providers improving security to ensure their services are used as intended.

 


Viewing all articles
Browse latest Browse all 138

Trending Articles