Accounts for mobile applications are often bound to phone numbers and working with multiple people on a project may make it necessary at some point to share mobile phone numbers for receiving SMS. Also, when testing mobile applications protected by a SMS-based second-factor authentication, sharing phone numbers among the testing team is sometimes necessary and also acceptable regarding security, when the scope is only a test system. At Pentagrid, we therefore operate a small SMS Gateway, which we hereby publish as open source.
If SMS is the second authentication factor, the target system sends an SMS to a mobile phone and then the auditor enters the token manually into the web-browser. While this is still somehow convenient for regular work, it is quite ineffective during a penetration test, especially when the server side invalidates the session every now and then, because the tested application does not like the input and just rejecting the HTTP request was not deemed sufficient enough for the software developers. And when a system is not designed to be tested with semi-automated tools such as the Burp Proxy, often enough 2FA couldn’t be just deactivated for certain test accounts even in a dedicated test environment. To be able to still test such a system, it is useful to bring the second factor into the Burp Proxy.
There are many commercial SMS gateways that provide an API for sending and receiving SMS. However, since the token is an authentication factor, even if only a part of the whole process, sharing this sensitive information with third parties is not an option, even for test systems. For this reason, we implemented an SMS gateway to avoid as much third-party infrastructure in between as possible.
There are a few SMS forwarding applications that, once installed on a mobile phone, will forward incoming SMS, usually to a destination E-mail address. This works, but the method has drawbacks. It increases dependencies and one has to additionally trust the application developer, the E-mail provider (if one relies on an external party for this), and in the end also other applications running on the mobile phone - at least to a certain degree. The approach additionally does not scale well. Generally, a phone may house up to two physical SIM cards. For three or more SIM cards additional phones would be required. Furthermore, service monitoring is not really supported. To check if the forwarding application is still working, the almost only way to test this is an end-to-end check, which includes sending an SMS and checking if the SMS was finally delivered to a destination.
To overcome these drawbacks, we implemented an SMS gateway with the main purpose of receiving SMS. It is also possible to send SMS, which could be used for sending server monitoring alarm messages, but this was not the focus.
In this initial release, the SMS gateway provides the following features:
Manage a batch of modems
Receive and send SMS
Forwarding of received SMS to E-mail
Be able to pull SMS or send SMS via an XMLRPC service
Support for sending Unstructured Supplementary Service Data (USSD) codes to top up prepaid SIM cards
Support for TLS
Icinga2/Nagios integration for deep checks
Munin integration for a few stats
Implementation and operation mode
The SMS gateway is implemented as a Python program for Linux. The module python-gsmmodem interfaces the modem and handles modem commands. Therefore, each modem runs in its own thread. Multiple modems are grouped as a modem pool, which allows us to operate multiple SIM cards in parallel. The modem pool monitors each modem’s health state, which includes the serial connection to the modem, the signal strength, and the account’s balance for pre-paid SIM cards. Furthermore, the modem pool tries to re-initialize modems in case of problems.
When a modem receives an SMS, it is put into an internal queue. A remote client fetches the SMS via an API provided by an XMLRPC server integrated into the SMS gateway, which is based on the network engine Twisted. Alternatively, the SMS gateway is able to deliver incoming SMS via SMTPS to a destination mailbox. The SMS forwarding via SMTPS is also monitored as a health check. If there are is a problem with SMTPS connection, the health check subsequentially fails.
Remote XMLRPC clients may interact with the XMLRPC server. A client can fetch a received SMS. The API is kept simple and there is no user management. Instead, the XMLRPC server authorizes operations based on API token the client passes as parameter when calling remote API functions. The server has the API token stored as a hash in a configuration file and checks it when deciding whether or not to authorize an operation. There are API token for generally fetching SMS, for fetching SMS for individual modems, for sending Unstructured Supplementary Service Data (USSD) codes, for sending SMS, for retrieving an SMS delivery status, and for monitoring and statistics purposes.
The SMS gateway is shipped with a Munin and an Icinga/Nagios plugin to support monitoring, when the solution is operated. The monitoring plugins are implemented as XMLRPC clients that retrieve health information respectively statistics from the XMLRPC server.
The SMS gateway also supports sending SMS. But when other people are allowed to send SMS, nothing stops them from sending messages to expensive service lines and changing booking options. Therefore, sending SMS can be restricted via an allowed destinations prefix list.
Set up an own installation
We published the SMS gateway’s source code on Github along with further documentation how to set up such a gateway. It should support many 2G/3G/4G/5G modems. In a simple case, you could use these plastic USB modem sticks that are sometimes called "surfstick" or similar.
How you can use the SMS gateway in an automated way with Portswigger's Burp Suite so you don't have to type the 2FA anymore is explained in the blog post Burp Suite - solving E-mail and SMS TAN multi-factor authentication with Hackvertor custom tags.