Content Security Policy – Important Defense-in-Depth missing for many Apps

The Content Security Policy (CSP) defines restrictions for webviews to reduce the attack surface of applications for Cross Site Scripting (XSS) and other attacks. The stricter the policy is configured, the fewer possibilities remain for attackers to inject malicious functionality in case of input validation flaws. This is especially important for hybrid apps, such those build with Cordova, that use JavaScript to access granted OS functionality via a JavaScript bridge. If an attacker can inject own code to a hybrid app’s webview, he can alter the way how the app uses accessible data and sensors.

A strict CSP can prevent the execution of injected functionality by restricting the executable code fragments to resources that are less accessible to an attacker. However, strict restrictions also require alternative programming styles during app development, which sometimes are inconvenient or unknown to the developer. Additionally, some external libraries or other existing code may not work out of the box with restrictive CSP settings, increasing the pressure for using a less restrictive policy.

With Appicaptor we inspect apps for configured CSPs to evaluate the restrictions for the security of the app. A single missing sanitation of user input may render a hybrid app vulnerable for hijacking of the app’s functionality in a malicious way. As the vulnerabilities can be introduced to apps by a missing ‘S’ for the HTTPS scheme when loading external JavaScript resources or by a flawed sanitation of user input, hybrid apps should reduce these risks by applying a ready to use second line of defense using CSPs. However, 60.5% of the analyzed hybrid apps for iOS and 72.3% of the hybrid apps for Android do not define a CSP. The analyzed app set each consists of the most used 2,000 apps as ranked by the Android and iOS App Stores.

One might consider a ratio of more than 25% for hybrid apps that do use CSP as a second line of defense an already good starting point. However, analyzing the actual CSPs of these apps shows that many policies are weak. In iOS 39.5% (Android: 27.6%) of the hybrid apps with a CSP deactivate important protective restrictions and therefore could be rated equally to apps with no defined CSP from the perspective of an attacker. So let’s see why.

This is a typical basic example of an observed CSP:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: 'unsafe-inline'; img-src *;"> 

CSPs are constructed in a simple fashion: Each section starts with the source keyword the directive should be applied to and is terminated with a semicolon. In the example the CSP starts a directive section with the default-src keyword. Its declared restrictions are used as fallback for other, not defined directives. For example, the directive for script-src and object-src are not declared, so the configuration of 'unsafe-inline' is applied to both of them, but not to 'img-src', as it is declared in the example and therefore the fallback to 'default-src' is not applied by the browser.

The intention here is to allow loading sources only from 'self', which is the source where the HTML page with the CSP entry was loaded from, to prevent injection of external scripts for Cross Site Scripting. Only images are allowed to be loaded from any source, declared by star character in the img-src directive.

However, by declaring the keyword 'unsafe-inline', this CSP allows executing JavaScript code injected at any place in an HTML page, such as

User entered <script>doSomethingBad();</script> text 

or

<div onclick="doSomethingBad();">Click Me</div>

Allowing 'unsafe-inline' together with the data: scheme for the object-src in the example allows an attacker to inject script code to <object>, <embed>, and <applet> elements:

<object data="data:text/html,<script>doSomethingBad();</script>"></object>

or by using JavaScript inside an SVG, embed as data: URL:

<embed src="data:image/svg+xml,<svg onload='doSomethingBad();' xmlns='http://www.w3.org/2000/svg'></svg>" type="image/svg+xml" width="1" height="1" /> 

Fortunately, in most common cases the code injected via data: scheme is treated as a separate frame. It cannot interact with the JavaScript bridge of a hybrid app, which is located in the parent index.html page and the Same Origin Policy prevents the access to it. However, attackers can still use this for UI manipulation attacks by tricking users to disclose credentials or other critical data in crafted dialogs.

