Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/metasploit/framework/login_scanner/postgres.rb
28052 views
1
require 'metasploit/framework/login_scanner/base'
2
require 'postgres_msf'
3
4
module Metasploit
5
module Framework
6
module LoginScanner
7
8
# This is the LoginScanner class for dealing with PostgreSQL database servers.
9
# It is responsible for taking a single target, and a list of credentials
10
# and attempting them. It then saves the results.
11
class Postgres
12
include Metasploit::Framework::LoginScanner::Base
13
14
# @!attribute ssl
15
# @return [Boolean] Whether the connection should use SSL
16
attr_accessor :ssl
17
# @!attribute ssl_version
18
# @return [String] The version of SSL to implement
19
attr_accessor :ssl_version
20
# @!attribute ssl_verify_mode
21
# @return [String] the SSL certification verification mechanism
22
attr_accessor :ssl_verify_mode
23
# @!attribute ssl_cipher
24
# @return [String] The SSL cipher to use for the context
25
attr_accessor :ssl_cipher
26
# @!attribute max_send_size
27
# @return [Integer] The max size of the data to encapsulate in a single packet
28
attr_accessor :max_send_size
29
# @!attribute send_delay
30
# @return [Integer] The delay between sending packets
31
attr_accessor :send_delay
32
33
# @returns [Boolean] If a login is successful and this attribute is true - a Msf::Db::PostgresPR::Connection instance is used as proof,
34
# and the socket is not immediately closed
35
attr_accessor :use_client_as_proof
36
37
DEFAULT_PORT = 5432
38
DEFAULT_REALM = 'template1'
39
LIKELY_PORTS = [ DEFAULT_PORT ]
40
LIKELY_SERVICE_NAMES = [ 'postgres' ]
41
PRIVATE_TYPES = [ :password ]
42
REALM_KEY = Metasploit::Model::Realm::Key::POSTGRESQL_DATABASE
43
44
# This method attempts a single login with a single credential against the target
45
# @param credential [Credential] The credential object to attempt to login with
46
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
47
def attempt_login(credential)
48
result_options = {
49
credential: credential,
50
host: host,
51
port: port,
52
protocol: 'tcp',
53
service_name: 'postgres'
54
}
55
56
db_name = credential.realm || 'template1'
57
58
if ::Rex::Socket.is_ipv6?(host)
59
uri = "tcp://[#{host}]:#{port}"
60
else
61
uri = "tcp://#{host}:#{port}"
62
end
63
64
pg_conn = nil
65
66
begin
67
ssl_opts = {}
68
ssl_opts[:ssl_version] = ssl_version if ssl_version
69
ssl_opts[:ssl_verify_mode] = ssl_verify_mode if ssl_verify_mode
70
ssl_opts[:ssl_cipher] = ssl_cipher if ssl_cipher
71
72
pg_conn = Msf::Db::PostgresPR::Connection.new(
73
db_name,
74
credential.public,
75
credential.private,
76
uri,
77
proxies,
78
ssl,
79
ssl_opts
80
)
81
rescue ::RuntimeError => e
82
case e.to_s.split("\t")[1]
83
when "C3D000"
84
result_options.merge!({
85
status: Metasploit::Model::Login::Status::INCORRECT,
86
proof: "C3D000, Creds were good but database was bad"
87
})
88
when "C28000", "C28P01"
89
result_options.merge!({
90
status: Metasploit::Model::Login::Status::INCORRECT,
91
proof: "Invalid username or password"
92
})
93
else
94
result_options.merge!({
95
status: Metasploit::Model::Login::Status::INCORRECT,
96
proof: e.message
97
})
98
end
99
rescue Rex::ConnectionError, Rex::ConnectionProxyError, Errno::ECONNRESET, Errno::EINTR, Errno::ENOTCONN, Rex::TimeoutError, EOFError, Timeout::Error => e
100
result_options.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
101
rescue Msf::Db::PostgresPR::AuthenticationMethodMismatch => e
102
result_options.merge!({
103
status: Metasploit::Model::Login::Status::INCORRECT,
104
proof: e.message
105
})
106
end
107
108
if pg_conn
109
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
110
111
# This module no longer owns the socket so return it as proof so the calling context can perform additional operations
112
# Additionally assign values to nil to avoid closing the socket etc automatically
113
if use_client_as_proof
114
result_options[:proof] = pg_conn
115
result_options[:connection] = pg_conn.conn
116
else
117
pg_conn.close
118
end
119
else
120
result_options[:status] = Metasploit::Model::Login::Status::INCORRECT
121
end
122
123
::Metasploit::Framework::LoginScanner::Result.new(result_options)
124
end
125
126
def set_sane_defaults
127
self.connection_timeout ||= 30
128
self.port ||= DEFAULT_PORT
129
self.max_send_size ||= 0
130
self.send_delay ||= 0
131
end
132
133
end
134
end
135
end
136
end
137
138