Hacker makes international calls through my FreePBX IVR

I am running:
FreePBX 12.0.76.2
Asterisk 11.18.0
FreePBX 64bit distro 6.12.65

I have many POTS lines for incoming and outgoing calls, and a Twilio SIP trunk for outbound International calls.

I just had repeated calls from three different caller IDs from southern California that attempted to call many internal extensions in our company. Employees receiving the call would hear an “underwater garble of digital tones” and then a hangup. Then these callers discovered some way to dial hundreds of dollars of international calls being made through both my Twilio and my local POTS lines. Destinations were Burkina Faso and Philippines mobile numbers (about three of them called repeatedly, some successful for 15 minutes, some 4 minutes and most were not answered).

I saw there was a vulnerability into the AMI, but I’ve had that patched since the patch came out.

I blacklisted the phone numbers that were calling in (using the blacklist module) and this stopped the calls. But I still don’t know what vulnerability they managed to exploit.

In the CDR I do see the context they seem to be using when they make the outbound calls, “macro-dial-one” and then “from-internal-xfer” or “from-trunk-sip-TwilioTrunkOutB”.

This same thing happened to our old FreePBX that was running PIAF v1.2.9, Asterisk 1.4.21.2, except they seemed to take advantage of a Misc Destination to a cell phone (since removed) that somehow allowed them to call international numbers from our system. So it doesn’t seem to be related to any remote code execution or escalation of privilages. It is some IVR exploit.

Any ideas how this could happen? I have google searched every combination I can and have not seen any mentions of this exploit.

Allowing T in your “Asterisk dial options” allows a caller to “hook-flash” on dahdi call and transfer the call to anything you allow.

1 Like

I’ll bet @dicko is right.

They dial into your IVR, press the * to dial a voicemail extension or just dial a direct extension number, then transfer the call to a number your system allows.

The other possibility is that they have discovered an extension with a weak password and are dialing out through that.

If you feel that allowing direct transfers from the IVR is a good idea, I recommend you change your outbound routes to require a passcode. That will narrow your problems down some.

You need to shut down either the exploit or your long-distance lines ASAP - the guys that used your phones for long distance are getting ready to sell this to HUNDRED of VOIP corksuckers.

1 Like

Should the “T” be removed from all the trunks? It looks like it is there by default.

Then any caller can “transfer the call” with ## by default, if it is answered, DAHDI also allows a hook flash to transfer, so it is your call if you want to allow that. Personally I would say that is a questionable default, you would probably be safe in the from-pstn context, but if you allow tunneling down , whoops . . . try it . . .

Thanks. I’ll have to think about it. No DAHDI, but still.

Doesn’t sound like there is a reason for a caller to transfer a call. I have IVRs but that isn’t technically a transfer in this sense, is it?

No. I can’t think of a reason why a caller should be allowed to unilaterally transfer a call. I don’t.

A long time ago it cost me $13000 over a weekend via a badly configured voicemail system. Once bitten . . .

Thanks. I’ll make the change and test things out. In process of starting from scratch to bring everything up to latest. I do it every few years. Yes, I do keep patches applied. But a good cleanup is sometimes a nice thing.

I do have my trunks all set at the provider to disallow costly outbound calls, hopefully that keeps my exposure limited, but better safe…

Resolved!!!

Thank you for the tips guys.

When I turned on DTMF under “FreePBX web gui / Settings / Asterisk Log File Settings” which saves in Asterisk’s /var/log/asterisk/full.log, I caught the offender dialing random extensions until they got a valid one, and the moment an employee picked up, they dialed *2 (In-Call Asterisk Attended Transfer), which is intended for our employees to dial. the moment the offender dials *2, Asterisk gives them control of transferring the call (whereupon they can dial out any number they wish), giving our employee silence and then a hangup, and the offender continues with his international (free) call, and once that call is done they hit *2 again and dial another international call.

Ouch. How painful.

Solution 1: So in “FreePBX web gui / Admin / Feature Codes” you can disable *2 and ## (and any other useless feature codes that could possibly be taken advantage of by a bot).

