Analysis of multiple vulnerabilities in different open source BTS products

Share this blog


By:Simone Margaritelli
        Zimperium zLabs

During the last weeks we’ve been investigating multiple aspects of GSM security such as protocol vulnerabilities as well as source auditing the world’s most common open source software products that run GSM networks. In this post we’ll share the details about multiple vulnerabilities in such software which allow an attacker to compromise a BTS station, crash it, or takeover its transceiver module remotely.

A BTS (base transceiver station) is composed of software and radio equipment that allows mobile stations (cellular phones) to connect to the GSM, UMTS, and LTE networks. They are the equivalent of wireless access points for Wi-Fi networks and handle the “Um”[1] layer/interface as shown in Figure 1.


Figure 1: A mobile station connecting to a BTS ( GNURadio OpenBTS documentation ).

The lower level software behind any BTS is the transceiver, which is the direct interface to the radio hardware. It is responsible for frequency tuning and handling GMSK (Gaussian Minimum Shift Keying) data modulation/demodulation. In short, it digitizes the radio waves. All the communication and synchronization with the rest of the logical units of the BTS is handled through three UDP sockets as shown in Figure 2.


Figure 2: The transceiver module and the three UDP sockets used to communicate with the rest of the BTS.

The clock socket is used for timing synchronization. The command socket is used by the BTS to send commands to the transceiver module. Finally, the data socket is used to transmit GSM “bursts” (data packets) from the BTS to the radio and receive responses back.

The UDPSocket class is used by the transceiver to handle all the three channels in Figure 2.

Our research shows that all of the most commonly available BTS software shares the same (or a very similar) transceiver code base. Thus, all of them are affected by the same vulnerabilities. The following reports are valid for all products listed below.

Such vulnerabilities would allow a malicious party to remotely control the transceiver module, thus compromising the BTS functionalities, impersonating a parallel BTS communicating with it.


Moreover, it is possible for the attacker to send GSM data bursts to the transceiver itself and perform a wide range of attacks such as IMSI detaching, encryption downgrading, denial of service, etc against mobile subscribers.

In order to be accepted by the transceiver module, UDP packets sent to the data channel socket must respect the following format:

Format for UDP packets sent to the data channel socket in order to be accepted by the transceiver module

Once the transceiver receives these packets it will decode and modulate them using GMSK (Gaussian Minimum Shift Keying). Eventually, the bursts will be transmitted to the connected mobile stations accordingly to their contents.

Even if the following products are GSM and UMTS only, the transceiver (which is a standalone component) itself is universal. Chances are that other (proprietary) BTS software uses the very same code base in order to serve LTE connectivity as well.

Affected Products

  • YateBTS <= 5.0.0
  • OpenBTS <= 4.0.0
  • OpenBTS-UMTS <= 1.0.0
  • Osmo-TRX/Osmo-BTS <= 0.1.10
  • Other products that share the same transceiver code base.


Issue 1: Overly Exposed Service Binding


There’s a bug in the network library of the aforementioned products which makes the transceiver UDP sockets bind to INADDR_ANY instead of the user configured value ( by default). This allows any attacker with IP connectivity to the BTS system to receive and send packets from/to the transceiver. Moreover, access to the services exposed on these UDP network sockets is not protected by any authentication mechanism whatsoever.

The three transceiver sockets bound to

Figure 3: The three transceiver sockets bound to


An attacker with IP connectivity could send UDP traffic to exercise any functionality provided. This could allow remote control takeover, GSM traffic hijacking, various information disclosure, DoS, or worse.


The root cause of this vulnerability (and the reason why the following vulnerabilities can be reached remotely) can be found in the UDPSocket constructor and the UDPSocket::open method in the source file CommonLibs/Sockets.cpp. This source file is present in all affected products. The following excerpt shows the vulnerable code.

256 UDPSocket::UDPSocket(unsigned short wSrcPort,
 257 const char * wDestIP, unsigned short wDestPort )
 258 :DatagramSocket()
 259 {
 260 open(wSrcPort);
 261 destination(wDestPort, wDestIP);
 262 }
 266 void UDPSocket::destination( unsigned short wDestPort, const char * wDestIP )
 267 {
 268 resolveAddress((sockaddr_in*)mDestination, wDestIP, wDestPort );
 269 }

In the above snippet we can see that the desired bind address is saved into the mDestination class member variable, but here’s how the UDPSocket::open method is implemented:

