All Articles

Monitoring traffic of iOS apps

Introduction

After reading a few days ago about Zoom sending data to facebook, I was not shocked at all. While I was using mitmproxy to log the traffic of my iPhone for my last project, it was obvious that many apps send analytics data to the Facebook API. Following #StayTheFuckHome, I have a bit more time on my hands, and I was logging the traffic of some of my installed applications. I do not think app analytics is a problem at all. For companies and developers, it is essential to know and understand about their app usage. However, this data is often sent together with unique identifiers, like the advertiser id or unique device id, to 3rd parties like Facebook. These 3rd parties can accumulate for each unique identifier which apps are installed and how they are used. In the best case, this information is (ab)used just for targeted advertisements. In the following, the apps I monitored are divided into The Good, The Bad, and The Ugly.

The Good

  • Uber
  • Twitter
  • Dropbox

All 3 of them did not show any traffic connection to 3rd parties for sending app analytics. All of them have set up their in-house analytics for reporting app usage to their APIs.

The Bad

Ryanair

The Ryanair app uses the Facebook SDK. It means the advertiser_id is sent together with the iOS version, screen resolution, network operator, timezone, and country-code for any app event. The POST request to https://graph.facebook.com/v4.0/1756342261282366/activities contains following data (shortened personal identifiers removed, yes I still use an iPhone 5s)

{
    "advertiser_id": "00AD3E04-CF5D-4B6A-9B06-xxxxxxxxxxx",
    "advertiser_tracking_enabled": "1",
    "anon_id": "XZ9308FFB6-7AEB-4077-B70D-xxxxxxxxxxx",
    "application_tracking_enabled": "1",
    "event": "CUSTOM_APP_EVENTS",
    "extinfo": "[\"i2\",\"com.ryanair.cheapflights\",\"227\",\"3.79.3\",\"12.4.5\",\"iPhone6,1\",\"en_PT\",\"WET\",\"NOS\",320,568,\"2.00\",2,15,2,\"Europe\\/Lisbon\"]",
    "format": "json",
    "include_headers": "false",
    "sdk": "ios"
}

However the Ryanair app also sends similar data to Swrve for every activity. A typical POST request to https://6177.eu-api.swrve.com/1/batch contains the same data as the request to facebook and additionally a unique_device_id and a user identifier.

{
    "data": [
        {
            "name": "app.launched",
            "type": "event"
        },
        {
            "attributes": {
                "Swrve.permission.ios.push_bg_refresh": "authorized",
                "swrve.device_dpi": 326,
                "swrve.device_height": 1136,
                "swrve.device_name": "iPhone6,1",
                "swrve.device_region": "PT",
                "swrve.device_width": 640,
                "swrve.os": "iOS",
                "swrve.os_version": "12.4.5",
                "swrve.sim_operator.iso_country_code": "pt",
                "swrve.sim_operator.name": "NOS",
                "swrve.timezone_name": "Europe/Lisbon",
            }
        }
    ],
    "unique_device_id": "3FFD84D2-70BE-49C2-B40F-XXXXXXXXXXXX",
    "user": "8C5F8FAF-8126-41F2-8D95-XXXXXXXXXXXX",
}

AirBnB

The Airbnb app sends to Facebook the same information as the Ryanair app. Additionally AirBnB also sends data to Sift. The requests to https://api3.siftscience.com/ contain the same data as the requests to Facebook. But, they contain additional information like the battery level, magnetic field sensor data, user id, and the IP address, which is personally identifiable information (PII).

{
    "installation_id": "3BD7943F-D927-4B2B-8827-xxxxxxxxxxxx",
    "ios_app_state": {
        "application_state": "ui_application_state_active",
        "battery_level": 0.6200000047683716,
        "battery_state": "ui_device_battery_state_unplugged",
        "device_orientation": "ui_device_orientation_portrait",
        "heading": {
            "raw_magnetic_field_x": -33.402767181396484,
            "raw_magnetic_field_y": -166.6410369873047,
            "raw_magnetic_field_z": 82.95677185058594,
            "true_heading": 163.66522216796875
        },
        "network_addresses": [
            "10.214.186.xxx",
            "fe80::86e:932a:29de:xxxx",
            "2001:8a0:65a3:6300:1809:8f6f:faa1:xxxx",
            "2001:8a0:65a3:6300:d14e:d203:4289:xxxx",
            "192.168.1.xx",
            "fe80::78a6:15ff:fea4:xxx",
            "fe80::7d1:2f87:88b1:xxxx"
        ],
    },
    "user_id": "C9uYLW9Rf1LHRsAwnBUCxxxx"
}

The Ugly

Glovo

The delivery app also sends the same data to Facebook as the other monitored apps. Besides that, the Glovo app also sends data to Braze. The POST requests to https://sdk.fra-01.braze.eu/api/v3/data contain the same data as the data sent to Facebook and a unique user_ID. Some requests also contain the location together with the time - also PII.

{
    "device_id": "5E1AAFC9-7889-4093-A3AF-xxxxxxxxxxxx",
    "events": [
        {
            "data": {
                "alt_accuracy": 4,
                "altitude": 58.13918685913086,
                "latitude": 48.858518,
                "ll_accuracy": 10,
                "longitude": 2.2922603
            },
            "name": "lr",
            "session_id": "7F8AF4F8-F5D8-43E0-A85C-xxxxxxxxxxxxx",
            "time": 1585420004.069,
            "user_id": "8349xxx"
        }
    ]
}

Glovo also sends data to Ravelin with a POST request to https://api.ravelin.net/v2/fingerprint containing the phone model, language, operator, all installed fonts and the gps location.

Bolt

