Skip to content

Commit 5e997aa

Browse files
committed
Landing rapid7#1816 - lists essential information about CouchDB
2 parents e338443 + cba045a commit 5e997aa

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'msf/core'
9+
10+
class Metasploit3 < Msf::Auxiliary
11+
12+
include Msf::Exploit::Remote::HttpClient
13+
include Msf::Auxiliary::Report
14+
15+
def initialize(info = {})
16+
super(update_info(info,
17+
'Name' => 'CouchDB Enum Utility',
18+
'Description' => %q{
19+
Send a "send_request_cgi()" to enumerate databases and your values on CouchDB (Without authentication by default)
20+
},
21+
'Author' => [ 'espreto <robertoespreto[at]gmail.com>' ],
22+
'License' => MSF_LICENSE
23+
))
24+
25+
register_options(
26+
[
27+
Opt::RPORT(5984),
28+
OptString.new('TARGETURI', [true, 'Path to list all the databases', '/_all_dbs']),
29+
OptEnum.new('HTTP_METHOD', [true, 'HTTP Method, default GET', 'GET', ['GET', 'POST', 'PUT', 'DELETE'] ]),
30+
OptString.new('USERNAME', [false, 'The username to login as']),
31+
OptString.new('PASSWORD', [false, 'The password to login with'])
32+
], self.class)
33+
end
34+
35+
def run
36+
username = datastore['USERNAME']
37+
password = datastore['PASSWORD']
38+
39+
uri = normalize_uri(target_uri.path)
40+
res = send_request_cgi({
41+
'uri' => uri,
42+
'method' => datastore['HTTP_METHOD'],
43+
'authorization' => basic_auth(username, password),
44+
'headers' => {
45+
'Cookie' => 'Whatever?'
46+
}
47+
})
48+
49+
if res.nil?
50+
print_error("No response for #{target_host}")
51+
return nil
52+
end
53+
54+
begin
55+
temp = JSON.parse(res.body)
56+
rescue JSON::ParserError
57+
print_error("Unable to parse JSON")
58+
return
59+
end
60+
61+
results = JSON.pretty_generate(temp)
62+
63+
if (res.code == 200)
64+
print_good("#{target_host}:#{rport} -> #{res.code}")
65+
print_good("Response Headers:\n\n #{res.headers}")
66+
print_good("Response Body:\n\n #{results}\n")
67+
elsif (res.code == 403) # Forbidden
68+
print_error("Received #{res.code} - Forbidden to #{target_host}:#{rport}")
69+
print_error("Response from server:\n\n #{results}\n")
70+
elsif (res.code == 404) # Not Found
71+
print_error("Received #{res.code} - Not Found to #{target_host}:#{rport}")
72+
print_error("Response from server:\n\n #{results}\n")
73+
else
74+
print_status("Received #{res.code}")
75+
print_line("#{results}")
76+
end
77+
78+
if res and res.code == 200 and res.headers['Content-Type'] and res.body.length > 0
79+
path = store_loot("couchdb.enum.file", "text/plain", rhost, res.body, "CouchDB Enum Results")
80+
print_status("Results saved to #{path}")
81+
else
82+
print_error("Failed to save the result")
83+
end
84+
end
85+
end

0 commit comments

Comments
 (0)