In this blog post, we’re going to setup our own callcenter to spoof any phone number on the fly!
What we’re doing today, is nothing new - but it is documented horribly. The blogs from Rapid7 regarding this topic, helped me tremendously - you may find them in the references below. Most of the code is based on those blogs. I merely adjusted and tested them for the Dutch providers.
Sometimes I have the idea this lack of information, is a symptom of security through obsecurity. Instead of improving security, we just try to hide the fact how broken it has been and currently still is. I’ve always hated the counterproductive sense of false security it creates. This is also why I don’t mind creating a blog post like this. It is better to be aware of the ease of which you can do this, and try to do something about it.
But let’s leave that debate for another time, how does this work and how do you set it up?
How does it work
The current process of spoofing a number interactively goes like this;
- Call your VOIP number, e.g. 08512345678
- Provide the PIN you configured, wait for the beep
- Press 1 to go into the menu, wait for the welcome tune
- Enter the number you want to spoof, e.g. 31612345678 - wait for the call tune
- Enter the number you want to call, e.g. 31611223344 - wait for the call tune
- You’re calling… enjoy.
The overview of this setup is as follows;
- For the VOIP services, I use CM.
- Great service, easy to use. Documenation and configuration does lack, but I provide it in this blog post.
- Costs are low, you buy a phone number for around 15EUR - and calling costs are cents per minute.
- For the callcenter itself, I use a VPS (10USD per month) on DigitalOcean, running FreePBX.
How do you defend against this?
Short answer, you can’t. Awareness does help in recognizing potential fraudulent callers.
The protocols that are being used, are inherently insecure - and have been for a long time. There are ways to e.g. block the spoofing of phone numbers - but only the providers themselves can do this. Some actually do, but most don’t and won’t. There are actual legitimate usecases for this, think of the telephones in the office that all call from the same number - that uses the same technique. And even if a provider blocks it, there are always providers that allow it. During testing, I also used USA providers that worked - you can route your calls all around the world if you want.
Same goes for SMS, but I’ll go over that in another blog post. I personally have a Telegram bot that can send SMS messages on the fly - spoofing not only the phone number, but also the id. For context, the id can be e.g. “ING”.
How do you set it up
CM.com | DigitalOcean (FreePBX) | |
---|---|---|
1 | Create your account | |
2 | Dump some money 20-30EUR | |
3 | Create your account | |
4 | Dump some money 20-30EUR | |
5 | Create a VPS (droplet), based on the FreePBX business app and don’t forget to set a proper password (as it’s connected to the internet lol) | |
6 | Set up a distribution group, and set the IP of your VPS and port 5060 | |
7 | Buy a number | |
8 | Configure the number to use the created distribution group, you may leave the other settings | |
9 | Create a SIP trunk | |
10 | Configure the SIP trunk by adding the VPS IP with port 5060 to the IP addresses section of your trunk | |
11 | Make sure the trunk is using Rijen and Breda | |
12 | Configure your DISA, and set a PIN - this PIN is used in the call menu and prevents abuse by unauthorized actors | |
13 | Configure an inbound route, with the destination being your created DISA | |
14 | Configure an outbound route, and only set the dial patterns as showed | |
15 | Configure the trunk. Use a consistent name for the trunk, as well as the outgoing trunk name. You may use the code samples below for the incoming and outgoing configuration. Make sure you replace the REPLACE_ME values. For the incoming configuration, the fromuser should equal the number you bought and own. Example; fromuser=318512345678. The USER Context needs to be from-trunk. For the outgoing configuration, the username and secret equal the credentials you can find in the CM trunk settings page. | |
16 | Configure the extensions_custom.conf. This is where the magic happens. You can just copy paste it, but make sure to replace the REPLACE_ME with the outgoing trunk name you set. |
VPS;
Inbound route;
Outbound route;
DISA;
extensions_custom.conf:
[from-internal-custom]
include => proof-of-concept-custom
[proof-of-concept-custom]
exten => 1,1,Answer
exten => 1,n,Wait(2)
exten => 1,n,Playback(welcome)
exten => 1,n(collect),Read(digito,,14)
exten => 1,n,Set(CALLERID(number)=${digito})
exten => 1,n,Set(CDR(outbound_cnum)=${digito})
exten => 1,n,Answer
exten => 1,n,Wait(2)
exten => 1,n,Playback(call)
exten => 1,n(collect),Read(digito1,,14)
exten => 1,n,Set(OUTBOUND_GROUP=OUT_3)
exten => 1,n,Playback(call)
exten => 1,n,Dial(SIP/REPLACE_ME/${digito1},300)
Incoming trunk config:
host=31.169.58.10&31.169.58.11&188.94.185.98&188.94.185.99&188.94.185.110
disallow=all
type=peer
allow=alaw&ulaw
canreinvite=yes
context=from-trunk
dtmfmode=rfc2833
insecure=invite,port
nat=no
pedantic=no
port=5060
qualify=yes
fromuser=REPLACE_ME
trustrpid=yes
sendrpid=pai
Outgoing trunk config:
username=REPLACE_ME
secret=REPLACE_ME
host=31.169.63.1&31.169.63.2
disallow=all
type=peer
allow=alaw&ulaw
canreinvite=yes
context=from-trunk
dtmfmode=rfc2833
insecure=invite,port
nat=yes
pedantic=no
port=5060
qualify=yes
trustrpid=yes
sendrpid=pai