Overview of iOS tracking traffic

Introduction
When I started reviewing a few iOS applications for privacy concerns, such as the SpringPad application which used your email addresses without permission, I noticed that many applications would contact third-party sites with information about your device, often including a unique identifier. At the time I didn’t have much data to back it up. But I decided to undertake a small project to study this more in depth. Here was my game plan:

  1. Download top 6 applications in each category on the App Store
  2. Launch each application, click few to no buttons at all, and close down the application
  3. Analyze the requests made by the application
  4. Note down all requests that somehow appears to have information enough to track your device
  5. Study the results

With this in mind, I went to work. It was quite a boring task, since I did it all manually. But quite quickly I noticed some trends. And this is what I want to share with everybody, since I couldn’t find any previous research done like this.

The tl;dr
Here are some very quick stats:

  • I downloaded apps from 22 categories
  • I downloaded and executed a total of 115 applications
  • They contacted 128 different servers and sent data about your device
  • Each application contacted between 0 and 10 servers with data about your device
  • 85 of the servers were contacted over HTTP (67%)
  • 42 of the servers were contacted over HTTPS (33%)
  • The applications that tracks you the most is USA TODAY, which communications information about you to 10 servers
  • The most used service is used by 29 applications (25%) of the ones tested, second most used was observed from 11 applications (9.5%)

Here are the requests contained about your device:

  • Unique identifier
  • Mac Address
  • Local IP address
  • GPS Coordinates
  • Time zone/location
  • Device type
  • Device version
  • OS type
  • OS version
  • OS locale
  • Application identifier
  • Application version
  • Screen resolution and orientation
  • Radio type (Wifi or 3G)

Methodology
My method for collecting this data involved using the proxy and target mapping function of Burp Pro. By installing a MITM certificate on my iPad, I can intercept most, if not all, of the traffic going out of the device over HTTP(S). I analyzed each request, and determined whether or not this request would track your device in any way, and added it to my Maltego document. I then saved the requests, cleared out Burp and went onto the next application.

The applications are the top 6 applications of each category from the iOS application store. I used the American app store for this, since it presumably has the biggest sample of users, and thus the top 6 applications would with the most likelihood be of interest to the most users. The applications had not been launched from the device before, so there were a lot of “first startup” requests observed.

The setup used can be replicated with the free version of the excellent tool Burp. Here are the steps I used:

  • Start up burp
  • Configure a browser (Example here being Firefox) to proxy through Burp, by default localhost on port 8080
  • Go to a HTTPS site through the configured browser, which should give you a SSL warning
  • Click “Add Exception”
  • Click “View”
  • Go to the “Details” tab
  • Click on the “PortSwigger CA” tree item in the Certificate Hierarchy
  • Click export
  • Save it as burp.cer
  • Using a command line, browse to where you saved the certificate.
  • Run python.exe -m SimpleHTTPServer
  • Now pick up your iDevice and browse to port 8000 on the machine used to extract the cert
  • You’ll now get a directory listing, pick out the cert you exported and download it
  • Now you’ll be taken to your System preferences, and can install the certificate. Job done

The big pictures

