Hacker makes international calls through my FreePBX IVR

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…


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!


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.


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.


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 [email protected] , 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 . . . .


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.


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_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)) {
+               $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_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.

Then I await your complete fix, it has so far WFM, but what do I know :slight_smile:

Thanks though to You and Rob for paying attention here.

It would have been nice if you had mentioned this earlier, you know. We try to have sane defaults. 8-( Is there anything else you haven’t mentioned that we should know about?

@tm1000 has figured out a way to mark a call as coming in from a route and explicitly blocks the ‘T’ right before every Dial command, so there’s no way to allow it (he’s also adding an advanced setting so you can turn that off, if you really want).


Core version 13.0.72