App Code Injection

Thomas Jansen on Feb 1, 2018 — 5 min read

In this third and last part of my blog post series (about the vulnerabilities I discovered in the Top-200 iOS Apps back in September of last year) I will talk about something even better than simply eavesdropping on insecure communication; manipulating the traffic. More specifically, today I will focus on injecting malicious code to trick the victim into giving away sensitive information.

As a reminder, the first blog post did talk about the dangers of plain-text app communication and described a simple setup that allows eavesdropping on such traffic. The second post then showed that even some apps that use a communication channel secured by TLS might be vulnerable to eavesdropping, due to the lack of x.509 certificate validation.

So far, we only talked about the ability to capture sensitive data passively when it was sent over a vulnerable channel by the app. Given the varying definitions of what sensitive data is —“bank account credentials” vs. “the last website you visited”— an argument could be made that the majority of vulnerable apps do not send data worthy of eavesdropping. But if the app does not send valuable data by itself, an attacker might use “code injection” to phish for such.

Hybrid Apps and WebViews

Many modern apps on iOS and Android use a hybrid approach for their user interface. Instead of using native code to create all buttons, edit fields, checkboxes, and so on, they basically present an embedded web-page to the user — a so-called WebView.

MarketWatch, Nationwide, and Otto replace some or all of their UI with web page snippets

MarketWatch, Nationwide, and Otto replace some or all of their UI with web page snippets

Discussing the various pros and cons of this approach is beyond the scope of this article, but there is a very real security impact if the content of the WebView is downloaded using a vulnerable channel. An attacker could intercept the content request and return a hand-crafted response that alters the user interface of the app. The victim has no way of noticing, especially as there usually is no URL address bar or any indication that the user-interface description has been fetched remotely (through an insecure channel even).

Given the flexibility of HTML, CSS, and JavaScript there are no limitations of the UI presented. An attacker is able to inject code to show a fake FacebookConnect screen, an age verification dialog based on your credit card information, or an AppleID alert. In all cases, the entered information would be sent to a server under the attacker’s control, unbeknownst by the user.

Attack: Rayman Adventures

During my investigation of the Top-200 iOS Apps I discovered more than 50 apps that would fetch WebView content from insecure sources. A dominant pattern turned out to be everything imprint or privacy policy related — in many cases the same content as on the app’s regular website was reused. However, some apps used WebViews to display real-time information and news, such as Ubisoft’s Rayman Adventures.

The game features a button —decorated with a red exclamation point— on its main screen. Tapping it brings up the Rayman Channel, a full-screen WebView running insecure content:

Tapping ‘Rayman Channel’ on the main screen will bring up a full-screen WebView

Tapping ‘Rayman Channel’ on the main screen will bring up a full-screen WebView

Using the same setup as in the previous two blog posts —bettercap to reroute network traffic through our server and mitmproxy to observe insecure content— the following script allows an attacker to inject malicious content (in the file attack.html) into the app:

from mitmproxy import http

def request(flow: http.HTTPFlow) -> None:
    if flow.request.pretty_url == "http://raymangame.com/raymanchannel/":
        flow.response = http.HTTPResponse.make(
            200,
            open("attack.html", "rb").read(),
            { "Content-Type": "text/html" }
        )

Passing the script into mitmproxy, using the --scripts option, and running Rayman Adventures on the iOS device again now looks like this1:

Tapping ‘Rayman Channel’ now brings up the attacker’s phishing dialog

Tapping ‘Rayman Channel’ now brings up the attacker’s phishing dialog

To conclude: Using the same setup as before —without special hardware, without physical access to neither the victim’s device nor the network infrastructure, and without any visual indication about an ongoing attack on the victim’s device— an attacker was able to inject code into the app and control its user interface to phish sensitive information.


Update (07/13/2018): A major new version of mitmproxy has been released a while back, so I went back and updated the command line and scripts to the new syntax. I’ve also updated the screen capture and vulnerability disclosure section.


Bonus: Vulnerability Disclosure and History

Rayman Adventures

The vulnerability is still present at the time of this writing.

DateDescription
10/11/2017Reached out via the support forum to learn about the disclosure process
10/12/2017Sent detailed report via the support forum
10/17/2017The development team acknowledged the vulnerability and is working on a fix
10/24/2017Requested status update
12/15/2017Still not fixed, requested status update
07/13/2018Still not fixed, 9 months after the initial report

ImmobilienScout24

The described vulnerability has been fixed as of December 15, 2017.

DateDescription
10/11/2017Reached out via support email to learn about the disclosure process
10/17/2017Send follow-up email
10/18/2017Sent detailed report to service@immobilienscout24.de
10/19/2017Received an email acknowledging the vulnerability
11/03/2017Requested status update
12/15/2017Verified that the vulnerability no longer exists

Microsoft Outlook

The described vulnerability has been fixed as of December 15, 2017.

DateDescription
10/11/2017Sent detailed report to service@microsoft.com
10/19/2017Received an email acknowledging the vulnerability
10/30/2017Requested status update
10/30/2017Got listed on the acknowledgment page
12/15/2017Verified that the vulnerability no longer exists


  1. Imagine how real this would look if my web design skills wouldn’t be so ridiculously bad!