Solution 2: In “FreePBX web gui / Settings / Advanced Settings / Dialplan and Operational / Asterisk Dial Options & Asterisk Outbound Trunk Dial Options” you can remove “Tt” on both and leave the first one with “r” (which edits the defaults on every trunk… unless you bypassed this on any trunk). And make sure to push the green check mark next to each and hit the big red “Apply Config”. I tested re-enabling the *2 and ## features, and this change cut them off as well.

I chose to apply both solutions.

Thanks guys for your help and I hope this helps anyone else being hacked with toll fraud, redialing, war dialing, or whatever they are calling this. And to hell with the fraud calling card companies or hackers using this vulnerability!

2 Likes

itdeptia Great find, I just check my Freepbx13/Asterisk13 system and I could make outbound calls using *2

I can’t believe Freepbx left such a big hole in system security with default settings, this could cost people Thousands of dollars if left unchecked.

Thanks,
Gary.

Hi itdeptia
Thanks, that saved our life :smiley:

I tried it this moment and could not believe it. I pressed *2 on my cell phone and called any number i liked.

I disabled only the feature codes because without Tt i have problems with calls.( If i call any cell phone i cannot hear “caller is busy” from the cell provider anymore…my phone on the pbx still let me hear a ring signal and doesnt recognize this anymore if i only enable “r” in trunk dial options.

http://issues.freepbx.org/browse/FREEPBX-12058

Guys. This dial plan code has been around since day 1. I am not negating what you are saying. But it’s fully configurable and isn’t a security vulnerability by any means.

The problem is two fold. You can change these settings under Advanced Settings under “Asterisk Dial Options” and “Asterisk Outbound Trunk Dial Options”. By modifying the “T” (Allow the calling party to transfer the called party) and “t” (Allow the called party to transfer the calling party) values (read the descriptions). The problem is how calls work. If you remove “t” or “T” then you will possibly break how transferring works on your local extensions as in removing “Tt” from advanced settings you won’t be able to use ## or *2 any more even if the feature codes are enabled.

This is not anything “new” (It’s in FreePBX since at least 2.5). Let’s all take a step back and breathe and come up with a solution instead of instantly saying it’s a security hole.

I encourage you to open a ticket next time.

As someone who has experienced this “penetration” (and here recently identified it) I would have to say that “T” is a horrible default and obviously a “security hole”, obviously I don’t allow it as stated , but that is after all what is the default and has been since asterisk@home , Obviously “T” will allow the caller to transfer, there is a valid argument for “t” but . . . please absolutely all take a step back and look at the likelihood of needing it and the possible expense of allowing it . . . .

2 Likes

We’re not denying it’s a bad default. @tm1000 and I have been on the phone about it, and we agree it needs a better default.

He’s having a think and experimenting with various ways to manage it. The problem is that ‘Tt’ is used in lots of OTHER situations where people expect it to work, but the one situation where you DON’T want it to work is also pretty major too.

There’s a ticket open, I think it’s linked above, so if you’re interested, click ‘watch’ on the ticket and you’ll get updates as it happens.

hehe

This issue can’t be viewed
The issue you’re trying to view can’t be displayed.
It may have been deleted or you don’t have permission to view it right now.

There’s nothing to see in that issue except for more “the sky is falling” basically a rehash of this thread but with more emphasis on how horrible this is.

Edit: Also I just realized that the OP of this thread opened a duplicate up on Monday and when asked for feedback provided nothing. The OP of this thread is the owner of the original ticket.

MY sky does not fall, but the default causes a rift in the sky for many, add a trunk/inbound route specific dial option and sanitize the default and everyone will stop panicking :wink:

Here is a quick fix for anyone wanting to test a solution that will block transferring when a party dials externally into the system. You can leave your defaults as is in “Advanced Settings”. This just removes the “T” option when a call is processed through any inbound route

diff --git a/agi-bin/dialparties.agi b/agi-bin/dialparties.agi
index 38782fd..6d9341b 100644
--- a/agi-bin/dialparties.agi
+++ b/agi-bin/dialparties.agi
@@ -705,6 +705,9 @@ if (!strlen($ds)) {
                        $ds .= $timer;
                }
                $ds .= $ds_seperator . $dialopts; // pound to transfer, provide ringing
+               $dir = get_var( $AGI, "DIRECTION" );
+               //dont allow inbound callers to transfer around inside the system
+               $ds = ($dir == "INBOUND") ? str_replace("T","",$ds) : $ds;
                $AGI->set_variable('ds',$ds);
                $AGI->set_variable("HuntMembers",$loops);
                $AGI->set_priority("huntdial"); // dial command was at priority 20 where dialplan handles calling a ringgroup with strategy of "hunt" or "MemoryHunt"
@@ -728,6 +731,9 @@ if (!strlen($ds)) {
                                $AGI->set_variable('__CALLCONFIRMCID',"999");
                        }
                }
