Using leaked data to examine vulnerabilities in SMS routing and SS7 signalling

3 months ago 2

Lighthouse Reports

By Gabriel Geiger and Crofton Black, Lighthouse Reports

Every day, millions of two-factor authentication codes travel the globe, securing access to bank accounts, email inboxes, dating profiles and encrypted chats. These SMS messages are designed to keep people’s accounts safe, yet rely on a sprawling, opaque and unregulated industry of intermediaries to reach their devices. A new leak obtained by Lighthouse Reports exposes just how vulnerable that system is.

In 2023, Lighthouse revealed how phone infrastructure controlled by Andreas Fink, an obscure telecom provider with ties to the surveillance industry, had been used to track people worldwide. Our investigation found that a phone network address (aka “global title”) used by Fink’s company, Fink Telecom Services (FTS), attempted to locate the phone of Mexican journalist Fredid Román just hours before he was shot and killed. Román had been reporting on organised crime activities in the state of Guerrero, on Mexico’s Pacific coast. Overall we found evidence of network addresses linked to FTS participating in a variety of surveillance, interception and account cracking operations over several years. We published our findings with a consortium of partners including Der Spiegel, Haaretz, Tages-Anzeiger and Mediapart.

Lighthouse subsequently received a dataset containing 100 million packets sent to and from FTS’s infrastructure over the span of one week. The leak gives a rarely seen (outside the telecom industry) insight into systemic network vulnerabilities, as well as exposing how a small and problematic entity can end up as a conduit for highly sensitive traffic from some of the world’s largest tech companies. It calls into question what due diligence these companies perform around their SMS routing and highlights concerns that companies may be compromising security by routing SMS at lowest cost. Our findings were published by Bloomberg Businessweek in June 2025.

The leaked traffic comprises SS7 signalling messages — elements in the network-to-network protocol used in 3G to direct communications to subscribers. Much of the traffic consists of routing instructions for A2P (application-to-person) SMS, within which there is a preponderance of two factor authentication (2FA) codes. These codes relate to top-tier tech companies including Google, Meta and Amazon, as well as other sensitive platforms such as Tinder, Snapchat, Airbnb, Uber and Docusign. There is also a significant quantity of 2FA codes for the encrypted messaging apps Signal and WhatsApp. A small subset of the data relates to geolocation surveillance attempts rather than SMS.

When we received this data, we wanted to understand where these 2FA messages were being routed to and from, which companies were most exposed, and to what extent the people receiving the messages were identifiable and thus potentially at risk of account compromise.

Analysing this type of data comes with challenges. Reconstructing SMS message flows required piecing together low level telecom signalling data. Furthermore, in some cases the data contains deliberate steps to obscure activity, including manipulating packet formation to disguise SMS content or more generally the type of signalling message. In the rest of this post, we’ll walk through how we processed and analysed the data, and what we found.

Mobile telecommunication has evolved through decades of accretion of protocols, with new layers being added as new generations of telephony have come online. Despite recent evolutions into 4G and 5G, for phones to communicate reliably when roaming or operating on different networks from their subscriber host, it is essential that they maintain backwards compatibility with previous network standards. As a result, the venerable SS7 system, now around fifty years old, remains an essential part of how mobile phone subscribers can connect to one another (and is likely to do so for a while yet). Because it was designed prior to the globalisation and liberalisation of the telecom industry, at a time when most countries had only one national operator and issues of trust around verification of message provenance did not exist, SS7 is relatively unsecured. The entire contents of any SS7 signalling message are visible at any node that the message passes through, and the market for accessing such nodes is well established.

Signalling messages carry routing instructions within and between networks. These routing instructions are used to query “location registers”, i.e. databases holding information about which network node each subscriber is currently (or was recently) located on.

Internally, phone networks identify their subscribers by IMSI (“International Mobile Subscriber Identity”) — 15- or 14-digit numbers which are not publicly available. Externally, people identify their phone numbers according to MSISDN (“Mobile Station International Subscriber Directory Number”), the normal phone number system commonly used by everyone. IMSIs and MSISDNs follow different structures. Many network operations begin with a translation from MSISDN to IMSI — from the normal phone number that your friends know, to an internal number that (in theory) is only known to your network.¹

SS7 signalling messages are sent and received by “global titles”. These look like normal phone numbers, and come from operators’ normal allocated ranges, but are used to carry out routing functions rather than being given to subscribers as their personal phone numbers.

To complicate matters, global titles are often leased and traded between phone operators and other entities in the broader telecom ecosystem. This means that such entities can send routing queries using global titles belonging to operators in other countries. FTS, a company based in Switzerland, has used global titles from countries including Namibia, Sweden, Italy, Russia, the UK and other places.