Bolt, formerly Taxify, is a transportation platform similar to Uber. Again data is sent to Facebook, as the other apps do. However, Bolt also sends data to Segment that includes a user id, email, and phone number. The POST requests to https://api.segment.io/v1/batch hold the following data:

{
    "anonymousId": "8738A73E-34DF-47CE-8971-xxxxxxxxxxxx",
    "context": {
        "device": {
            "adTrackingEnabled": true,
            "advertisingId": "00AD3E04-CF5D-4B6A-9B06-xxxxxxxxxxxx",
            "id": "BED9A70E-667A-40C3-9113-xxxxxxxxxxxx",
            "manufacturer": "Apple",
            "model": "iPhone6,1",
            "type": "ios"
        },
        "traits": {
            "anonymousId": "8738A73E-34DF-47CE-8971-xxxxxxxxxxxx",
            "country": "pt",
            "device_name": "iPhone5S",
            "facebook_connected": false,
            "platform": "iOS",
            "platform_version": "12.4.5",
            "userId": "client-38675xxx",
            "user_email": "xxx@gmail.com",
            "user_first_name": "Swen",
            "user_id": "38675xxx",
            "user_last_name": "xxx",
            "user_phone": "+351915xxxxxx"
        }
    }
}

Additionally Bolt sends data to CleverTap containing similar information, as the requests to Facebook.

Zomato

Zomato is an app to discover restaurants and for food delivery. Zomato makes no exception in sending data to Facebook. However, Zomato also sends data to CleverTap . The POST requests to https://wzrkt.com/ contain pretty much the same data as the request to Facebook. But, also the full customer name, email address, and phone number are included. Here is an example of the request:

{
    "af": {
        "Carrier": "NOS",
        "Make": "Apple",
        "Model": "iPhone6,1",
        "OS": "iOS",
        "OS Version": "12.4.5",
        "Radio": "LTE",
        "cc": "pt",
        "mt_ifa": "00ad3e04cf5d4b6a9b0629exxxxxxxxx",
        "mt_ifv": "86c6b057b8844a3ba0ebe3bxxxxxxxxx",
        "useIP": true,
        "wifi": true
    }
},
{
    "profile": {
        "Carrier": "NOS",
        "Email": "xxx@gmail.com",
        "Name": "Swen XXX",
        "Phone": "",
        "cc": "pt",
        "ct_optout": false,
        "tz": "Europe/Lisbon"
    }
}

Conclusion

With the implementation of GDPR in 2018, most websites started to have mandatory consent for visitors, explaining how personal data is saved and used. Unfortunately, mobile applications do not seem to show or ask for any consent. Most apps send analytics data to Facebook, although this option can be switched off in the SDK. My biggest worry are The Ugly applications, which send personal information like full name, email, phone number, and location to Segment, CleverTap, or Ravelin. Segment advertises on the landing page Segment is a customer data platform that makes good data accessible for all teams. Who is going to have access to my personal information, maybe an external marketing team that also gets access to the Segment account? But the biggest concern is the same as for Facebook: There was never the option in any of the apps to give explicit consent. Since Segment and CleverTap are based in the US and both are probably used to create automatic profiles for advertisement, I believe that an explicit GDPR consent is necessary - But I am also not a lawyer ;)

Update 3 April 2020

Houseparty

Houseparty received some bad press about leaking passwords, which until this date is not proofed. Because of the popularity of the app, and by request in a Slack Channel, I also analyzed the app traffic of Houseparty. Houseparty does use the Facebook SDK, but no data is sent to the API containing user or device data.
After login, the app sends analytics data to Instabug containing the username, email, first name, and unique identifiers. Houseparty also sends data to Segment. These requests contain a lot of personal data (shortened to most essential):

{   "anonymousId": "EBB66C97-2120-4B5D-B949-B358B701XXXX",
    "context": {
        "device": {
            "adTrackingEnabled": true,
            "advertisingId": "00AD3E04-CF5D-4B6A-9B06-XXXXXXXXXXXX",
            "id": "60035683-C533-4A34-8541-XXXXXXXXXXXX",
            "manufacturer": "Apple",
            "model": "iPhone6,1"
        },
        "locale": "en-PT",
        "network": {
            "carrier": "NOS",
            "cellular": false,
            "wifi": true
        },
        "timezone": "Europe/Lisbon",
        "traits": {
            "email": "xxx@gmail.com",
            "name": "Swen",
            "p_camera": "allowed",
            "p_contacts": "denied",
            "p_location": "denied",
            "p_microphone": "allowed",
            "p_notifications": "denied",
            "phone_verified": false,
            "profile_photo": false,
            "token": "F07vbLVWMhOUHnz7tFEGcmu4J8Hhhh4XTGxFagRmMKHbXrVvGaUT0ECLvUXXXXXX",
            "user_dob": "19XX-XX-XXT00:00:00.000Z",
            "username": "sknzl"
        }
    },
    "properties": {
        "battery_percent_remaining": -100,
        "charge_state": "unknown",
        "connection_type": "wifi",
        "device_orientation": "portrait",
        "headphones": "none",
        "sneaking": false,
    },
    "userId": "5e837e625069b82c502cXXXX"
}

This request contains different phone settings, email, username, first name, day of birth and a token. This token got my special attention because it is the same token the application receives after a successful login and is used to authenticate the requests to the Houseparty API. Anybody with knowledge of this token, this means everybody that has access to the Segment data, can communicate with the API on behalf of the user account without knowing the username and password. The token is only refreshed on a password reset and is deleted on logout. The email of the user can only be changed by confirming with the existing password. Therefore it is not possible to take over an account completely, even by knowing the authentication token.