Module: Msf::Exploit::Remote::HTTP::FreePBX

Defined in:
lib/msf/core/exploit/remote/http/freepbx.rb

Overview

Shared routines for FreePBX modules

Instance Method Summary collapse

Instance Method Details

#freepbx_admin_uriString

Get the admin config URI

Returns:

  • (String)

    Admin config URI path



15
16
17
# File 'lib/msf/core/exploit/remote/http/freepbx.rb', line 15

def freepbx_admin_uri
  normalize_uri(target_uri.path, 'admin', 'config.php')
end

#freepbx_get_login_page_data(timeout = 20) ⇒ Hash

Get or create the login page data

Parameters:

  • timeout (Integer) (defaults to: 20)

    Request timeout

Returns:

  • (Hash)

    Hash with :response and :detected keys



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/msf/core/exploit/remote/http/freepbx.rb', line 88

def (timeout = 20)
  return @freepbx_login_page if @freepbx_login_page

  res = send_request_cgi({
    'uri' => freepbx_admin_uri,
    'method' => 'GET',
    'headers' => { 'Referer' => freepbx_referer }
  }, timeout)

  body_lower = res&.body&.downcase || ''
  detected = (res&.code == 200) && (
    body_lower.match?(%r{<title>freepbx\s+administration</title>}) ||
    (body_lower.include?('freepbx administration') && body_lower.include?('loginform')) ||
    body_lower.include?('assets/js/freepbx.js') ||
    body_lower.include?('freepbx-navbar') ||
    (body_lower.match?(/id=["']loginform["']/) && body_lower.include?('freepbx'))
  )

  @freepbx_login_page = {
    response: res,
    detected: detected
  }
end

#freepbx_login(username, password, timeout = 20) ⇒ String?

Authenticate with supplied credentials and return the session cookie

Parameters:

  • username (String)

    FreePBX username

  • password (String)

    FreePBX password

  • timeout (Integer) (defaults to: 20)

    The maximum number of seconds to wait before the request times out

Returns:

  • (String, nil)

    the session cookies as a single string on successful login, nil otherwise



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
72
73
74
75
76
77
78
79
80
81
# File 'lib/msf/core/exploit/remote/http/freepbx.rb', line 39

def (username, password, timeout = 20)
  cache_key = "#{username}:#{password}"
  if @freepbx_auth_cache && @freepbx_auth_cache[cache_key]
    return @freepbx_auth_cache[cache_key]
  end

  data = (timeout)
  res = data[:response]
  return nil unless res

  cookie = res.get_cookies
  return nil if cookie.empty?

   = send_request_cgi({
    'uri' => freepbx_admin_uri,
    'method' => 'POST',
    'cookie' => cookie,
    'headers' => {
      'Referer' => freepbx_referer
    },
    'vars_post' => {
      'username' => username,
      'password' => password
    }
  }, timeout)

  return nil unless 

  body_lower = .body.downcase
  if body_lower.include?('invalid username or password') && body_lower.include?('obe_error')
    @freepbx_auth_cache ||= {}
    @freepbx_auth_cache[cache_key] = :auth_failed
    return :auth_failed
  end

  return nil unless .code == 302 || (.code == 200 && !.body.include?('Login'))

  new_cookie = .get_cookies
  result = new_cookie.empty? ? cookie : new_cookie
  @freepbx_auth_cache ||= {}
  @freepbx_auth_cache[cache_key] = result
  result
end

#freepbx_refererString

Get the Referer header for FreePBX requests

Returns:

  • (String)

    Referer URL



23
24
25
26
27
28
29
30
# File 'lib/msf/core/exploit/remote/http/freepbx.rb', line 23

def freepbx_referer
  host = datastore['RHOSTS'] || rhost
  host = '127.0.0.1' if host == '::1' || host == 'localhost'
  protocol = datastore['SSL'] ? 'https' : 'http'
  default_port = datastore['SSL'] ? 443 : 80
  port_str = (rport == default_port) ? '' : ":#{rport}"
  "#{protocol}://#{host}#{port_str}#{freepbx_admin_uri}"
end