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.
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.
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:
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:
Use a good passcode to make it harder to access these files unauthorized.
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.
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.
Besides the targeted and specific weekly app tests with individual security policies of our customers, Appicaptor analyses the top 2,000 iOS and Android Android apps each month. The top 2,000 app test results can be indicatory for app security quality and risk assessment in your mobile device administration. As Appicaptor utilizes a standard policy for medium security requirements for the top 2,000 apps assessment, the results could be directly applied for your app blacklisting.
The Appicaptor backend uses data sources to determine app popularity and usage. This allows Appicaptor to designate the 2,000 most relevant, free apps within the entire iOS and Android app stores. Therefore, the Appicaptor Top 2000 Free test catalog offers a broad coverage of the apps that are relevant for administration practice (all apps of the app stores with the exception of games and sticker apps).
There are two Appicaptor options that provide an app risk assessment for a budget price point:
Top 2000 Free evaluates the top 2,000 apps of the iOS or Android app store.
Top 2000 Free Select expands the tested apps by 20 self-defined, free apps from the app stores.
Both options cost less than 10 Euro per day for your entire mobile environment. You receive web statistics (including blacklist rating according to the standard Appicaptor policy) and an Excel report of the findings every month.
The security quality of iOS and Android apps has improved slightly compared to 2018. However, the use of enterprise-class apps continues to require a critical look at existing risks to effectively address threats through audit and approval mechanisms.
The Twitter Kit framework through 3.4.2 for iOS does not properly validate the TLS certificate for api.twitter.com. That’s a finding found with our static binary analysis and reported to Twitter.
There will be no fixed version, as this library is no longer supported by Twitter, but this vulnerable library was still found in many apps. It is urgently advised that their app developers switch to alternative APIs.
Such issues are likewise common, which illustrates the need to check for vulnerable or outdated 3rd party code.
What makes this issue a bit special is the way the developers broke the validation of TLS certificates. Apparently, they wanted to increase the security by implementing a public key pinning of trusted root certificate authorities (CA), such as VeriSign, DigiCert and GeoTrust. So they created the following array with entries of 21 public key hashes for the CAs:
On every new connection, TwitterKit for iOS checks in method evaluateServerTrust whether the received certificate chain contains a certificate with a fitting public key of the list above. This way, certificates for api.twitter.com issued by possibly untrusted CAs should be blocked. However, this approach lacks a very important verification: The domain name of the leaf certificate is not verified by iOS, as TwitterKit for iOS implemented an own delegate method for its public key pinning functionality. In this case, iOS only verifies, that the certificate chain is valid regarding signatures. All other checks have to be performed by the delegate method, to provide the flexibility for alternative verification methods. A simple fix would have been additionally calling the iOS method secTrustEvaluate and utilize its result value to reject certificates for other domains.
Because of the missing domain name verification, any valid certificate chain containing a certificate with a public key hash of that list is accepted by the app. An attacker with a valid certificate for his own domain, issued by one of these CAs, can use this certificate for man-in-the-middle-attacks against apps communicating via the Twitter Kit for iOS with api.twitter.com. As the implementation does not check the position inside the chain, the matching public key could also be in the middle of the chain, such as in case of an intermediate certificate.
We used a matching legitimate certificate, issued by DigiCert for a domain under our control to verify the impact of the vulnerability. So we redirected the traffic for api.twitter.com to our server, that answers the request with our own certificate. The received content is logged and transmitted to the ‘real’ Twitter servers. The server’s response is also logged and transmitted back to the app. However, as the login process for Twitter involves a WebView, which does not use the vulnerable pinning functionality, it would not accept our certificate. As the WebView loads its content via the same domain name, we had to distinguish TLS connections based on differences in ALPN extension of the TLS Client Hello and route WebView connections without interception, to create a fully working proof of concept attack.
During the Login with Twitter process, our man-in-the-middle proxy recorded for a vulnerable news app the OAuth 1.0oauth_token_secret together with the authorized oauh_token. This enabled us to fully use the provided Twitter API with these long term secrets. Attackers could perform actions like changing content of the profile, creating fake tweets and direct messages or abusing the account to push tweets via fake likes. It would also be possible to read private direct messages sentor received within the last 30 days. We could not retrieve the password nor set it to a known value, so an attacker could not use the vulnerability to lock out a user from his account. However, by changing the Twitter password a victim would also not be able to invalidate the sniffed OAuth tokens. For this it is required to revoke the app’s authorization within the Twitter settings.
Further, on every app start the vulnerable app checks the validity of the Twitter account by invoking the Twitter API account/verify_credentials.json. In case the credentials are valid, the response contains detailed information about the victims Twitter profile, such as ID, name, location and last activities. As the response can be read in our attack scenario, the information can be used to collect information about the victim to track him or dynamically create targeted phishing attacks.
We will demonstrate the vulnerability and its detection at it-sa 2019 fair in Nuremberg, Germany at Hall 9, Booth 234.