Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

oracle.rb 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # -*- coding: binary -*-
  2. ###
  3. #
  4. # This module provides methods for communicating with a host running oracle.
  5. # Dependencies:
  6. # - Oracle Instant Client
  7. # - ruby-oci8
  8. #
  9. # Rory McCune <rorym@nmrconsult.net>
  10. # MC <mc@metasploit.com>
  11. #
  12. ###
  13. require 'msf/core'
  14. module Msf
  15. module Exploit::ORACLE
  16. def initialize(info = {})
  17. super
  18. register_options(
  19. [
  20. OptString.new('RHOST', [ true, 'The Oracle host.', '']),
  21. OptString.new('RPORT', [ true, 'The TNS port.', '1521']),
  22. OptString.new('SID', [ true, 'The sid to authenticate with.', 'ORCL']),
  23. OptString.new('DBUSER', [ true, 'The username to authenticate with.', 'SCOTT']),
  24. OptString.new('DBPASS', [ true, 'The password to authenticate with.', 'TIGER']),
  25. ], Msf::Exploit::ORACLE
  26. )
  27. begin
  28. olang = ENV['NLS_LANG']
  29. ENV['NLS_LANG'] = 'AMERICAN_AMERICA.WE8ISO8859P1'
  30. require 'oci8'
  31. ENV['NLS_LANG'] = olang
  32. @oci8_loaded = true
  33. rescue ::Exception => e
  34. @oci8_loaded = false
  35. @oci8_error = e
  36. end
  37. end
  38. def check_dependencies
  39. if not @oci8_loaded
  40. print_error("Failed to load the OCI library: #{@oci8_error}")
  41. print_error("Try 'gem install ruby-oci8'")
  42. return false
  43. end
  44. return true
  45. end
  46. def connect
  47. handle = nil
  48. if(not @oci8_loaded)
  49. raise RuntimeError, "Could not load the Oracle driver (oci8): #{@oci8_error}"
  50. end
  51. # Create a Connection to the Database
  52. if datastore['DBUSER'] == 'SYS' || datastore['DBUSER'] == 'SYSTEM'
  53. begin
  54. handle = OCI8.new(
  55. datastore['DBUSER'],
  56. datastore['DBPASS'],
  57. "//#{datastore['RHOST']}:#{datastore['RPORT']}/#{datastore['SID']}",
  58. :SYSDBA
  59. )
  60. rescue ::OCIError
  61. # Try again without a request for SYSDBA
  62. vprint_status('Insufficient privileges, trying without SYSDBA')
  63. handle = OCI8.new(
  64. datastore['DBUSER'],
  65. datastore['DBPASS'],
  66. "//#{datastore['RHOST']}:#{datastore['RPORT']}/#{datastore['SID']}"
  67. )
  68. end
  69. else
  70. handle = OCI8.new(
  71. datastore['DBUSER'],
  72. datastore['DBPASS'],
  73. "//#{datastore['RHOST']}:#{datastore['RPORT']}/#{datastore['SID']}"
  74. )
  75. end
  76. handle
  77. end
  78. def disconnect
  79. connect.logoff
  80. end
  81. def prepare_exec(sql)
  82. begin
  83. sploit = connect.parse(sql)
  84. rescue ::OCIError => e
  85. print_error("#{e.to_s}")
  86. return
  87. end
  88. # DEBUG
  89. # print_status("did the parse sploit type is " + sploit.type.to_s)
  90. begin
  91. sploit.exec
  92. rescue ::OCIError => e
  93. if ( e.to_s =~ /ORA-00942: table or view does not exist/ )
  94. print_status("ORA-00942: table or view does not exist")
  95. raise RuntimeError, "ORA-00942: table or view does not exist"
  96. end
  97. print_status e.to_s
  98. end
  99. # The Handling is a little different for certain types of query
  100. # Mainly Select needs a fetch statement to get the data
  101. # Also return types are a little different (some return rows changed so we can used that)
  102. # The case statement could probably be collapsed a bit but leaving it as is for the moment
  103. # in case it's useful later...
  104. # Select Queries
  105. case sploit.type
  106. when 1, :select_stmt
  107. # Create an array to return to the calling function
  108. results = Array.new
  109. while r = sploit.fetch()
  110. str = r.join(',')
  111. # Removed this as it should really be down to the exploit to decide what to print
  112. # eg leaving this in messes up oraenum.
  113. # print_status(str)
  114. results << str
  115. end
  116. return results
  117. # Update Queries
  118. when 2, :update_stmt
  119. connect.commit
  120. # If we were successful our return should be a Fixnum with the number of rows updated
  121. result = ['UPDATE Successful ' + sploit.row_count.to_s + ' Rows Updated']
  122. return result
  123. # Delete Queries
  124. when 3, :delete_stmt
  125. connect.commit
  126. # If we were successful our return should be a Fixnum with the number of rows updated
  127. result = ['DELETE Successful ' + sploit.row_count.to_s + ' Rows Deleted']
  128. return result
  129. # Insert Queries
  130. when 4, :insert_stmt
  131. connect.commit
  132. # If we were successful our return should be a Fixnum with the number of rows updated
  133. result = ['INSERT Successful ' + sploit.row_count.to_s + ' Rows Inserted']
  134. return result
  135. # Create Queries
  136. when 5, :create_stmt
  137. connect.commit
  138. if sploit
  139. print_status('CREATE successful')
  140. end
  141. when 6, :drop_stmt
  142. connect.commit
  143. if sploit
  144. print_status('DROP successful')
  145. end
  146. when 7, :alter_stmt
  147. connect.commit
  148. if sploit
  149. print_status('Alter successful')
  150. end
  151. when 8, :begin_stmt
  152. connect.commit
  153. when 9, :declare_stmt
  154. connect.commit
  155. else
  156. print_status("Didn't match Query Type!")
  157. print_status("Query type passed was " + sploit.type.to_s)
  158. end
  159. end
  160. end
  161. end