Besides many other possible shortcomings observed CSP are having regarding inline XSS protection, about 10% of the analyzed hybrid apps (iOS / Android) do not properly restrict the sources for loading scripts. This is caused by using the star character as a wildcard for the scheme. This way an attacker would be able to inject a script element that can load malicious code from any domain. The same applies if instead the scheme https: is used. It seems that this configuration option is too confusing for developers as for some it might look like as if this configuration would just prevent HTTP access. However, if used it allows access to any domain via HTTPS. So, when some developers use the https: together with a list of domain names they want to allow, this domain list does not have any effect, as any domains are already allowed:

default-src 'self' data: https: ssl.gstatic.com maps.google.com;

Such ineffective domain restrictions were observed in about 7% (iOS / Android) of the analyzed hybrid apps, which might give a false sense of security. Instead, the developer would need to specify the protocol together with the scheme (e.g. https://ssl.gstatic.com) to restrict access to listed domains and allow this access only via HTTPS.

Unfortunatly, in about 5% (iOS / Android) of the analyzed hybrid apps also parsing errors were detected that can prevent the intended protection. In general, such parsing errors could lead to more strict or less strict restrictions, depending on which part of the CSP is affected. However, as more strict policies that are accidentally created are more likely to cause functional issues than in the case of accidentally created less strict policies, the chance is much higher that those issues are detected in functional testing. For example, we observed parsing errors that prevent some or all directives from being applied. In all these cases, the errors lead to a less strict CSP, e.g. by omitting a good strict default-src directive that is now missing for a secure fallback for other non-specified directives.

CSPs can have a strong impact on app security. They are especially important for hybrid apps. The analysis results show that it is important to check if apps do use a CSP and that the CSP needs to be evaluated carefully. In case of doubt, developers should check the CSP with a free tool such as the Google CSP Evaluator to better understand the impact of the directives and to prevent parsing flaws.

iOS App Tracking Transparency – Adoption Rate of App Implementations

With Apple’s release of iOS 14.5 at the end of April, iOS app developers are required to request permission in order to track their users beyond the app’s border. While there are already complaints about the low opt-in rate published by the app analytics company Flurry, which are updated weekly, we were curious to see how the overall adoption rate for app implementations would look like.

Developers need to provide a tracking description in the apps info.plist file – together with localized versions in file InfoPlist.strings of language’s project directory – called NSUserTrackingUsageDescription that informs the user why an app is requesting permission to use data for tracking the user or the device. However, in 57.3 % of the current German Top 2000 iOS apps no tracking description was provided by the developers although the app contains tracking code. On devices with iOS 14.5 or later this causes iOS to deny the request for access to the identifier for advertisers (IDFA). So the opt-in rate of users could be higher if those 57.3% of the developers would have provided a description, so that the user is at least presented with a decision dialog.

Property %
No tracking description included but tracking code detected57.3 %
Tracking description included and tracking code detected33.5 %
No tracking description included and no tracking code detected9.0 %
Tracking description included but no tracking code detected0.2 %
Evaluation of Tracking Descriptions in German Top 2000 iOS Apps of all Categories except Games and Stickers (Appicaptor, July 2021)

Another effect we observed is a missing individualization and usefullness of the description. The table below lists the Top 10 used descriptions in the Top 2000 Apps, with 77 Apps just repeating the example text provided by Apple. Other just include placeholder text, such as “YOUR TEXT”, “NSUserTrackingUsageDescription”, “none” or even “-“.

Description #
This identifier will be used to deliver personalized ads to you.77
Your data will be used to deliver personalized ads to you.9
Dadurch können wir Ihnen relevantere Werbung anzeigen, ohne deren Anzahl zu erhöhen.7
Dies wird verwendet, um den Dienst zu identifizieren, der dich weitergeleitet hat, um die ein individuelles Erlebnis zu bieten.6
Diese Kennung wird verwendet, um Ihnen personalisierte Anzeigen zu liefern.6
Ihre Daten werden verwendet, um Ihnen personalisierte Werbung zu zeigen.6
Your data will be used to deliver personalized ads.5
Datenerhebung zur Verbesserung der App und für Werbezwecke zulassen4
Deine Aktivitäten werden verwendet, um Dein Nutzererlebnis und Werbung zu personalisieren.4
Mithilfe dieser ID können wir Dir für Dich ausgewählte Werbung anzeigen.4
Top 10 Tracking Descriptions by Occurence in German Top 2000 iOS Apps of all Categories except Games and Stickers (Appicaptor, July 2021)

This leaves us with the impression, that creating a fitting description is currently only deamed important for 1/3 of the developers. Obviously the motivation depends on the benefits the developers gain from providing a tracking description.

There are many business cases which rely on or have a benefit from cross-app user tracking. The players of these business cases (e.g., ad providers and app developers who generate ad revenue) have an interest to achieve high opt-in rates. Fitting or at least reasonable descriptions for the permission dialogue will be the key for broad acceptance rates. The current evaluation shows that (1) only a minority of apps have at least a description included and (2) that they are very unspecific.

But there are use cases which currently integrate cross-app user tracking, however it does not have a beneficial effect for the using party. For example, this is the case when an app developer integrates a runtime diagnostic library. As he is only interested in the telematic data of his app, cross-app tracking would not be his interest and for that reason he may not include the description for the permission dialogue. In this case Apple’s initiative would help to reduce user tracking from companies that provide a runtime diagnostic services with a business model of selling retrieved analytics data sets to third parties or similar use cases.

Known TwitterKit Vulnerability, still an Issue?

Nearly 18 months ago we published a vulnerability in our Appicaptor blog that the current Twitter Kit framework for iOS does not properly validate the TLS certificate. This vulnerability can be utilized for man-in-the-middle-attacks.

Twitter stated that there will be no fixed version of the vulnerable library, because it is seen as deprecated and no longer supported. Therefore, developers should have taken action and have removed the TwitterKit from their apps.

Every month Appicaptor evaluates the IT security quality of thousands of Android and iOS apps. So one might ask: Does the German Top 2000 iOS Apps still utilize the vulnerable Twitter Kit library version and is there a trend visible? The following chart depicts for each month the number of apps that are prone to the vulnerability within the 2,000 most popular apps in iOS App Store.

It is visible in the chart that the amount of apps with the vulnerable library quite constantly and slowly decreases throughout the year, reducing the risks for users. Although there is quite some fluctuation on the considered top list, a clear trend is visible, even if it took much longer than thought. But nevertheless, from our point of view, none of the most popular apps should have such a massive vulnerability. Therefore we would like to advise again that app developers should switch to alternative APIs.

iOS: 40% Critical Log Statement Usage in Apps

Developers commonly need log statements in their apps to track down problems by printing out information about the current program state. However, this can also lead to serious information disclosure to third parties, as many developers still use the old NSLog statement in about 40% of the Top 2000 German iOS apps. Many developer sites state, that information logged with NSLog will not be persisted on the device and therefore the usage is not critical. However, that’s not correct as we will demonstrate in the following for current iOS devices.

Over the years, Apple has changed a lot under the hood of iOS. Likewise the logging mechanism has changed in multiple aspects. One major change was the introduction of unified logging with iOS 10, which provides log levels, information hiding for sensitive entries and many other configuration capabilities. However, these new feature are only usable if the new os_log macro is used.

When using NSLog, the log messages are stored with default log level persistently for a certain time, which was tested with iOS 12.4, iOS 13.3 and 13.4 on non-jailbroken devices. Depending on the usage intensity of the iOS device, the stored log messages can go back days or months.

Log entries on these iOS devices are stored system-wide in the directory /var/db/diagnostics/Persist in files of the tracev3 binary format, which can be made readable again e.g. with the OSX log tool or platform independent wth UnifiedLogReader. The stored database files are protected by iOS DataProtection class NSFileProtectionCompleteUntilFirstUserAuthentication with the device passcode until the first user’s logon and can only be read by the administrative user root.

This means, in a lost-device scenario for an iOS device without passcode, these logging outputs can be read directly via USB using the iOS sysdiagnose function. If a passcode is set, the passcode is required to read the logging outputs.

However, since users are often asked to send the sysdiagnose data to Apple or App developers (see instructions e.g: https://faq.pdfviewer.io/en/articles/1458505-ios-how-to-send-a-sysdiagnose), in this case third parties will get access to log messages of all utilized apps (within the persisted time frame).

Among many other debug information, the transmitted file sysdiagnose_[date]_iPhone_OS_[device].tar.gz contains the file system_logs.logarchive. It is compressed and needs to be converted first to make use of it. This can be done quite easy on OSX.

The file system_logs.logarchive can be viewed on OSX with the log command:

log show system_logs.logarchive --info --debug > logs.txt

To use the UnifiedLogReader instead, one first has to extract the files from the system_logs.logarchive to a folder and start the python script inside this folder like this, e.g. on Windows systems:

python [path_to]\UnifiedLogReader.py .\ .\timesync\ .\Persist [output_folder]

In the output file logs.txt, one can search for the app binary name to find the related log messages. In the following example the binary is called TestApp:

2020-03-25 15:18:19.707346+0100 0x517db  Default  0x0  737 0 TestApp: My NSLog example GPS: {"geoData": {"latitude": 49.xxx, "longitude": 8.xxx, "radius": 2.818104}, "filters": {}, "exclude": []}
2020-03-25 15:18:25.635420+0100 0x517db  Default  0x0  737 0 TestApp: My NSLog example GPS: {"geoData": {"latitude": 49.xxx, "longitude": 8.xxx, "radius": 5.515101}, "filters": {}, "exclude": []}
2020-03-25 15:18:28.657474+0100 0x517db  Default  0x0  737 0 TestApp: My NSLog example GPS: {"geoData": {"latitude": 49.xxx, "longitude": 8.xxx, "radius": 10.625031}, "filters": {}, "exclude": []} 

In these log messages, we often find GPS-positions along with email addresses, generated encryption keys, full credit card information and much more entered user content. Even for apps that primarily do not store sensitive data, the log can also reveal sensitive information such as sensitive app names, their installation dates and how and what was used inside the apps.   

From a user’s perspective, it should now be clear:

  • Do not send sysdiagnose data to anyone!
  • Deny access for Apple (see https://support.apple.com/en-us/HT202100), however, this does not disable the logging nor does this disable the possibility to create sysdiagose files.
  • Use a good passcode to make it harder to access these files unauthorized. 

But the best protection is to use apps, that don’t store sensitive data to logfiles!

So, make a test for yourself and inspect your sysdiagonse file to learn more about your apps and the things they store.

Developers should take a look at iOS Unified Logging with the os_log macro. It can be used to programmatically enable a persistent storage only for cases when needed for remote debugging (if that’s necessary at all). For all other cases it can be configured to use only console output, preventing a data leakage via persitent log files.

New Feature: Dynamic App Analysis

We have added a new app analysis method to our Appicaptor infrastructure. From now on all iOS app analysis orders within Appiaptor SmartWeb or Corporate subscriptions are also processed using dynamic analysis. Besides the already existing static code analysis, the apps are automatically invoked in an analysis environment. This way, processing and communication of user data is additionally monitored and analyzed during runtime of the app. To create reproducible results and code coverage, user interactions are simulated with a deterministic interaction model.

The results of the dynamic analysis are correlated with the static code analysis to increase the depth of the Appicaptor app rating regarding security and privacy risks.  For example user related data (address book entries, passwords, GPS positions, etc.) transmitted unprotected, transmitted to untrusted 3rd parties as well as abused by 3rd party libraries exploiting access permissions can be identified.