This year, following revelations of surveillance abuses and account cracks, the UK phone regulator, Ofcom, banned the leasing of global titles. Globally, however, the issue remains largely unaddressed. The relative ease and low cost of acquiring global titles on the international market has allowed a broad roster of entities to acquire the ability to interact with networks worldwide, querying subscriber locations and sending messages to them. These entities may be “aggregators” (bulk SMS senders), IOT businesses, purveyors of sundry niche services such as number database cleaning, portability checks or anti-fraud mechanisms. Alternatively, they may be surveillance industry contractors.²

We received hundreds of .pcap files, each of which contained tens of thousands of packets capturing the raw flow of SS7 data between Fink Telecom and other networks. We decoded the packets using Wireshark, a popular open source application for analysing networks.

Each packet contains dozens of fields spread across a stack of different communication protocols. Of these, the following fields are most relevant to our analysis because they provide key information about provenance and destination of a packet and its payload.

For analysis, we needed to convert each of our .pcap files into a flat, tabular format. We exported the packet data to .csv files, which allowed for easier parsing and analysis in Python. We automated the conversion process using Tshark, a command line interface for Wireshark. We used the following command to convert each .pcap file into a .csv file.

tshark -r {input_pcap} -T fields -E header=y -E separator=, -E quote=d{fields} > {output}.csv

We ended up with around 200 .csvs, which we concatenated into a single dataframe in Pandas, a data analysis library in Python. This dataframe contained around 100 million rows, each representing an individual packet. To focus our analysis on the most relevant packets, we dropped all packets associated with other network functions to focus only on those containing SS7 routing data. Our final working dataframe contained over 34 million packets.

Each completed interaction in the dataset involves multiple packets. Take SMS delivery as an example: the sending network issues a packet containing a Send Routing Info for Short Message (SRI-SM) request which includes the recipient’s MSISDN. The recipient’s network responds with a packet containing the corresponding IMSI and MSC (switching centre). The sending network then sends a Forward Short Message (ForwardSM) packet containing the actual text message directed to this IMSI at that MSC.

These interactions are linked using an originating transaction ID (otid) and destination transaction ID (dtid). These IDs can be reused even within a relatively short duration, so we developed a linking algorithm that uses timestamp proximity when multiple candidates exist. This allowed us to link IMSIs to MSISDNs, and thus to identify subscribers receiving 2FA codes.

def map_imsi_to_msisdn(row, otid_msisdn_mapping) :
"""
Takes a row and matches its IMSI to corresponding MSISDNs by comparing dtid and otid
Args:
row (pd.Series): A dataframe row
otid_msisdn_mapping (dict): A dictionary where each otid is mapped to a dictionary containing MSISDN - timestamp pairs of potential candidates
"""

matching_otid = row['dtid']
msisdn_dict = otid_msisdn_mapping.get(matching_otid, [])

# If only one candidate, return it
if len(msisdn_dict) == 1:
return msisdn_dict[0]['msisdn']

# Extract timestamp
imsi_timestamp = row['Arrival Time']

# Initialize variables to track the closest MSISDN and time difference
closest_msisdn = None
closest_time_diff = float('inf')

# Compare timestamps and find the closest MSISDN
for msisdn_timestamp_pair in msisdn_dict:
msisdn = msisdn_timestamp_pair['msisdn']
msisdn_timestamp = msisdn_timestamp_pair['timestamp']

time_diff = abs(imsi_timestamp - msisdn_timestamp).total_seconds()

# Update closest MSISDN if a closer one is found
if time_diff < closest_time_diff:
closest_msisdn = msisdn
closest_time_diff = time_diff

return closest_msisdn

From this dataset we derived a set of tables indicating what types of commands were being sent, which global titles were being used, which IMSIs and MSISDNs were being targeted, and other analytical breakdowns.

In total, the SMS messages in our data were routed to individuals in more than 170 countries (i.e. around 90% of the countries in the world). Many of the subscribers in the dataset were roaming rather than being located on their home network, which the data captures using the Called Country field.

The “sender ID” of an SMS message is captured under the heading of Third Party — Originating Address (TP-OA). Within our dataset, a large number of SMS messages had TP-OAs reflecting names of various companies. We produced a frequency list of TP-OAs across the whole dataset, to get a sense of which companies were included as well as what other types of sender ID occurred (e.g. random numbers or alphanumeric strings). For a set of common TP-OAs we then extracted all SMSs and corresponding metadata. Looking at the most frequent and prominent companies in the TP-OA list,³ we saw that their SMS content included thousands of 2FA codes. The table below offers some examples (numbers rounded).

Looking at the SMS content, we could see which messages contained account security checks. We could also in some instances identify email accounts or usernames, or the personal name of the recipient. Not all SMS content contained login codes; some contained detailed bank transactions, online shopping or other services.

