CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/exploit/pgadmin.rb
Views: 18091
1
# -*- coding: binary -*-
2
3
#
4
# This mixin provides helpers to interact with pgAdmin. It provides methods to:
5
# - authenticate
6
# - obtain the CSRF token,
7
# - check the version of pgAdmin.
8
#
9
module Msf
10
module Exploit::PgAdmin
11
include Msf::Exploit::Remote::HttpClient
12
13
def get_version
14
res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'login'), 'keep_cookies' => true)
15
return unless res&.code == 200
16
17
html_document = res.get_html_document
18
return unless html_document.xpath('//title').text == 'pgAdmin 4'
19
20
versioned_link = html_document.xpath('//link').find { |link| link['href'] =~ /\?ver=(\d?\d)(\d\d)(\d\d)/ }
21
return unless versioned_link
22
23
set_csrf_token_from_login_page(res)
24
Rex::Version.new("#{Regexp.last_match(1).to_i}.#{Regexp.last_match(2).to_i}.#{Regexp.last_match(3).to_i}")
25
end
26
27
def check_version(patched_version, low_bound = 0)
28
version = get_version
29
return Msf::Exploit::CheckCode::Unknown('Unable to determine the target version') unless version
30
return Msf::Exploit::CheckCode::Safe("pgAdmin version #{version} is not affected") if version >= Rex::Version.new(patched_version) || version < Rex::Version.new(low_bound)
31
32
Msf::Exploit::CheckCode::Appears("pgAdmin version #{version} is affected")
33
end
34
35
def csrf_token
36
return @csrf_token if @csrf_token
37
38
res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'login'), 'keep_cookies' => true)
39
set_csrf_token_from_login_page(res)
40
fail_with(Msf::Exploit::Failure::UnexpectedReply, 'Failed to obtain the CSRF token') unless @csrf_token
41
@csrf_token
42
end
43
44
def set_csrf_token_from_login_page(res)
45
if res&.code == 200 && res.body =~ /csrfToken": "([\w+.-]+)"/
46
@csrf_token = Regexp.last_match(1)
47
elsif (element = res.get_html_document.xpath("//input[@id='csrf_token']")&.first)
48
@csrf_token = element['value']
49
end
50
end
51
52
def authenticate(username, password)
53
res = send_request_cgi({
54
'uri' => normalize_uri(target_uri.path, 'authenticate/login'),
55
'method' => 'POST',
56
'keep_cookies' => true,
57
'vars_post' => {
58
'csrf_token' => csrf_token,
59
'email' => username,
60
'password' => password,
61
'language' => 'en',
62
'internal_button' => 'Login'
63
}
64
})
65
66
unless res&.code == 302 && res&.headers&.[]('Location') != normalize_uri(target_uri.path, 'login')
67
fail_with(Msf::Exploit::Failure::NoAccess, 'Failed to authenticate to pgAdmin')
68
end
69
70
print_good('Successfully authenticated to pgAdmin')
71
res
72
end
73
end
74
end
75
76