+               $dir = get_var( $AGI, "DIRECTION" );
+               //dont allow inbound callers to transfer around inside the system
+               $ds = ($dir == "INBOUND") ? str_replace("T","",$ds) : $ds;
                $AGI->set_variable('ds',$ds);
                $AGI->set_priority("normdial"); // dial command was at priority 10
        }
diff --git a/functions.inc.php b/functions.inc.php
index 13a3872..1db5f27 100644
--- a/functions.inc.php
+++ b/functions.inc.php
@@ -1227,6 +1227,8 @@ function core_do_get_config($engine) {
                $ext->addInclude('from-internal-additional', $context); // Add the include from from-internal
                $exten = '_LC-.';
                $ext->add($context, $exten, '', new ext_noop_trace('IN '.$context.' with - RT: ${RT}, RG_IDX: ${RG_IDX}'));
+               //dont allow inbound callers to transfer around inside the system
+               $ext->add($context, $exten, '', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,T)}I'));
                $ext->add($context, $exten, '', new ext_dial('${DB(DEVICE/${EXTEN:3}/dial)}', '${RT},${DIAL_OPTIONS}M(auto-confirm^${RG_IDX})b(func-apply-sipheaders^s^1)'));

                /* This needs to be before outbound-routes since they can have a wild-card in them
@@ -1507,6 +1509,7 @@ function core_do_get_config($engine) {
                                $exten = (($exten == "")?"s":$exten);
                                $exten = $exten.(($cidnum == "")?"":"/".$cidnum); //if a CID num is defined, add it

+                               $ext->add($context, $exten, '', new ext_setvar('__DIRECTION','INBOUND'));
                                if ($cidroute) {
                                        $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
                                        $ext->add($context, $exten, '', new ext_goto('1','s'));
diff --git a/functions.inc/macro-dial-one.php b/functions.inc/macro-dial-one.php
index 3a716d3..85912f9 100644
--- a/functions.inc/macro-dial-one.php
+++ b/functions.inc/macro-dial-one.php
@@ -90,6 +90,9 @@ if ($amp_conf['AST_FUNC_CONNECTEDLINE']) {
 //Purpose is to have the option to add sip-headers as with the trunk pre dial out hook.
 //We need to have this as we have mobile extensions connected directly to the pbx as sip extensions.
 $ext->add($mcontext,$exten,'godial', new ext_macro('dialout-one-predial-hook'));
+
+//dont allow inbound callers to transfer around inside the system
+$ext->add($mcontext,$exten,'', new ext_execif('$["${DIRECTION}" = "INBOUND"]', 'Set', 'D_OPTIONS=${STRREPLACE(D_OPTIONS,T)}I'));
 $ext->add($mcontext,$exten,'', new ext_dial('${DSTRING}', '${ARG1},${D_OPTIONS}b(func-apply-sipheaders^s^1)'));
 $ext->add($mcontext,$exten,'', new ext_execif('$["${DIALSTATUS}"="ANSWER" & "${CALLER_DEST}"!=""]', 'MacroExit'));
1 Like

That is not easy at all and could really screw the internals up.