271 address.sin_family = AF_INET;
 272 address.sin_addr.s_addr = INADDR_ANY;
 273 address.sin_port = htons(localPort);
 274 if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {

Despite the fact that the UDPSocket class provides a constructor argument to specify the address to which to bind the server, this information is ignored. As show on line 272, the socket is bound to INADDR_ANY instead of using the mDestination address variable.

Issue 2: Remote Stack-Based Buffer Overflow


An attacker can overflow a stack buffer by sending an oversized UDP packet to the control channel.


An attacker may be able to achieve remote code execution (RCE) or cause a denial of service (DoS) condition.


The control channel is handled by the Transceiver::driveControl method in the Transceiver.cpp source file. The first lines follow.

694 void Transceiver::driveControl(size_t chan)
695 {
696   int MAX_PACKET_LENGTH = 100;
698   // check control socket
699   char buffer[MAX_PACKET_LENGTH];
700   int msgLen = -1;
701   buffer[0] = '';
703   msgLen = mCtrlSockets[chan]->read(buffer);

Note that the packet buffer, which resides on the method’s stack, is defined to be 100 bytes (from MAX_PACKET_LENGTH).

If we analyze the DatagramSocket::read method (the DatagramSocket class is the parent class of UDPSocket) declared in the Sockets.cpp source file, we see the following.

194 int DatagramSocket::read(char* buffer)
195 {
196   socklen_t temp_len = sizeof(mSource);
197   int length = recvfrom(mSocketFD, (void*)buffer, MAX_UDP_LENGTH, 0,

Here we see that MAX_UDP_LENGTH bytes are read instead of MAX_PACKET_LENGTH. This value is defined in the Sockets.h file as follows.

#define MAX_UDP_LENGTH 1500 /* (or 8000 for OpenBTS-UMTS) */

Therefore, it’s possible to cause a stack overflow in the transceiver process simply by sending a UDP packet larger than 100 bytes. Figure 4 shows the result of a debugging session when this occurs.


Figure 4: Segmentation fault caused by a large UDP packet.


  1. RCE can be mitigated when the appropriate flags are applied in compile time. History shows that these mitigations can be bypassed given the right vulnerability or chain of vulnerabilities (e.g. with an infoleak). Furthermore, since this software is compiled by various parties, it is likely that some of these builds do not contain sufficient mitigations (ASLR, Stack canaries, etc).
  2. If there is no impact or usage of the transceiver interface, we advise blocking this port from external connections on the firewall.

Issue 3: Remote Unauthenticated Control


The control channel does not implement any type of authentication. Since it is exposed to the outer network due to Issue 1, this fact can be used by any malicious party to control the transceiver module remotely.


An attacker could…

  • …deny service by turning the module off.
  • …jam frequencies by tuning the TX radio to the wrong frequency.
  • …hijack BTS identity remotely using the SETBSIC command to change the BTS identity to another one.


The control channel implements a simple text over UDP protocol handled by the Transceiver::driveControl method in the Transceiver.cpp source file. Some of the features this protocol exposes include (remember, there is no authentication):

  • Turning the TRX module on or off: CMD POWERON / CMD POWEROFF
  • Tuning the TRX to other frequencies: CMD RXTUNE frequency / CMD TXTUNE frequency
  • Setting the GSM cell identity: CMD SETBSIC value

An attacker can execute such commands (and others) by simply sending UDP packets to port 5701 of the server. The full protocol specification can be found inside the TRXManager/README.TRXManager file.

Conclusions, Additional Mitigations & Recommendations:

We’ve demonstrated how the complete lack of any form of authentication and code bugs make the aforementioned BTS products vulnerable to a wide range of attack.

We highly recommend vendors to apply the following mitigations in order to make their products safer:

  1. Update your BTS software when a patch is available.
  2. Bind the sockets used for control and data exchange only to the local interface (
  3. Firewall: Block traffic coming from external networks to ports 5701 ( control port ) and 5702 ( data port), or other ports as used by your BTS software.
  4. Be sure to apply compile time mitigations (ASLR + DEP)
  5. Implement an authentication system for such channels to deny an unprivileged attacker logged on the same machine, or on the same network, from communicating with BTS control ports.
  6. Fix buffer handling by using correct sizes.
  7. Perform additional code audits.

For security and mobility professionals concerned about implications of similar attacks to corporate or BYOD devices, consider leveraging a Mobile Threat Prevention solution such as Zimperium zIPS to detect active manipulation by an unauthorized third party.

Disclosure Timeline

  • 26 April 2016: Initial disclosure email sent to vendors.
  • 29 April 2016: Contact from OsmoBB
  • 30 April 2016 : OsmoBB: follow up
  • 06 May 2016: Initial notification to Zimperium Handset Alliance (ZHA).
  • 06 May 2016: OpenBTS: bugs fixed [1] [2]
  • 07 June 2016: Follow up with vendors
  • 07 June 2016: OsmoBB: bug fixed
  • 06 July 2016: Release to ZHA partners
  • 06 July 2016: OpenBTS: Reverted overflow fix (!!) [3]
  • 13 July 2016: OpenBTS: Reverted bind fix (!!) [4]
  • 10 August 2016 : Commented on both “Why are you deliberately reintroducing severe security issues in your software?” (OpenBTS)
  • 15 August 2016: OpenBTS – Follow up, no response
  • 23 August 2016: Public Disclosure
Avatar photo
Author: zLabs

Get started with Zimperium today