Land #10357, CouchDB improvements and docs
parent
3fbd4f8f2f
commit
68272c410e
|
@ -0,0 +1,73 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Apache CouchDB is a nosql database server which communicates over HTTP. This module will enumerate the server and databases hosted on it.
|
||||
|
||||
The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https://www.1and1.com/cloud-community/learn/database/couchdb/install-and-use-couchdb-on-ubuntu-1604/):
|
||||
|
||||
1. `sudo apt install software-properties-common`
|
||||
2. `sudo add-apt-repository ppa:couchdb/stable`
|
||||
3. `sudo apt update`
|
||||
4. `sudo apt install couchdb`
|
||||
5. Reconfigure couchdb to listen to all interfaces. Edit `/etc/couchdb/local.ini`. Under `[httpd]` add the following line: `bind_address = 0.0.0.0`
|
||||
6. Restart the service: `sudo service couchdb restart`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install and configure couchdb
|
||||
2. Start msfconsole
|
||||
3. Do: `auxiliary/scanner/couchdb/couchdb_enum`
|
||||
4. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
**serverinfo**
|
||||
|
||||
If set to true, the server info will also enumerated and set in msf's DB. Defaults to `false`
|
||||
|
||||
## Scenarios
|
||||
|
||||
A run against the configuration from these docs
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/afp/afp_login) > use auxiliary/scanner/couchdb/couchdb_enum
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > run
|
||||
|
||||
[+] 1.1.1.1:5984 {
|
||||
"couchdb": "Welcome",
|
||||
"uuid": "6f08e89795bd845efc6c2bf3d57799e5",
|
||||
"version": "1.6.1",
|
||||
"vendor": {
|
||||
"version": "16.04",
|
||||
"name": "Ubuntu"
|
||||
}
|
||||
}
|
||||
[*] #{peer} Enumerating Databases...
|
||||
[+] 1.1.1.1:5984 Databases:
|
||||
|
||||
[
|
||||
"_replicator",
|
||||
"_users"
|
||||
]
|
||||
|
||||
[+] 1.1.1.1:5984 File saved in: /root/.msf4/loot/20180721105522_default_1.1.1.1_couchdb.enum_888970.bin
|
||||
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > services
|
||||
Services
|
||||
========
|
||||
|
||||
host port proto name state info
|
||||
---- ---- ----- ---- ----- ----
|
||||
1.1.1.1 5984 tcp couchdb open HTTP/1.1 200 OK
|
||||
Server: CouchDB/1.6.1 (Erlang OTP/18)
|
||||
Date: Sat, 21 Jul 2018 14:54:45 GMT
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Length: 127
|
||||
Cache-Control: must-revalidate
|
||||
|
||||
{"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}}
|
||||
|
||||
```
|
|
@ -0,0 +1,51 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Apache CouchDB is a nosql database server which communicates over HTTP. This module will enumerate the server and databases hosted on it.
|
||||
|
||||
The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https://www.1and1.com/cloud-community/learn/database/couchdb/install-and-use-couchdb-on-ubuntu-1604/):
|
||||
|
||||
1. `sudo apt install software-properties-common`
|
||||
2. `sudo add-apt-repository ppa:couchdb/stable`
|
||||
3. `sudo apt update`
|
||||
4. `sudo apt install couchdb`
|
||||
5. Reconfigure couchdb to listen to all interfaces. Edit `/etc/couchdb/local.ini`. Under `[httpd]` add the following line: `bind_address = 0.0.0.0`
|
||||
6. Restart the service: `sudo service couchdb restart`
|
||||
7. Create an admin user `curl -X PUT http://127.0.0.1:5984/_config/admins/anna -d '"secret"'`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install and configure couchdb
|
||||
2. Start msfconsole
|
||||
3. Do: `auxiliary/scanner/couchdb/couchdb_login`
|
||||
4. Do: `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
A run against the configuration from these docs
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/couchdb/couchdb_login
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > set username anna
|
||||
username => anna
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > set password secret
|
||||
password => secret
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > run
|
||||
|
||||
[*] 1.1.1.1:5984 - [001/305] - Trying username:'connect' with password:'connect'
|
||||
[*] 1.1.1.1:5984 - [002/305] - Trying username:'sitecom' with password:'sitecom'
|
||||
[*] 1.1.1.1:5984 - [003/305] - Trying username:'admin' with password:'1234'
|
||||
[*] 1.1.1.1:5984 - [004/305] - Trying username:'cisco' with password:'cisco'
|
||||
[*] 1.1.1.1:5984 - [005/305] - Trying username:'cisco' with password:'sanfran'
|
||||
[*] 1.1.1.1:5984 - [006/305] - Trying username:'private' with password:'private'
|
||||
[*] 1.1.1.1:5984 - [007/305] - Trying username:'wampp' with password:'xampp'
|
||||
[*] 1.1.1.1:5984 - [008/305] - Trying username:'newuser' with password:'wampp'
|
||||
[*] 1.1.1.1:5984 - [009/305] - Trying username:'xampp-dav-unsecure' with password:'ppmax2011'
|
||||
[*] 1.1.1.1:5984 - [010/305] - Trying username:'admin' with password:'turnkey'
|
||||
[*] 1.1.1.1:5984 - [011/305] - Trying username:'vagrant' with password:'vagrant'
|
||||
[*] 1.1.1.1:5984 - [012/305] - Trying username:'anna' with password:'secret'
|
||||
[+] 1.1.1.1:5984 - Successful login with. 'anna' : 'secret'
|
||||
[*] 1.1.1.1:5984 - [013/305] - Trying username:'admin' with password:'secret'
|
||||
...snip...
|
||||
```
|
|
@ -26,16 +26,17 @@ class MetasploitModule < Msf::Auxiliary
|
|||
[
|
||||
Opt::RPORT(5984),
|
||||
OptString.new('TARGETURI', [true, 'Path to list all the databases', '/_all_dbs']),
|
||||
OptBool.new('SERVERINFO', [true, 'Print server info']),
|
||||
OptString.new('HttpUsername', [false, 'The username to login as']),
|
||||
OptString.new('HttpPassword', [false, 'The password to login with'])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
username = datastore['HttpUsername']
|
||||
password = datastore['HttpPassword']
|
||||
auth = basic_auth(username, password) if username && password
|
||||
def valid_response(res)
|
||||
return res.code == 200 && res.headers['Server'].include?('CouchDB')
|
||||
end
|
||||
|
||||
def get_dbs(auth)
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path),
|
||||
|
@ -45,26 +46,66 @@ class MetasploitModule < Msf::Auxiliary
|
|||
|
||||
temp = JSON.parse(res.body)
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, JSON::ParserError => e
|
||||
print_error("The following Error was encountered: #{e.class}")
|
||||
print_error("#{peer} The following Error was encountered: #{e.class}")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 200 && res.headers['Server'].include?('CouchDB')
|
||||
print_status('Enumerating...')
|
||||
if valid_response(res)
|
||||
print_status("#{peer} Enumerating Databases...")
|
||||
results = JSON.pretty_generate(temp)
|
||||
print_good("Found:\n\n#{results}\n")
|
||||
print_good("#{peer} Databases:\n\n#{results}\n")
|
||||
|
||||
path = store_loot(
|
||||
'couchdb.enum',
|
||||
'text/plain',
|
||||
'application/json',
|
||||
rhost,
|
||||
results,
|
||||
'CouchDB Enum'
|
||||
'CouchDB Databases'
|
||||
)
|
||||
|
||||
print_good("File saved in: #{path}")
|
||||
print_good("#{peer} File saved in: #{path}")
|
||||
else
|
||||
print_error("Unable to enum, received \"#{res.code}\"")
|
||||
print_error("#{peer} Unable to enum, received \"#{res.code}\"")
|
||||
end
|
||||
end
|
||||
|
||||
def get_server_info(auth)
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
'uri' => '/',
|
||||
'method' => 'GET',
|
||||
'authorization' => auth
|
||||
)
|
||||
|
||||
temp = JSON.parse(res.body)
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, JSON::ParserError => e
|
||||
print_error("#{peer} The following Error was encountered: #{e.class}")
|
||||
return
|
||||
end
|
||||
|
||||
if valid_response(res)
|
||||
# Example response: {"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}}
|
||||
|
||||
print_good("#{peer} #{JSON.pretty_generate(temp)}")
|
||||
report_service(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
name: 'couchdb',
|
||||
proto: 'tcp',
|
||||
info: res
|
||||
)
|
||||
else
|
||||
print_error("#{peer} Unable to enum, received \"#{res.code}\"")
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
username = datastore['HttpUsername']
|
||||
password = datastore['HttpPassword']
|
||||
auth = basic_auth(username, password) if username && password
|
||||
if datastore['SERVERINFO']
|
||||
get_server_info(auth)
|
||||
end
|
||||
get_dbs(auth)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue