CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/metasploit/framework/login_scanner/postgres.rb
Views: 1904
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
# @returns [Boolean] If a login is successful and this attribute is true - a Msf::Db::PostgresPR::Connection instance is used as proof,
15
# and the socket is not immediately closed
16
attr_accessor :use_client_as_proof
17
18
DEFAULT_PORT = 5432
19
DEFAULT_REALM = 'template1'
20
LIKELY_PORTS = [ DEFAULT_PORT ]
21
LIKELY_SERVICE_NAMES = [ 'postgres' ]
22
PRIVATE_TYPES = [ :password ]
23
REALM_KEY = Metasploit::Model::Realm::Key::POSTGRESQL_DATABASE
24
25
# This method attempts a single login with a single credential against the target
26
# @param credential [Credential] The credential object to attempt to login with
27
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
28
def attempt_login(credential)
29
result_options = {
30
credential: credential,
31
host: host,
32
port: port,
33
protocol: 'tcp',
34
service_name: 'postgres'
35
}
36
37
db_name = credential.realm || 'template1'
38
39
if ::Rex::Socket.is_ipv6?(host)
40
uri = "tcp://[#{host}]:#{port}"
41
else
42
uri = "tcp://#{host}:#{port}"
43
end
44
45
pg_conn = nil
46
47
begin
48
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri,proxies)
49
rescue ::RuntimeError => e
50
case e.to_s.split("\t")[1]
51
when "C3D000"
52
result_options.merge!({
53
status: Metasploit::Model::Login::Status::INCORRECT,
54
proof: "C3D000, Creds were good but database was bad"
55
})
56
when "C28000", "C28P01"
57
result_options.merge!({
58
status: Metasploit::Model::Login::Status::INCORRECT,
59
proof: "Invalid username or password"
60
})
61
else
62
result_options.merge!({
63
status: Metasploit::Model::Login::Status::INCORRECT,
64
proof: e.message
65
})
66
end
67
rescue Rex::ConnectionError, Rex::ConnectionProxyError, Errno::ECONNRESET, Errno::EINTR, Errno::ENOTCONN, Rex::TimeoutError, EOFError, Timeout::Error => e
68
result_options.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
69
rescue Msf::Db::PostgresPR::AuthenticationMethodMismatch => e
70
result_options.merge!({
71
status: Metasploit::Model::Login::Status::INCORRECT,
72
proof: e.message
73
})
74
end
75
76
if pg_conn
77
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
78
79
# This module no longer owns the socket so return it as proof so the calling context can perform additional operations
80
# Additionally assign values to nil to avoid closing the socket etc automatically
81
if use_client_as_proof
82
result_options[:proof] = pg_conn
83
result_options[:connection] = pg_conn.conn
84
else
85
pg_conn.close
86
end
87
else
88
result_options[:status] = Metasploit::Model::Login::Status::INCORRECT
89
end
90
91
::Metasploit::Framework::LoginScanner::Result.new(result_options)
92
end
93
end
94
95
def set_sane_defaults
96
self.connection_timeout ||= 30
97
self.port ||= DEFAULT_PORT
98
end
99
100
end
101
end
102
end
103
104