The hidden risks of public SMS services — How your messages are being exposed

Molx32
10 min readSep 22, 2024

--

This article explores the security risks posed by Public SMS Services, where shared virtual phone numbers allow users to read each other’s messages. Through real-world examples, it highlights the potential for data exposure and unauthorized access to sensitive information, underscoring the dangers of using these services for verification and authentication.

[Introduction text partially generated by ChatGPT]

About Public SMS Services and security

A really quick word about existing reasearch on this topic : the only source I could find is from the Canadian ZATAZ that published a short post about Public SMS Services. I couldn’t find anything else, so tell me if you did.

What are Public SMS Services (PSS)?

While browsing the Internet, you probably searched for a temporary email address at least once. For example, you created a user account on some web app, and you didn’t want to provide real information. In the same way, you may need a temporary phone number if the app requires it: in this case, you probably used a virtual phone number, which allows you to receive a confirmation SMS or so, in order to validate your registration on the concerned web app. Although this use case is quite simple, let’s give a proper definition of what I call SMS Services.

A SMS Service is an online service that provides virtual phone numbers to their customers in order to receive SMSs. If a service provides additional services, such as VoIP, let’s still consider it a SMS Service.

There are plenty of such services out there. Using any simple online research such as receive sms online using your favorite search engine will lead you to multiple websites.

An example

Let’s take an example real quick and have a look at https://smstome.com. Just select a phone number : congratulation, you can read all messages received.

Step 1 — Choose a country
Step 2 — Choose a number

If you want to do some testing, simply try to register on a web app that requires a phone number, and check if you receive a verification SMS. Actually it might not work, because after some time, those phone numbers are considered malicious or suspicious by carriers and applications. To ensure the service is still available, SMS service providers simply retire old phone numbers and replace them with new ones.

Step 3 — Read messages

You may notice that some messages seem truncated, and they actually are. I don’t know why, but this is a common issue shared by many SMS services, which maybe need to optimize their data storage, especially for free services.

Security issue

When looking at these services, we can see that some are billed, others are free. There are two main differences between the two :

  • Privacy — For users looking for privacy, free services are prefered because they don’t require users to create an account, while paid services require to do so i.e. require users to provide personal information.
  • Access control — When subscribing to a paid service, virtual phone numbers are private i.e. a user can have multiple virtual phone numbers, but a virtual phone number can be owned only by one user. However with free services there is no form of access control, and virtual phone numbers can be shared, so are SMSs.

Obviously, the only thing we can exploit here is free SMS services, that I will now call Public SMS Services (PSS), which is not an official term.

A Public SMS Service (PSS) is a SMS Service that do not provide any access control mechanism, and allows multiple users to share the same virtual phone numbers, and thus allows users to read each other messages.

Here is a quick summary of the different SMS Services categories.

SMS Services categories

Before digging those services, here is a scheme representing our study scope. As you can see, I only studied SMS received on https://receive-smss.com/, which is a public and free SMS service. I decided to focus only this data source because it was pretty simple to automate data collection, but also because this web sites received a lot of messages.

Scope of the study

Exploiting the security issue

In very short words, exploiting the security issue consist in reading messages and finding juicy information. This GIF summarizes the different exploit scenarios.

Exploit scenarios

When reading messages, there are two main situations SMS without URL, and SMS with URL.

  • SMS without URL

1. — User A gets a virtual phone number from a PSS

2. — User A uses this phone number to register on a web application that will store all user-related data into its database.

3. — At some point, the application will be triggered to send a SMS, e.g. to invite the user to come back to the app : Hey John DOE, you have a new offer on your house located at Av. de Cointe 5, 4000 Liège, Belgium!. The SMS will be sent to the phone number associated to User A and thus sent to the PSS.

4.a. — A malicious User B spends their time watching SMSs on the PSS and reads PII, which is the equivalent of an indirect read access to the application database.

4.b. — Alternatively, the SMS may also contain some PIN or password that can be used to authenticate on an app with the phone number as a user ID. In this case, User B could compromise the account, and have an indirect read/write access to User A information.

  • SMS with URL

1. — User A gets a virtual phone number from a PSS

2. — User A uses this phone number to register on a web application that will store all user-related data into its database.

3. — At some point, the application will be triggered to send a SMS, for example : Hey John DOE, you have a new match, send them a message : https://findadate.com/messages?token=eyf652s4fz6e621s[…]r5g1. The SMS will be sent to the phone number associated to User A and thus sent to the PSS.

4. — A malicious User B spends their time to watch SMSs on the PSS and navigate to the URL, and is able to either reset a password, or directly compromise User A account, and have an indirect read/write access to User A information.

At this point you may think that this is quite a simple scenario but that there might not be a lot of messages, nor a lot of juicy information there. This is what I believed until I compromised 1500 accounts/month, as described in my previous post!

Additionaly, I described the personal information/account takeover case, but there are two other applications in cybersecurity.

  • OffSec purposes — Discovery (subdomains, shorten domains, internal test user accounts, account takeovers, password resets takeover, etc.)
  • OSINT purposes — Personal information (email, first name, last name, username, location )
  • Threat Intell purposes — Scams and smishing campaigns on-going or being set up.

