# -*- coding: binary -*- ### # # This module provides methods for communicating with a host running oracle. # Dependencies: # - Oracle Instant Client # - ruby-oci8 # # Rory McCune # MC # ### require 'msf/core' module Msf module Exploit::ORACLE def initialize(info = {}) super register_options( [ OptString.new('RHOST', [ true, 'The Oracle host.', '']), OptString.new('RPORT', [ true, 'The TNS port.', '1521']), OptString.new('SID', [ true, 'The sid to authenticate with.', 'ORCL']), OptString.new('DBUSER', [ true, 'The username to authenticate with.', 'SCOTT']), OptString.new('DBPASS', [ true, 'The password to authenticate with.', 'TIGER']), ], Msf::Exploit::ORACLE ) begin olang = ENV['NLS_LANG'] ENV['NLS_LANG'] = 'AMERICAN_AMERICA.WE8ISO8859P1' require 'oci8' ENV['NLS_LANG'] = olang @oci8_loaded = true rescue ::Exception => e @oci8_loaded = false @oci8_error = e end end def check_dependencies if not @oci8_loaded print_error("Failed to load the OCI library: #{@oci8_error}") print_error("Try 'gem install ruby-oci8'") return false end return true end def connect handle = nil if(not @oci8_loaded) raise RuntimeError, "Could not load the Oracle driver (oci8): #{@oci8_error}" end # Create a Connection to the Database if datastore['DBUSER'] == 'SYS' || datastore['DBUSER'] == 'SYSTEM' begin handle = OCI8.new( datastore['DBUSER'], datastore['DBPASS'], "//#{datastore['RHOST']}:#{datastore['RPORT']}/#{datastore['SID']}", :SYSDBA ) rescue ::OCIError # Try again without a request for SYSDBA vprint_status('Insufficient privileges, trying without SYSDBA') handle = OCI8.new( datastore['DBUSER'], datastore['DBPASS'], "//#{datastore['RHOST']}:#{datastore['RPORT']}/#{datastore['SID']}" ) end else handle = OCI8.new( datastore['DBUSER'], datastore['DBPASS'], "//#{datastore['RHOST']}:#{datastore['RPORT']}/#{datastore['SID']}" ) end handle end def disconnect connect.logoff end def prepare_exec(sql) begin sploit = connect.parse(sql) rescue ::OCIError => e print_error("#{e.to_s}") return end # DEBUG # print_status("did the parse sploit type is " + sploit.type.to_s) begin sploit.exec rescue ::OCIError => e if ( e.to_s =~ /ORA-00942: table or view does not exist/ ) print_status("ORA-00942: table or view does not exist") raise RuntimeError, "ORA-00942: table or view does not exist" end print_status e.to_s end # The Handling is a little different for certain types of query # Mainly Select needs a fetch statement to get the data # Also return types are a little different (some return rows changed so we can used that) # The case statement could probably be collapsed a bit but leaving it as is for the moment # in case it's useful later... # Select Queries case sploit.type when 1, :select_stmt # Create an array to return to the calling function results = Array.new while r = sploit.fetch() str = r.join(',') # Removed this as it should really be down to the exploit to decide what to print # eg leaving this in messes up oraenum. # print_status(str) results << str end return results # Update Queries when 2, :update_stmt connect.commit # If we were successful our return should be a Integer with the number of rows updated result = ['UPDATE Successful ' + sploit.row_count.to_s + ' Rows Updated'] return result # Delete Queries when 3, :delete_stmt connect.commit # If we were successful our return should be a Integer with the number of rows updated result = ['DELETE Successful ' + sploit.row_count.to_s + ' Rows Deleted'] return result # Insert Queries when 4, :insert_stmt connect.commit # If we were successful our return should be a Integer with the number of rows updated result = ['INSERT Successful ' + sploit.row_count.to_s + ' Rows Inserted'] return result # Create Queries when 5, :create_stmt connect.commit if sploit print_status('CREATE successful') end when 6, :drop_stmt connect.commit if sploit print_status('DROP successful') end when 7, :alter_stmt connect.commit if sploit print_status('Alter successful') end when 8, :begin_stmt connect.commit when 9, :declare_stmt connect.commit else print_status("Didn't match Query Type!") print_status("Query type passed was " + sploit.type.to_s) end end end end