Background

I recently purchased a Nexus 6P and being on O2 it's a requirement to download the O2 Wifi app and register it to get access to the London Underground wifi. I downloaded the app on my new phone and entered my phone number, only to get an error message saying, "Please download the latest version of the O2 Wifi App from the App Store". I called O2 technical support and spoke to a somewhat confused guy who didn't really understand the problem. I got a vague "Have you tried turning it off and on again" type of response but he said that he would report the issue.

Charles Proxy

I use Charles a lot when building mobile apps, often to simply monitor network requests coming from an app and less often to intercept and modify requests and responses to test abnormal and hard to reproduce situations. I happened to have it setup for some testing when it occurred to me to test the O2 app to see if I can determine and even fix the problem myself with some creative use of Charles. I was surprised with what I found next...

Summary of requests

I reinstalled the app on my Nexus 5 to log these requests, the process for a clean install (e.g. new device, new number) is a little different. New registrations prompt for additional details, they are sent to the O2 API in a similar way.

Step 1: Enter your phone number

Request 1
GET http://api.o2wifi.net.uk/v1?client_id=momac&method=customer.mobile_login&mac_address=f8-a9-**-**-**-**&sig=aef5daa90057d5674bc56b65ac80c052
Response 1
{
    "data": {
    "name": "Phil",
    "device": {
        "id": "79******",
        "last_sent": null,
        "mac_address": "f8-a9-**-**-**-**",
        "verified": true
        }
    },
    "state": "loaded"
}

OK, this one isn't so bad, but my MAC address has just been sent twice over the insecure connection.

Request 2
GET http://api.o2wifi.net.uk/v1?client_id=momac&countrycode=183&device_id=79******&method=sms.send_challenge&mpn=7*********&sig=359902eff609a14701b2ad1d5bb88e6c
Response 2
{
    "data": {
        "sent": true,
        "device_mpn": "unchanged"
    },
    "state": "saved"
}

There goes my phone number!

Step 2: Enter the text confirmation code

Request 1
GET http://api.o2wifi.net.uk/oauth2/token?client_id=momac&grant_type=sms_challenge&device_id=79******&verification_code=065168&scope=offline
Response 1
{
    "token_type": "Bearer",
    "access_token": "7524b243-****-****-****-************"
}

This is a custom OAuth2 grant request, although it somewhat resembles a password grant (if you consider the device_id and verification_code the username and password). Nothing wrong with that as such, but again it's sent insecurely over HTTP. Also, for what it's worth, I'm sure OAuth2 spec says to use POST for these kind of requests.

Request 2
GET http://api.o2wifi.net.uk/v1?access_token=7524b243-****-****-****-************&client_id=momac&method=customer_detail.secure_get&sig=1eeeb293ffe7a1a6744525b659564f3a
Response 2
{
    "data": {
        "customer_id": "5*******",
        "title": "Mr",
        "forename": "Phil",
        "surname": "Bayfield",
        "email": "phil@***************",
        "cust_type": "",
        "post_code": "ME10***",
        "dob": "1981-**-**",
        "signup_origin": "momac",
        "password": null,
        "signup_ssid": "",
        "opt_in_partner": "0",
        "opt_in_o2": "1",
        "created": "2015-05-07 07:55:22",
        "modified": "2015-05-07 07:56:59"
    },
    "state": "loaded"
}

There goes my personal details! Name, email, date of birth, postcode...

Request 3
GET http://api.o2wifi.net.uk/v1?access_token=7524b243-****-****-****-************&client_id=momac&method=device.secure_activate&sig=8bd7973a3253e276722512a0b77d197a
Response 3
{
    "data": [],
    "state": "updated"
}

Nothing to see here, although amusingly the request methods on the last two were secure_get and secure_activate.

Step 3: We're in!

O2 seem to be using http://momac.net/ to measure customer engagement. I've never heard of it, but at least they are using SSL to send my MAC address this time:

GET https://wapsbts.momac.net/pl/app/o2devid?devid=f5c948d702cdf629&msisdn=447557856876&devtype=Android&mac=f8-**-**-**-**-**

If you search for a hotspot, off go my device id, MAC address and phone number, merrily along their way over HTTP:

GET http://api.o2wifi.net.uk/v1?client_id=momac&id=7*******&limit=500&mac_address=f8-**-**-**-**-**&method=venue.find_all&mpn=7*********&offset=0&sig=105dc752929a71d60ace8801a6f0a0b4

Conclusion

A company the size of O2 should know better. If they are going to be transmitting your personal data, they should not be sending it insecurely in plain text. If they're going to use OAuth 2, they should stick to the guidelines and not completely ignore them.

If you use this app over your phone's data connection or a secure network, you probably don't have too much to worry about. Public access point, forget it!