Breakdown by provider top 7 (Technical!)
http://data.flurry.com
Flurry comes in at the top of our list, with a total of 29 applications in our sample which uses this. Their site claims that (more than 190.000 applications use it)[http://www.flurry.com/product/analytics/index.html]. It makes a lot of requests with a lot of data. For instance, it appears to be making a request at both startup and shutdown of an application. And there’s a lot of seemingly random information. This traffic takes place over plain HTTP without SSL.

There are a few trends that we can see.

  • A unique identifier is sent across, 38XEJT2XRT2I9H9BFB29. This is seemingly unique to the application
  • The version number of the application, in this case 1.0.6
  • A unique identifier of the device, de5381e09b10d93043b50f43153f3aeeb4dcc589
  • Another seemingly unique value to the device, ID1BDCEF03-F55E-439D-BA2A-C0AAC6B7BF6B
  • Screen height, width, OS version, device model, locale, time zone
  • Followed by what seems like some application-specific information

ScoreCardResearch

This request looks, much like Flurry, to be tracking of the device and events taking place from the application, such as startup. It sends this content over plain HTTP, and was used by 11 of the tested applications.

Between these 4 requests, we see a number of information being transmitted:

  • The resolution of the device
  • Device type, version and locale
  • Application version
  • The connectivity of the device (Wifi or 3G)
  • Number of times the application has been started
  • Name of the application
  • The event that triggered the request (Such as starting up)

Admob
Admob is a Google service, which is used to track downloads of an application. It does so by making requests with a MD5 hash of the unique identifier of the device, and the application ID. It communicates exclusively over HTTP, and was used by 9 applications tested.

This is done by this piece of code that Google provides.

Tapjoy
Tapjoy is another run of the mill marketing network that has had a bit of a past. It appears to be also tied to a virtual currency, which can be obtained and used in applications using this service. It tracks the user on the application startup like most other services. The interesting thing to notice here is that one application is communicating with it across HTTP, while five are doing so over HTTPS.

From these two requests, we can see that it transmits:

  • A country code
  • Device type
  • Application ID
  • OS version
  • A library version
  • Language
  • Timestamp
  • Mac Address
  • Display multiplier
  • Application version
  • A verification value

2o7
2o7 is an “online marketing and web analytics business unit owned by Adobe Systems”. All communication takes place over HTTPS, and was used by 6 applications tested

These are the items that the request contains:

  • The local time
  • VID, an unique identifier
  • Device type and model
  • OS version
  • Locale
  • Day of the week
  • Time of week (In this case, weekend)
  • Screen orientation
  • Screen resolution

ChartBoost
ChartBoost is a system for cross-promoting applications, used by 5 of the tested applications. They are basically another marketing network. They make a request on first start over HTTPS, which looks like:

The interesting thing is that some of the applications sent across an “identity” value. I’ve yet to trace down what that value exactly means yet however.

  • OS Version
  • Unique identifier
  • An identity
  • Application ID
  • A signature of some sort
  • Country
  • Application version
  • Device language
  • Device model

Medialytics
Medialytics is a “rich media ad platform for mobile”. It communicates solely over HTTP, and was used by 5 of the tested applications.

The interesting thing is that it contains parameters for latitude and longitude, as well as mcc, mnc, and c which were empty during my testing. My iPad does not have GPS, which is most likely why this information was missing.

  • An application ID
  • Application version
  • Device type
  • OS version
  • Unique identifier
  • Latitude and Longitude
  • Screen resolution

Crittercism
Crittercism is a telemetry platform for tracking crashes and performance metrics. It is used by 5 applications which was tested and communicates over HTTPS.

From the looks of things, it collects:

  • Device model
  • OS version
  • Application version
  • Timestamp
  • OS Type
  • Locale
  • Device type
  • If the application was pirated or not
  • If the application was allowed remote notifications
  • A unique ID of some sort
  • Device name
  • Application ID
  • A key
  • Library version
  • Whether or not the request was sent through an application launch

Dissecting traffic from SpringPad for iOS

My research over the last couple of months has focused on the security ghetto of WordPress plugins. But recently @arnimarhardar turned me to the subject of mobile applications. As they often use HTTP, I felt right at home. I decided to download a few random applications onto my iPad and then go to town. I personally use my iPhone on a daily basis, so what I’m about to describe to you was quite the eye-opener for me in terms of what sort of data is sent about you to third-parties and such. Let me present to you, an extremely popular application: SpringPad.

Note: I’ve masked out parts of requests since they may contain unique identifiers and such things.

Dissecting Springpad
Armed with my recently acquired copy of Burp Pro, I booted up the application for the very first time. I was greeted with an authentication screen, asking me to sign up. Already at this point, Springpad has contacted a number of very interesting domains. There’s a few calls to Twitter and Facebook and such, but I’ve left those out since they offer no insights into what Springpad does.

  • https://api.redlaser.com
  • http://data.flurry.com
  • http://iphone3.springpad.com
  • https://ws.tapjoyads.com

Of these 4 requests, only one of them is actually related to the application at all. That seemed very odd to me. So let’s look at what they did in order listed.

Third-party requests

RedLaser is a “RedLaser is a free shopping app for iPhone, Windows Phones, and Android that has been downloaded over 19 million times.”. Ok, interesting. How that is used by a note-taking application is a mystery to me. But from what we can tell from the request, is that they sent the name of the application making the request, an unique identifier, the platform, hardware versions, sdk version, the build number, locale, application version and OS version. Of course, sending across an unique identifier is a bit questionable, given that I as an end-user have no idea what redlaser is, but let’s move on!

This one is fun, because it seems to be sending across an actual data-structure, null-byte padding and everything. But it’s sending across a couple of (unique) identifiers, resolution, model, and version information. That’s nice. Not only does there seem to be one piece of identifying information in this request like to redlaser, there’s several.

Before getting into the actual request to springpad, we need a last stop over to tapjoyads.com!

The third request to a third party consists of a lot of fun information, such as country, device type, carrier name, language, iOS version, and your devices’ mac address.

Springpad requests
And now, for the main course, Springpad. Let’s see what it’s got in store for us!

This is the first request it makes, and the very first thing that greeted me was that this communication didn’t go over HTTPS, which is a concern. But onto the request, we see some OAuth fun, and then a device identifier, which is again your mac address. Ok, not the biggest of deals, let’s now sign up!

At this point, we post our credentials to the site(Over HTTP, mind you. Ooops) with the addition of a sessionID in our cookie. Again we see the transmission of your mac address.

Hold on a minute, what is that being sent across the wire? At this point, all I’ve clicked on is for me to sign up and just finish registration. I’ve not been requested to submit all of my contacts which are stored in my iOS contact list. Huh, that’s odd! I thought maybe I missed something, so I checked again. Nope, I’m not asked if I want to upload this.

Note that these emails were a part of the HTTP request

The fine-print part of the story
So let’s go consult our privacy policy as for what information the application will automatically upload from me:

Oh, how odd. Not a word about contacts! This isn’t really what I’d expect. There’s another bit of the privacy policy which states:

Thinking that I could now log into their web-site and see which information they have obtained from me, I logged in and started reviewing it. To my surprise, not a single mention of contacts was to be found. This is starting to smell. So let’s consult the iOS Application Guidelines as put forward by Apple:

I am no lawyer, but I don’t see that this application should have, as per Apples application guidelines, taken this information from my device without permission.

Does this remind anybody else about Path?

Response from vendor
When I contacted Springpad about my concerns in regards to the lack of HTTPS and their use of contact information, they were very prompt in a reply to my concerns, specifically in regards to the lack of HTTPS and the use of contact informations. They explained that the lack of HTTPS was a result of a bug in the build process. A fix for this was being fast-tracked for submission to Apple by the end of the day.

They acknowledged that the application uploaded the emails from the contact book of the device. They noted that the data wasn’t stored, only kept in memory to see if anybody you know uses SpringPad as well. They plan to request for explicit permission in version 3.0.7, which at the time of writing is being tested by their QA.

Overall, they were extremely quick to reply and addressed my concerns quite well, despite having a bad time all at the same time.

WordPress Paid Memberships Pro information disclosure vulnerability

Advisory
Secunia Advisory SA 49630

Analysis of vulnerability
The page /adminpages/memberslist-csv.php is called through AJAX from admin pages, in order to export a CSV list of paid members on the WordPress site. It sets itself up like this:

Due to a lack of validation that the user is logged in and has sufficient rights to do so, we can simply request this page and get a full list of paid members on the blog.

WordPress Global Content Blocks multiple vulnerabilities

Advisory
Secunia Advisory SA 49854

Analysis of gcb_ajax_add.php vulnerability
A part of the admin interface for this plugin allows you to insert a “content block”, which can be used across WordPress to contain reusable blocks of content and PHP code. It does so by making a POST call to /resources/tinymce/gcd_ajax_add.php. Let’s have a quick look at that to see how it works.

So it starts by doing some initializations, validate that all the input is there that it needs, and do mostly best-practice sanitization. It then inserts the value into a database and returns the same value back in json format. The problem here is that at no point has the script checked that the calling user is logged in, and is an admin(This is important because it allows for inserting PHP code, which could cause an arbitrary code execution).

It does sanitization of all values but the name, but as it turns out this is all output encoded in the admin interface. But we’re still able to insert arbitrary content into the table without authentication, which could be bad due to the possibility of PHP code being inserted. This can be exploited like this:

Analysis of gdbvalue.php vulnerability
Another part of the admin interface is used to fetch the value of a content block, i.e the php code or other trip of content that may be reused on pages. In cases where it is php code, source code disclosure is a concern. The next 3 vulnerabilities allows for disclosure of block contents. The first one is in [/resources/tinymce/gcbvalue.php](http://plugins.svn.wordpress.org/global-content-blocks/tags/1.5.1/resources/tinymce/gcbvalue.php):

We see some validation of the input id to prevent SQL injection, and then a SQL query which will be used to print out the value(Code/markup) to the page. There is no validation that the caller is an admin, which means we can fetch the value(Which can be PHP code) with a simple HTTP request

This will disclose the contents of the block, which may contain PHP code that may contain secrets.

Analysis of gcb_export.php vulnerability
A feature that the admin panel of this plugin is that it will export the block defined for easy import into another blog. It does so by calling /gcb/gcb_export.php, which forces the browser to download a .gcb file which contains base64 encoded content.

Again there is a lack of validation that the user is logged in and has sufficient privileges to view this data normally. And because it may contain php code that is sensitive, it offers a source code disclosure vulnerability we can exploit like this. Note the semi-colon separated id list, which makes this very handy.

WordPress Sendit Newsletter plugin multiple SQL injection

Advisory
Secunia Advisory SA 49506

Analysis
A SQL injection vulnerability exists in the ajax.php file of the Sendit Newsletter plugin for WordPress, which is used for setting the subscribed or unsubscribed flag on an email.

By passing in an arbitrary key-pair value, we see that because of line 9, it will use the key-pair for the SET statement on line 17/27 without any validation. It will also explode(Split into an array) the ID value on line 10 and 11 and put the “ID” into a variable later used, without validating that it is an integer. This is then also used on line 17/27, and is also exploitable.

Because this call does not require any sort of authentication, we can make a simple POST request to exploit this and inject SQL:

WordPress A Page Flip Book plugin local file inclusion vulnerability

Advisory
Secunia Advisory SA 49505

Analysis
A page flip book for WordPress allows for different languages to be used. This is toggled by posting “pageflipbook_language” to the blog, which will update an option and then include the appropiate language. This is done in the main file, pageflipbook.php, which is always included.

We can see that it checks if “pageflipbook_language” is included in a POST parameter on line 30, it will update the option on the blog, otherwise it will pull the language value from the option and put that into the variable. This value is supposed to be the name of a php file. After that, it will include the chosen language file on line 47.

But because there is no validation that the file is a valid language file and there is no directory transversal, we can do a local file inclusion attack on this:

WordPress Symposium plugin multiple SQL injection vulnerabilities

Advisory
Secunia Advisory SA 49534

Analysis of group_menu_settings vulnerability
The group_menu_settings function in /ajax/symposium_group_functions.php allows an user to show settings for a group. The function takes a POST parameter called “uid1″, which is used for a sql query.

However due to an incorrect use of wpdb->prepare, the groupID is never sanitized. Also the function does not check user credentials until line 616, and as such allows for a SQL injection through a simple POST request like this:

Analysis of loadComposeForm vulnerability
The loadComposeForm function in /ajax/symposium_mail_functions.php is used to fetch the display name of an userID through a simple SQL query like this:

It first checks if the user is logged in, and then takes to mail_to POST parameter and append it to the query. But because there is no validation that the mail_to variable is in fact an integer, we can make a POST request if we have an authentication cookie, and exploit this SQL injection vulnerability:

Analysis of getReply vulnerability
The getReply function in /ajax/symposium_mail_functions.php is used to fetch the display name of a recipient and message information about a particular mail.

It first checks if the user is logged in, and then takes to mail_id and recipient_id POST parameter and stitches those into 2 SQL queries using simple concatenation. However due to a lack of validation of the parameters being integers, we can exploit this:

Analysis of symposium_openchat vulnerability
The symposium_openchat function in /ajax/symposium_bar_functions.php allows for opening a chat with another user on the site. It does so by getting the chat_to POST parameter, which si expected to be an integer, and then checks if that chat already exists:

If you’re logged in and the chat does not exist, on line 572 it will then insert a new chat and select the display name from the user table, and incorrectly use the wpdb_prepare function. By rather concatenating the ID in instead of passing it as a parameter, we can now select data out of the database like this:

Analysis of getEditDetails vulnerability
The getEditDetails function in /ajax/symposium_forum_functions.php gets the contents of a post for the edit page.

It checks if you’re logged in, and then takes the tid POST parameter and concatenates it into a SQL query without casting it to an integer or otherwise sanitizes it. This means we can exploit it by making a request like this:

Multiple blind injection spots in /ajax/symposium_mail_functions.php
On line 94, 101, 208, 210, 274, 276 in /ajax/symposium_mail_functions.php there is also a lack of validation of integer inputs, which allows for arbitrary query execution.

WordPress Quotes Collection plugin cross-site request forgery vulnerability

Advisory
Secunia Advisory SA 49653

Analysis
A type of vulnerability that seems to be fairly common is CSRF. You can obviously speculate as to why, but I found this interesting one. I normally won’t publish CSRF vulnerabilities, but there are cases where they can abuse the inherent trust that is put in an admin to not attempt to exploit the blog readers.

In this case, because the admin pages did not make use of nonces, we are able to craft a page which will make the user make a GET request with a XSS payload, which will at no point be sanitized besides being escaped for inserting into the database.

If we either make this request directly, simulating a CSRF attack, or actually create a malicious page and convince an admin on a WordPress blog with this plugin to click on your link, we can cause a persistent XSS due to the lack of a nonce and sanitizing of html input.

WordPress Zingiri Shop plugin “abspath” remote file inclusion vulnerability

Advisory
Secunia Advisory SA 49676

Analysis
I had been looking at this particular piece of code for a while. At a glance, while the handling of the looks somewhat safe due to the validation that the input path is in fact a directory, so at best you could sort of chain an exploit with this. The question is, how could you take this to a RFI? Lets look at /fws/download.php:

As you see, this may very well look safe at a glance. For us to be able to exploit the fact that the ‘abspath’ variable is user controlled, we need to get a true back from is_dir. I checked with google how to pull this off when providing a remote host. This isn’t possible with HTTP, and nobody suggested an alternative. For this to work, the protocol wrapper needs to support the “stat()” family of functions. HTTP isn’t one of these. But as it turns out, FTP is. Bingo! We now have a piece of code that through a very specific detail in the PHP implementation, that we can exploit.

By putting up a FTP server with some specified credentials, and a file called wp-blog-header.php with some malicious PHP, we can include an URL in the abspath GET parameter, which will exploit this vulnerability:

WordPress Mac Photo Gallery plugin “albid” arbitrary file disclosure vulnerability

Advisory
Secunia Advisory SA 49650

Analysis
This vulnerability relies on a lack of validation of the “albid” in macdownload.php, which is passed straight into the path that is read at line 37 into the response. This cases an arbitrary file disclosure vulnerability.

If we make a request like this, it will cause the code to read out the wp-config.php file, which will contain database credentials in.