Something to remember so far : do not trust web application, they may send anything they want using SMSs, including personal information or URLs giving access to your account.

Automation

This part is about technical stuff. If you simply want to get the result, skip this section! Otherwise, let’s go!

Architecture

The whole architecture is made of Docker containers. The entry point from the user perspective is the Flask web server which renders and serves web pages, and launch different jobs in a Redis queue:

  • A job that will initialize various things
  • A job that will collect messages (infinite loop)
  • A job that will collect data, only in aggressive mode (infinite loop)

These jobs will be executed by two workers. Finally, we have a database with SMSs, targets, configuration, and so on.

How it works

  • First approach

I developed a first very basic version of the solution. It parses https://receive-smss.com/ and stores any unique SMS identified. I quickly figured out that there were two interesting cases.

❌ The first one is when messages directly contain sensitive data, like credentials or PII. Since this is a very rare case, and because it is complex to automate without false positive, I paused this use case for now.

✅The second one is when messages contain URLs. This is a much more frequent case, and it represents a huge part of interesting messages. Why? Because anything can hide behind a URL : a scam or an account compromise. From now on, my goal is to exploit SMS that contain URLs.

  • Improvements

To make the analysis a bit simpler, I developed a web interface where I can look for messages collected, and easily navigate to URLs. Thanks to this tiny improvement, I built a list of all URLs and I manually navigated to each one of them, and some of them simply gave me access to user accounts. Thus, I decided to develop the last core feature: the aggressive mode. This can be turned on to navigate to URLs known to hide interesting data, then it will add this data to the database!

Challenges, limitations and backlog

  • Race conditions (Priority -)

I faced a challenge that is still not resolved: race conditions. Some URLs, such as password reset URLs, have either an expiration date, or can be accessed only once to prevent someone else to reset a password a second time. I decided not to focus on that problem for now, because there are a lot of simpler cases URLs to explore. That being said, the application is able to collect message with a 5s delay so that’s not so bad.

  • Security controls (Priority -)

Some security controls prevents us to access some URLs, because of user agents, locations, and so on. This also includes web apps that are supposed to be accessed with a smartphone user-agent.

  • Request throttling (Priority +)

Requests rate limiting causes the targeted server to return a HTTP 429 Too Many Requests and prevents us to parse additional data for a few seconds or minutes. The simple solution is to wait for the server to accept new requests, but this is not enough.

  • Data collection (Priority ++)

Collecting data is a real challenge because it will be different for each target domain identified. What I mean is that data may be included directly in HTML, or it may be fetched from an API, or in URL parameters after a redirect, and so on.

There are multiple methods to retrieve data, and it is different for each URL identified. But I tried to simplify data collection by creating data collection modules. Here is an example : I recently noticed that TargetA sends SMSs with a URL matching https://sub.target-a.com/, and that interesting data can be retrieved from the Location header of an HTTP 302 response.

// Request
GET /1UxRn3rwtFtQOma HTTP/1.1
Host: sub.target-a.com
// Response
HTTP/1.1 301 Moved Permanently
Location: http://www.sub.target-a.com/account?token=abcedfgh1234567890&email=test@test.net

I want to collect data, and I need to create a new module that I will call TargetA, which is a child of DataModule. DataModule already provides a function to retrieve data from the Location header so I can use it to avoid writing code.

class TargetA(DataModule):
def __init__(self):
name = 'TargetA'
base_url = 'https://sub.target-a.com/'
super().__init__(name, base_url)

def retrieve_data(self, url, msg):
return self._retrieve_data_redirect(url)

In that situation, developping a new module is very simple, but it becomes way more annoying when we need to parse HTML. Improving data collection is still in my backlog.

Results

Now is the time to finally talk about cybersecurity, OSINT, CTI, and OffSec! This section describes the different use cases I encountered while analyzing hundreds of thousands of SMS. For each use case, I tried to dig as deeper as I could to provide a real world impact analysis.

Also, from an attacker perspective, all the presented results are opportunistic, which means the attacker is not able to choose its target and entirely relies on which account or data URLs may redirect to.

The following table shows the different use cases encountered.

Cases encountered

Here is a non-exhaustive list of targets sorted in the different use cases encountered. If you want to take a closer look at those targets, I invite you to check the results here as is will be easy for you to navigate where you want.

Conclusion

Based on the sample of results we saw, there are two main outcomes I would like to highlight.

First, by assuming that phone numbers are private, companies allow themselves to send sensitive information by SMS e.g. URL to access a user account. Of course password reset is a specific case that requires the phone number to be trusted, but this is quite difficult to exploit because of race conditions and additional limit rate protection that can be set up (c.f. the Instagram case). Otherwise, companies may set up a blacklisting system to prevent users to register with PSS phone numbers : this is quite easy to implement.

Second, when registering on an application with a PSS phone number, we have no way to know what SMS will be sent. Thus, I would recommend the use of such phone number for testing purposes, and to avoid associating real data to whatever account was created with the phone number.

Thanks for reading!

--

--

Molx32
Molx32

Written by Molx32

I am a cybersecurity engineer, mainly working on Microsoft solutions.