Module: Msf::Exploit::Remote::SIP

Defined in:
lib/msf/core/exploit/remote/sip.rb

Overview

SIP protocol support

Instance Method Summary collapse

Instance Method Details

#create_probe(ip, proto) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/msf/core/exploit/remote/sip.rb', line 73

def create_probe(ip, proto)
  suser = Rex::Text.rand_text_alphanumeric(rand(8) + 1)
  shost = Rex::Socket.source_address(ip)
  src   = "#{shost}:#{datastore['RPORT']}"

  data  = "OPTIONS sip:#{datastore['TO']}@#{ip} SIP/2.0\r\n"
  data << "Via: SIP/2.0/#{proto.upcase} #{src};branch=z9hG4bK.#{format('%.8x', rand(0x100000000))};rport;alias\r\n"
  data << "From: sip:#{suser}@#{src};tag=70c00e8c\r\n"
  data << "To: sip:#{datastore['TO']}@#{ip}\r\n"
  data << "Call-ID: #{rand(0x100000000)}@#{shost}\r\n"
  data << "CSeq: 1 OPTIONS\r\n"
  data << "Contact:  sip:#{suser}@#{src}\r\n"
  data << "Max-Forwards: 20\r\n"
  data << "User-Agent: #{suser}\r\n"
  data << "Accept: application/sdp\r\n"
  data << "Content-Length: 0\r\n"
  data << "\r\n"
  data
end

#report_response(response, rhost, proto, desired_headers = %w(User-Agent Server Allow)) ⇒ Object

Parses response, extracts useful metadata and then reports on it. Returns true iff the response was a valid SIP response



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/msf/core/exploit/remote/sip.rb', line 9

def report_response(response, rhost, proto, desired_headers = %w(User-Agent Server Allow))
  endpoint = "#{rhost}:#{rport} #{proto}"
  begin
    options_response = Rex::Proto::SIP::Response.parse(response)
  rescue ArgumentError => e
    vprint_error("#{endpoint} is not SIP: #{e}")
    return false
  end

  # Extracted headers, stored as a hash where the key is the header name
  # and the value is a list of all values seen for the header, covering the
  # case where the same header value is seen multiple times
  extracted_headers = {}
  unless desired_headers.nil? || desired_headers.empty?
    desired_headers.each do |desired_header|
      next unless (found_header = options_response.header(desired_header))
      extracted_headers[desired_header] ||= []
      extracted_headers[desired_header]  |= found_header
    end
  end

  # Create a SIP OPTIONS fingerprint hash
  fprint = {
    'code'    => options_response.code,
    'message' => options_response.message
  }

  # compact the header values, append the header information to the
  # fingerprint hash
  extracted_headers.each_pair do |k,v|
    value = v.join(',')
    extracted_headers[k] = value
    fprint['header_' + k.gsub('-', '_').downcase] = value
  end

  # Create a summary of the response
  status = options_response.status_line.dup
  unless extracted_headers.keys.empty?
    status << ": #{extracted_headers}"
  end

  # Report the service with the status information
  report_service(
    host: rhost,
    port: rport,
    proto: proto.downcase,
    name: 'sip',
    info: status
  )

  # Report the fingerprint information
  report_note(
    host: rhost,
    port: rport,
    proto: proto.downcase,
    type: "sip.options.fingerprint",
    data: fprint
  )

  # Display the actual result to the user
  print_status(endpoint + " " + status)
  true
end