One interesting feature of this data was that it exhibits, in the wild, a firewall-bypassing technique known as “global opcode”. The efficacy of this technique has been known for some years to SS7 specialists.⁴

The technique relies on the fact that within the packet’s structure the “opcode” — i.e. the 2-digit hex code that identifies what type of operation is being carried out — is accompanied by a single byte flag, which can either be set to “local” (02) or “global” (06). Standard packet translation protocol expects this flag to be set to local. If the byte is flipped to “global”, the packet’s structure appears no longer translatable, although nothing else has changed. In Wireshark such packets are marked as “malformed”, and SMS content is no longer visible, although it remains embedded within the packet in just the same way as before. Security specialists have observed that packets with global opcodes are sometimes able to evade firewall filters, while carrying out their intended activity unimpeded.⁵ As a result, global opcode SMS may reach their destination intact, but without being billed as SMS to the company doing the sending. The result is that the sender makes a greater margin on their activities, while the recipient network is effectively being defrauded.

In order to decode the over 1 million “malformed” packets, we parsed the raw hex data and replaced all global opcodes with local opcodes. The modified binary was then written to a new capture file, which Wireshark was able to parse and no longer marked as “malformed.” We could now see that these formerly unreadable packets contained further 2FA SMS, notably from Google, TikTok, Signal and WhatsApp.

# Read the hex string and replace 0601 (global) opcodes with 0201 (local)
with open(malformed_pcap_path + pcap,"rb") as f :
hex_string = f.read().hex()
hex_string = hex_string.replace("0601","0201", 1)
f.close()

# Write the new hex string as bytes into a new pcap.
with open(malformed_pcap_path + new_filename,"wb") as f :
f.write(bytes.f

Not all SMS traffic in the dataset was 2FA codes or banking/billing info. In one curious and troubling case, we identified hundreds of SMS messages that appeared to be sent from a well known European surveillance company, comprising real-time updates on operational surveillance of individuals. We have chosen not to disclose the name of the company. These SMSs included detailed information such as the names of the persons of interest, movements at specific times, geographical areas and car registration plates. In one case we were able to match the name of one of the individuals to a media report of an arrest by authorities a few weeks later, occurring in the same region as the surveillance data. We found it alarming that the company in question was using unencrypted SMS to send this type of sensitive real-time operational data.

As well as SMSs, the data contained a smaller amount of geolocation traffic of the sort typically used by surveillance-for-hire companies and their clients. This usually took the form of AnyTimeInterrogation (ATI), ProvideSubscriberInformation (PSI) or ProviderSubscriberLocation (PSL) GSM MAP packets. These packets query either the MSISDN (in the case of ATI) or the IMSI (in the case of PSI and PSL) of the target and when successful trigger the return of a Cell ID. The Cell ID can then be geolocated via public databases to give latitude and longitude. We identified around 150 location requests, although not all were successful. Some of these were malformed in the same way as the SMSs discussed above, presumably in an effort to bypass firewall protections.

In some cases, the targets of these attempts were identifiable through their MSISDN. In one instance, we identified an employee of a company that sells SS7-based geolocation services. We assume — but cannot confirm — that the efforts to geolocate this employee were tests of the company’s own systems.

Our findings (made in collaboration with Ryan Gallagher at Bloomberg) were that companies sending sensitive information via SMS have little visibility into how that information reaches its intended recipient. The fact that FTS was acting as a transit route for these SMSs at the same time as acting as a contractor for the surveillance industry underlines the difficulty of doing due diligence into SMS supply chains. Predominantly, the industry appears to be motivated primarily by speed and low cost rather than by due diligence in any case. We do not believe that FTS is unique in this regard; rather that any number of companies could play a similar role, given the market conditions prevailing around SMS routing.

In response to our reporting, Meta stated that it “had reminded partners of contractual obligations to ensure privacy and security when delivering SMS messages to Meta users” and “had notified its partners they shouldn’t subcontract or otherwise engage with Fink Telecom when providing services to Meta or any of its affiliates”. But we didn’t receive similar confirmations of enhanced due diligence from other companies — including, perhaps surprisingly, Signal.

The distributed nature of SMS routing may make overseeing the supply chain hard. But it would be nice to think that companies are at least trying to look as if they are doing it.

A second finding relates to the instances of geolocation surveillance traffic within the dataset. We previously showed how Tykelab, an undisclosed affiliate of the Italian surveillance company RCS Lab, was claiming on its website to be a bulk SMS sender while in fact sending geolocation signalling messages. The FTS dataset offers further evidence that bulk SMS traffic remains a good place to hide surveillance traffic. Notably, we were able to see instances of successful surveillance queries, i.e. those returning Cell IDs and coordinates.

Read Entire Article