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/modules/auxiliary/scanner/couchdb/couchdb_login.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::HttpClient
8
include Msf::Auxiliary::Report
9
include Msf::Auxiliary::AuthBrute
10
include Msf::Auxiliary::Scanner
11
12
def initialize(info={})
13
super(update_info(info,
14
'Name' => 'CouchDB Login Utility',
15
'Description' => %{
16
This module tests CouchDB logins on a range of
17
machines and report successful logins.
18
},
19
'Author' =>
20
[
21
'espreto <robertoespreto[at]gmail.com>'
22
],
23
'License' => MSF_LICENSE
24
))
25
26
register_options(
27
[
28
Opt::RPORT(5984),
29
OptString.new('TARGETURI', [false, "TARGETURI for CouchDB. Default here is /", "/"]),
30
OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line",
31
File.join(Msf::Config.data_directory, "wordlists", "http_default_userpass.txt") ]),
32
OptPath.new('USER_FILE', [ false, "File containing users, one per line",
33
File.join(Msf::Config.data_directory, "wordlists", "http_default_users.txt") ]),
34
OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line",
35
File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt") ]),
36
OptBool.new('USER_AS_PASS', [ false, "Try the username as the password for all users", false]),
37
])
38
39
deregister_options('HttpUsername', 'HttpPassword')
40
end
41
42
def run_host(ip)
43
44
user = datastore['HttpUsername'].to_s
45
pass = datastore['HttpPassword'].to_s
46
47
if user.nil? || user.strip == ''
48
each_user_pass do |user, pass|
49
do_login(user, pass)
50
end
51
return
52
end
53
54
vprint_status("#{rhost}:#{rport} - Trying to login with '#{user}' : '#{pass}'")
55
56
uri = target_uri.path
57
58
res = send_request_cgi({
59
'uri' => normalize_uri(uri, '_users/_all_docs'),
60
'method' => 'GET',
61
'authorization' => basic_auth(user, pass)
62
})
63
64
return if res.nil?
65
return if (res.headers['Server'].nil? or res.headers['Server'] !~ /CouchDB/)
66
return if (res.code == 404)
67
68
if [200, 301, 302].include?(res.code)
69
vprint_good("#{rhost}:#{rport} - Successful login with '#{user}' : '#{pass}'")
70
end
71
72
rescue ::Rex::ConnectionError
73
vprint_error("'#{rhost}':'#{rport}' - Failed to connect to the web server")
74
end
75
76
def report_cred(opts)
77
service_data = {
78
address: opts[:ip],
79
port: opts[:port],
80
service_name: opts[:service_name],
81
protocol: 'tcp',
82
workspace_id: myworkspace_id
83
}
84
85
credential_data = {
86
origin_type: :service,
87
module_fullname: fullname,
88
username: opts[:user],
89
private_data: opts[:password],
90
private_type: :password
91
}.merge(service_data)
92
93
login_data = {
94
core: create_credential(credential_data),
95
status: Metasploit::Model::Login::Status::UNTRIED,
96
proof: opts[:proof]
97
}.merge(service_data)
98
99
create_credential_login(login_data)
100
end
101
102
def do_login(user, pass)
103
vprint_status("Trying username:'#{user}' with password:'#{pass}'")
104
105
res = send_request_cgi({
106
'uri' => normalize_uri(target_uri.path, '_users/_all_docs'),
107
'method' => 'GET',
108
'ctype' => 'text/plain',
109
'authorization' => basic_auth(user, pass)
110
})
111
112
unless res
113
print_error('HTTP connection failed, aborting')
114
return :abort
115
end
116
117
return :skip_pass unless res.code == 200
118
119
print_good("#{peer} - Successful login with: '#{user}' : '#{pass}'")
120
121
report_cred(
122
ip: rhost,
123
port: rport,
124
service_name: 'couchdb',
125
user: user,
126
password: pass,
127
proof: res.code.to_s
128
)
129
130
:next_user
131
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ETIMEDOUT
132
print_error('HTTP connection failed, aborting')
133
return :abort
134
rescue => e
135
print_error("Error: #{e}")
136
return nil
137
end
138
end
139
140